build: Allow &pathconfig XML entities to be used in all manpages, not just smb.conf
[bbaumbach/samba-autobuild/.git] / buildtools / wafsamba / wafsamba.py
1 # a waf tool to add autoconf-like macros to the configure section
2 # and for SAMBA_ macros for building libraries, binaries etc
3
4 import os, sys, re, shutil, fnmatch
5 from waflib import Build, Options, Task, Utils, TaskGen, Logs, Context, Errors
6 from waflib.Configure import conf
7 from waflib.Logs import debug
8 from samba_utils import SUBST_VARS_RECURSIVE
9 TaskGen.task_gen.apply_verif = Utils.nada
10
11 # bring in the other samba modules
12 from samba_utils import *
13 from samba_utils import symlink
14 from samba_version import *
15 from samba_autoconf import *
16 from samba_patterns import *
17 from samba_pidl import *
18 from samba_autoproto import *
19 from samba_python import *
20 from samba_perl import *
21 from samba_deps import *
22 from samba_bundled import *
23 from samba_third_party import *
24 import samba_cross
25 import samba_install
26 import samba_conftests
27 import samba_abi
28 import samba_headers
29 import generic_cc
30 import samba_dist
31 import samba_wildcard
32 import symbols
33 import pkgconfig
34 import configure_file
35 import samba_waf18
36
37 LIB_PATH="shared"
38
39 os.environ['PYTHONUNBUFFERED'] = '1'
40
41 if Context.HEXVERSION not in (0x2001800,):
42     Logs.error('''
43 Please use the version of waf that comes with Samba, not
44 a system installed version. See http://wiki.samba.org/index.php/Waf
45 for details.
46
47 Alternatively, please run ./configure and make as usual. That will
48 call the right version of waf.''')
49     sys.exit(1)
50
51 @conf
52 def SAMBA_BUILD_ENV(conf):
53     '''create the samba build environment'''
54     conf.env.BUILD_DIRECTORY = conf.bldnode.abspath()
55     mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, LIB_PATH))
56     mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, LIB_PATH, "private"))
57     mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, "modules"))
58     mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, "plugins"))
59     mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, 'python/samba/dcerpc'))
60     # this allows all of the bin/shared and bin/python targets
61     # to be expressed in terms of build directory paths
62     mkdir_p(os.path.join(conf.env.BUILD_DIRECTORY, 'default'))
63     for (source, target) in [('shared', 'shared'), ('modules', 'modules'), ('plugins', 'plugins'), ('python', 'python')]:
64         link_target = os.path.join(conf.env.BUILD_DIRECTORY, 'default/' + target)
65         if not os.path.lexists(link_target):
66             symlink('../' + source, link_target)
67
68     # get perl to put the blib files in the build directory
69     blib_bld = os.path.join(conf.env.BUILD_DIRECTORY, 'default/pidl/blib')
70     blib_src = os.path.join(conf.srcnode.abspath(), 'pidl/blib')
71     mkdir_p(blib_bld + '/man1')
72     mkdir_p(blib_bld + '/man3')
73     if os.path.islink(blib_src):
74         os.unlink(blib_src)
75     elif os.path.exists(blib_src):
76         shutil.rmtree(blib_src)
77
78
79 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
80     '''add an init_function to the list for a subsystem'''
81     if init_function is None:
82         return
83     bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
84     cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
85     if not subsystem in cache:
86         cache[subsystem] = []
87     cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
88 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
89
90
91 def generate_empty_file(task):
92     task.outputs[0].write('')
93     return 0
94
95 #################################################################
96 def SAMBA_LIBRARY(bld, libname, source,
97                   deps='',
98                   public_deps='',
99                   includes='',
100                   public_headers=None,
101                   public_headers_install=True,
102                   private_headers=None,
103                   header_path=None,
104                   pc_files=None,
105                   vnum=None,
106                   soname=None,
107                   cflags='',
108                   cflags_end=None,
109                   ldflags='',
110                   external_library=False,
111                   realname=None,
112                   keep_underscore=False,
113                   autoproto=None,
114                   autoproto_extra_source='',
115                   group='main',
116                   depends_on='',
117                   local_include=True,
118                   global_include=True,
119                   vars=None,
120                   subdir=None,
121                   install_path=None,
122                   install=True,
123                   pyembed=False,
124                   pyext=False,
125                   target_type='LIBRARY',
126                   bundled_name=None,
127                   link_name=None,
128                   abi_directory=None,
129                   abi_match=None,
130                   orig_vscript_map=None,
131                   hide_symbols=False,
132                   manpages=None,
133                   private_library=False,
134                   grouping_library=False,
135                   require_builtin_deps=False,
136                   provide_builtin_linking=False,
137                   builtin_cflags='',
138                   allow_undefined_symbols=False,
139                   allow_warnings=False,
140                   enabled=True):
141     '''define a Samba library'''
142
143     # We support:
144     # - LIBRARY: this can be use to link via -llibname
145     # - MODULE:  this is module from SAMBA_MODULE()
146     # - PLUGIN:  this is plugin for external consumers to be
147     #            loaded via dlopen()
148     # - PYTHON:  a python C binding library
149     #
150     if target_type not in ['LIBRARY', 'MODULE', 'PLUGIN', 'PYTHON']:
151         raise Errors.WafError("target_type[%s] not supported in SAMBA_LIBRARY('%s')" %
152                               (target_type, libname))
153
154     if require_builtin_deps:
155         # For now we only support require_builtin_deps only for libraries, plugins
156         if target_type not in ['LIBRARY', 'PLUGIN']:
157             raise Errors.WafError("target_type[%s] not supported SAMBA_LIBRARY('%s', require_builtin_deps=True)" %
158                                   (target_type, libname))
159
160     if private_library and public_headers:
161         raise Errors.WafError("private library '%s' must not have public header files" %
162                              libname)
163
164     if orig_vscript_map and not private_library:
165         raise Errors.WafError("public library '%s' must not have orig_vscript_map" %
166                              libname)
167
168     if orig_vscript_map and abi_directory:
169         raise Errors.WafError("private library '%s' with orig_vscript_map must not have abi_directory" %
170                              libname)
171     if orig_vscript_map and abi_match:
172         raise Errors.WafError("private library '%s' with orig_vscript_map must not have abi_match" %
173                              libname)
174
175     if LIB_MUST_BE_PRIVATE(bld, libname) and target_type not in ['PLUGIN']:
176         private_library = True
177
178     if not enabled:
179         SET_TARGET_TYPE(bld, libname, 'DISABLED')
180         return
181
182     source = bld.EXPAND_VARIABLES(source, vars=vars)
183     if subdir:
184         source = bld.SUBDIR(subdir, source)
185
186     # remember empty libraries, so we can strip the dependencies
187     if ((source == '') or (source == [])):
188         if deps == '' and public_deps == '':
189             SET_TARGET_TYPE(bld, libname, 'EMPTY')
190             return
191         empty_c = libname + '.empty.c'
192         bld.SAMBA_GENERATOR('%s_empty_c' % libname,
193                             rule=generate_empty_file,
194                             target=empty_c)
195         source=empty_c
196
197     samba_deps = deps + ' ' + public_deps
198     samba_deps = TO_LIST(samba_deps)
199
200     if BUILTIN_LIBRARY(bld, libname):
201         builtin_target = libname + '.builtin.objlist'
202         builtin_cflags_end = '-D_PUBLIC_=_PRIVATE_'
203         empty_target = libname
204         obj_target = None
205     else:
206         if provide_builtin_linking:
207             builtin_target = libname + '.builtin.objlist'
208             builtin_cflags_end = '-D_PUBLIC_=_PRIVATE_'
209         else:
210             builtin_target = None
211         empty_target = None
212         obj_target = libname + '.objlist'
213         if require_builtin_deps:
214             # hide the builtin deps from the callers
215             samba_deps = TO_LIST('')
216         dep_target = obj_target
217
218     if group == 'libraries':
219         subsystem_group = 'main'
220     else:
221         subsystem_group = group
222
223     # first create a target for building the object files for this library
224     # by separating in this way, we avoid recompiling the C files
225     # separately for the install library and the build library
226     if builtin_target:
227         __t = __SAMBA_SUBSYSTEM_BUILTIN(bld, builtin_target, source,
228                                         deps=deps,
229                                         public_deps=public_deps,
230                                         includes=includes,
231                                         header_path=header_path,
232                                         builtin_cflags=builtin_cflags,
233                                         builtin_cflags_end=builtin_cflags_end,
234                                         group=group,
235                                         depends_on=depends_on,
236                                         local_include=local_include,
237                                         global_include=global_include,
238                                         allow_warnings=allow_warnings)
239         builtin_subsystem = __t
240     else:
241         builtin_subsystem = None
242     if obj_target:
243         bld.SAMBA_SUBSYSTEM(obj_target,
244                             source         = source,
245                             deps           = deps,
246                             public_deps    = public_deps,
247                             includes       = includes,
248                             public_headers = public_headers,
249                             public_headers_install = public_headers_install,
250                             private_headers= private_headers,
251                             header_path    = header_path,
252                             cflags         = cflags,
253                             cflags_end     = cflags_end,
254                             group          = subsystem_group,
255                             autoproto      = autoproto,
256                             autoproto_extra_source=autoproto_extra_source,
257                             depends_on     = depends_on,
258                             hide_symbols   = hide_symbols,
259                             allow_warnings = allow_warnings,
260                             pyembed        = pyembed,
261                             pyext          = pyext,
262                             local_include  = local_include,
263                             __require_builtin_deps=require_builtin_deps,
264                             global_include = global_include)
265     else:
266         et = bld.SAMBA_SUBSYSTEM(empty_target,
267                                  source=[],
268                                  __force_empty=True,
269                                  __require_builtin_deps=True)
270         et.samba_builtin_subsystem = builtin_subsystem
271
272     if BUILTIN_LIBRARY(bld, libname):
273         return
274
275     if not SET_TARGET_TYPE(bld, libname, target_type):
276         return
277
278     # the library itself will depend on that object target
279     samba_deps.append(dep_target)
280
281     realname = bld.map_shlib_extension(realname, python=(target_type=='PYTHON'))
282     link_name = bld.map_shlib_extension(link_name, python=(target_type=='PYTHON'))
283
284     # we don't want any public libraries without version numbers
285     if (not private_library and target_type != 'PYTHON' and not realname):
286         if vnum is None and soname is None:
287             raise Errors.WafError("public library '%s' must have a vnum" %
288                     libname)
289         if pc_files is None:
290             raise Errors.WafError("public library '%s' must have pkg-config file" %
291                        libname)
292         if public_headers is None:
293             raise Errors.WafError("public library '%s' must have header files" %
294                        libname)
295
296     abi_vnum = vnum
297
298     if bundled_name is not None:
299         pass
300     elif target_type == 'PYTHON' or realname or not private_library:
301         if keep_underscore:
302             bundled_name = libname
303         else:
304             bundled_name = libname.replace('_', '-')
305     else:
306         assert (private_library == True and realname is None)
307         bundled_name = PRIVATE_NAME(bld, libname.replace('_', '-'))
308         vnum = None
309
310     ldflags = TO_LIST(ldflags)
311     if bld.env['ENABLE_RELRO'] is True:
312         ldflags.extend(TO_LIST('-Wl,-z,relro,-z,now'))
313
314     features = 'c cshlib symlink_lib install_lib'
315     if pyext:
316         features += ' pyext'
317     if pyembed:
318         features += ' pyembed'
319
320     if abi_directory:
321         features += ' abi_check'
322
323     if pyembed and bld.env['PYTHON_SO_ABI_FLAG']:
324         # For ABI checking, we don't care about the Python version.
325         # Remove the Python ABI tag (e.g. ".cpython-35m")
326         abi_flag = bld.env['PYTHON_SO_ABI_FLAG']
327         replacement = ''
328         version_libname = libname.replace(abi_flag, replacement)
329     else:
330         version_libname = libname
331
332     vscript = None
333     if bld.env.HAVE_LD_VERSION_SCRIPT:
334         if private_library:
335             version = bld.env.PRIVATE_VERSION
336         elif vnum:
337             version = "%s_%s" % (libname, vnum)
338         else:
339             version = None
340         if version:
341             vscript = "%s.vscript" % libname
342             if orig_vscript_map:
343                 bld.VSCRIPT_MAP_PRIVATE(version_libname, orig_vscript_map, version, vscript)
344             else:
345                 bld.ABI_VSCRIPT(version_libname, abi_directory, version, vscript,
346                                 abi_match, private_library)
347             fullname = apply_pattern(bundled_name, bld.env.cshlib_PATTERN)
348             fullpath = bld.path.find_or_declare(fullname)
349             vscriptpath = bld.path.find_or_declare(vscript)
350             if not fullpath:
351                 raise Errors.WafError("unable to find fullpath for %s" % fullname)
352             if not vscriptpath:
353                 raise Errors.WafError("unable to find vscript path for %s" % vscript)
354             bld.add_manual_dependency(fullpath, vscriptpath)
355             if bld.is_install:
356                 # also make the .inst file depend on the vscript
357                 instname = apply_pattern(bundled_name + '.inst', bld.env.cshlib_PATTERN)
358                 bld.add_manual_dependency(bld.path.find_or_declare(instname), bld.path.find_or_declare(vscript))
359             vscript = os.path.join(bld.path.abspath(bld.env), vscript)
360
361     bld.SET_BUILD_GROUP(group)
362     t = bld(
363         features        = features,
364         source          = [],
365         target          = bundled_name,
366         depends_on      = depends_on,
367         samba_ldflags   = ldflags,
368         samba_deps      = samba_deps,
369         samba_includes  = includes,
370         version_script  = vscript,
371         version_libname = version_libname,
372         local_include   = local_include,
373         global_include  = global_include,
374         vnum            = vnum,
375         soname          = soname,
376         install_path    = None,
377         samba_inst_path = install_path,
378         name            = libname,
379         samba_realname  = realname,
380         samba_install   = install,
381         abi_directory   = "%s/%s" % (bld.path.abspath(), abi_directory),
382         abi_match       = abi_match,
383         abi_vnum        = abi_vnum,
384         private_library = private_library,
385         grouping_library=grouping_library,
386         allow_undefined_symbols=allow_undefined_symbols,
387         samba_require_builtin_deps=False,
388         samba_builtin_subsystem=builtin_subsystem,
389         )
390
391     if realname and not link_name:
392         link_name = 'shared/%s' % realname
393
394     if link_name:
395         if 'waflib.extras.compat15' in sys.modules:
396             link_name = 'default/' + link_name
397         t.link_name = link_name
398
399     if pc_files is not None and not private_library:
400         if pyembed:
401             bld.PKG_CONFIG_FILES(pc_files, vnum=vnum, extra_name=bld.env['PYTHON_SO_ABI_FLAG'])
402         else:
403             bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
404
405     if (manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and
406         bld.env['XSLTPROC_MANPAGES']):
407         bld.MANPAGES(manpages, install)
408
409
410 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
411
412
413 #################################################################
414 def SAMBA_BINARY(bld, binname, source,
415                  deps='',
416                  includes='',
417                  public_headers=None,
418                  private_headers=None,
419                  header_path=None,
420                  modules=None,
421                  ldflags=None,
422                  cflags='',
423                  cflags_end=None,
424                  autoproto=None,
425                  use_hostcc=False,
426                  use_global_deps=True,
427                  compiler=None,
428                  group='main',
429                  manpages=None,
430                  local_include=True,
431                  global_include=True,
432                  subsystem_name=None,
433                  allow_warnings=False,
434                  pyembed=False,
435                  vars=None,
436                  subdir=None,
437                  install=True,
438                  install_path=None,
439                  enabled=True,
440                  fuzzer=False,
441                  for_selftest=False):
442     '''define a Samba binary'''
443
444     if for_selftest:
445         install=False
446         if not bld.CONFIG_GET('ENABLE_SELFTEST'):
447             enabled=False
448
449     if not enabled:
450         SET_TARGET_TYPE(bld, binname, 'DISABLED')
451         return
452
453     # Fuzzing builds do not build normal binaries
454     # however we must build asn1compile etc
455
456     if not use_hostcc and bld.env.enable_fuzzing != fuzzer:
457         SET_TARGET_TYPE(bld, binname, 'DISABLED')
458         return
459
460     if fuzzer:
461         install = False
462         if ldflags is None:
463             ldflags = bld.env['FUZZ_TARGET_LDFLAGS']
464
465     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
466         return
467
468     features = 'c cprogram symlink_bin install_bin'
469     if pyembed:
470         features += ' pyembed'
471
472     obj_target = binname + '.objlist'
473
474     source = bld.EXPAND_VARIABLES(source, vars=vars)
475     if subdir:
476         source = bld.SUBDIR(subdir, source)
477     source = unique_list(TO_LIST(source))
478
479     if group == 'binaries':
480         subsystem_group = 'main'
481     elif group == 'build_compilers':
482         subsystem_group = 'compiler_libraries'
483     else:
484         subsystem_group = group
485
486     # only specify PIE flags for binaries
487     pie_cflags = TO_LIST(cflags)
488     pie_ldflags = TO_LIST(ldflags)
489     if bld.env['ENABLE_PIE'] is True:
490         pie_cflags.extend(TO_LIST('-fPIE'))
491         pie_ldflags.extend(TO_LIST('-pie'))
492     if bld.env['ENABLE_RELRO'] is True:
493         pie_ldflags.extend(TO_LIST('-Wl,-z,relro,-z,now'))
494
495     # first create a target for building the object files for this binary
496     # by separating in this way, we avoid recompiling the C files
497     # separately for the install binary and the build binary
498     bld.SAMBA_SUBSYSTEM(obj_target,
499                         source         = source,
500                         deps           = deps,
501                         includes       = includes,
502                         cflags         = pie_cflags,
503                         cflags_end     = cflags_end,
504                         group          = subsystem_group,
505                         autoproto      = autoproto,
506                         subsystem_name = subsystem_name,
507                         local_include  = local_include,
508                         global_include = global_include,
509                         use_hostcc     = use_hostcc,
510                         pyext          = pyembed,
511                         allow_warnings = allow_warnings,
512                         use_global_deps= use_global_deps)
513
514     bld.SET_BUILD_GROUP(group)
515
516     # the binary itself will depend on that object target
517     deps = TO_LIST(deps)
518     deps.append(obj_target)
519
520     t = bld(
521         features       = features,
522         source         = [],
523         target         = binname,
524         samba_deps     = deps,
525         samba_includes = includes,
526         local_include  = local_include,
527         global_include = global_include,
528         samba_modules  = modules,
529         top            = True,
530         samba_subsystem= subsystem_name,
531         install_path   = None,
532         samba_inst_path= install_path,
533         samba_install  = install,
534         samba_ldflags  = pie_ldflags
535         )
536
537     if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
538         bld.MANPAGES(manpages, install)
539
540 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
541
542
543 #################################################################
544 def SAMBA_MODULE(bld, modname, source,
545                  deps='',
546                  includes='',
547                  subsystem=None,
548                  init_function=None,
549                  module_init_name='samba_init_module',
550                  autoproto=None,
551                  autoproto_extra_source='',
552                  cflags='',
553                  cflags_end=None,
554                  internal_module=True,
555                  local_include=True,
556                  global_include=True,
557                  vars=None,
558                  subdir=None,
559                  enabled=True,
560                  pyembed=False,
561                  manpages=None,
562                  allow_undefined_symbols=False,
563                  allow_warnings=False,
564                  install=True
565                  ):
566     '''define a Samba module.'''
567
568     bld.ASSERT(subsystem, "You must specify a subsystem for SAMBA_MODULE(%s)" % modname)
569
570     source = bld.EXPAND_VARIABLES(source, vars=vars)
571     if subdir:
572         source = bld.SUBDIR(subdir, source)
573
574     if internal_module or BUILTIN_LIBRARY(bld, modname):
575         # Do not create modules for disabled subsystems
576         if GET_TARGET_TYPE(bld, subsystem) == 'DISABLED':
577             return
578         bld.SAMBA_SUBSYSTEM(modname, source,
579                     deps=deps,
580                     includes=includes,
581                     autoproto=autoproto,
582                     autoproto_extra_source=autoproto_extra_source,
583                     cflags=cflags,
584                     cflags_end=cflags_end,
585                     local_include=local_include,
586                     global_include=global_include,
587                     allow_warnings=allow_warnings,
588                     enabled=enabled)
589
590         bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
591         return
592
593     if not enabled:
594         SET_TARGET_TYPE(bld, modname, 'DISABLED')
595         return
596
597     # Do not create modules for disabled subsystems
598     if GET_TARGET_TYPE(bld, subsystem) == 'DISABLED':
599         return
600
601     realname = modname
602     deps += ' ' + subsystem
603     while realname.startswith("lib"+subsystem+"_"):
604         realname = realname[len("lib"+subsystem+"_"):]
605     while realname.startswith(subsystem+"_"):
606         realname = realname[len(subsystem+"_"):]
607
608     build_name = "%s_module_%s" % (subsystem, realname)
609
610     realname = bld.make_libname(realname)
611     while realname.startswith("lib"):
612         realname = realname[len("lib"):]
613
614     build_link_name = "modules/%s/%s" % (subsystem, realname)
615
616     if init_function:
617         cflags += " -D%s=%s" % (init_function, module_init_name)
618
619     bld.SAMBA_LIBRARY(modname,
620                       source,
621                       deps=deps,
622                       includes=includes,
623                       cflags=cflags,
624                       cflags_end=cflags_end,
625                       realname = realname,
626                       autoproto = autoproto,
627                       local_include=local_include,
628                       global_include=global_include,
629                       vars=vars,
630                       bundled_name=build_name,
631                       link_name=build_link_name,
632                       install_path="${MODULESDIR}/%s" % subsystem,
633                       pyembed=pyembed,
634                       manpages=manpages,
635                       allow_undefined_symbols=allow_undefined_symbols,
636                       allow_warnings=allow_warnings,
637                       private_library=True,
638                       install=install
639                       )
640
641
642 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
643
644 #################################################################
645 def SAMBA_PLUGIN(bld, pluginname, source,
646                  deps='',
647                  includes='',
648                  vnum=None,
649                  soname=None,
650                  cflags='',
651                  ldflags='',
652                  local_include=True,
653                  global_include=True,
654                  vars=None,
655                  subdir=None,
656                  realname=None,
657                  keep_underscore=False,
658                  autoproto=None,
659                  autoproto_extra_source='',
660                  install_path=None,
661                  install=True,
662                  manpages=None,
663                  require_builtin_deps=True,
664                  allow_undefined_symbols=False,
665                  enabled=True):
666     '''define an external plugin.'''
667
668     bld.ASSERT(realname, "You must specify a realname for SAMBA_PLUGIN(%s)" % pluginname)
669
670     source = bld.EXPAND_VARIABLES(source, vars=vars)
671     if subdir:
672         source = bld.SUBDIR(subdir, source)
673
674     build_name = "_plugin_%s" % (pluginname)
675     build_link_name = "plugins/%s" % (realname)
676
677     bld.SAMBA_LIBRARY(pluginname,
678                       source,
679                       bundled_name=build_name,
680                       link_name=build_link_name,
681                       target_type='PLUGIN',
682                       deps=deps,
683                       includes=includes,
684                       vnum=vnum,
685                       soname=soname,
686                       cflags=cflags,
687                       ldflags=ldflags,
688                       realname=realname,
689                       autoproto=autoproto,
690                       autoproto_extra_source=autoproto_extra_source,
691                       local_include=local_include,
692                       global_include=global_include,
693                       vars=vars,
694                       group='main',
695                       install_path=install_path,
696                       install=install,
697                       manpages=manpages,
698                       require_builtin_deps=require_builtin_deps,
699                       builtin_cflags=cflags,
700                       hide_symbols=True,
701                       public_headers=[],
702                       public_headers_install=False,
703                       pc_files=[],
704                       allow_undefined_symbols=allow_undefined_symbols,
705                       allow_warnings=False,
706                       enabled=enabled)
707 Build.BuildContext.SAMBA_PLUGIN = SAMBA_PLUGIN
708
709 def __SAMBA_SUBSYSTEM_BUILTIN(bld, builtin_target, source,
710                               deps='',
711                               public_deps='',
712                               includes='',
713                               public_headers=None,
714                               public_headers_install=True,
715                               private_headers=None,
716                               header_path=None,
717                               builtin_cflags='',
718                               builtin_cflags_end=None,
719                               group='main',
720                               autoproto=None,
721                               autoproto_extra_source='',
722                               depends_on='',
723                               local_include=True,
724                               global_include=True,
725                               allow_warnings=False):
726
727     bld.ASSERT(builtin_target.endswith('.builtin.objlist'),
728                "builtin_target[%s] does not end with '.builtin.objlist'" %
729                (builtin_target))
730     return bld.SAMBA_SUBSYSTEM(builtin_target, source,
731                                deps=deps,
732                                public_deps=public_deps,
733                                includes=includes,
734                                public_headers=public_headers,
735                                public_headers_install=public_headers_install,
736                                private_headers=private_headers,
737                                header_path=header_path,
738                                cflags=builtin_cflags,
739                                cflags_end=builtin_cflags_end,
740                                hide_symbols=True,
741                                group=group,
742                                target_type='BUILTIN',
743                                autoproto=autoproto,
744                                autoproto_extra_source=autoproto_extra_source,
745                                depends_on=depends_on,
746                                local_include=local_include,
747                                global_include=global_include,
748                                allow_warnings=allow_warnings,
749                                __require_builtin_deps=True)
750
751 #################################################################
752 def SAMBA_SUBSYSTEM(bld, modname, source,
753                     deps='',
754                     public_deps='',
755                     __force_empty=False,
756                     includes='',
757                     public_headers=None,
758                     public_headers_install=True,
759                     private_headers=None,
760                     header_path=None,
761                     cflags='',
762                     cflags_end=None,
763                     group='main',
764                     target_type='SUBSYSTEM',
765                     init_function_sentinel=None,
766                     autoproto=None,
767                     autoproto_extra_source='',
768                     depends_on='',
769                     local_include=True,
770                     local_include_first=True,
771                     global_include=True,
772                     subsystem_name=None,
773                     enabled=True,
774                     use_hostcc=False,
775                     use_global_deps=True,
776                     vars=None,
777                     subdir=None,
778                     hide_symbols=False,
779                     __require_builtin_deps=False,
780                     provide_builtin_linking=False,
781                     builtin_cflags='',
782                     allow_warnings=False,
783                     pyext=False,
784                     pyembed=False):
785     '''define a Samba subsystem'''
786
787     # We support:
788     # - SUBSYSTEM: a normal subsystem from SAMBA_SUBSYSTEM()
789     # - BUILTIN:   a hidden subsystem from __SAMBA_SUBSYSTEM_BUILTIN()
790     if target_type not in ['SUBSYSTEM', 'BUILTIN']:
791         raise Errors.WafError("target_type[%s] not supported in SAMBA_SUBSYSTEM('%s')" %
792                               (target_type, modname))
793
794     if not enabled:
795         SET_TARGET_TYPE(bld, modname, 'DISABLED')
796         return
797
798     # remember empty subsystems, so we can strip the dependencies
799     if ((source == '') or (source == [])):
800         if not __force_empty and deps == '' and public_deps == '':
801             SET_TARGET_TYPE(bld, modname, 'EMPTY')
802             return
803         empty_c = modname + '.empty.c'
804         bld.SAMBA_GENERATOR('%s_empty_c' % modname,
805                             rule=generate_empty_file,
806                             target=empty_c)
807         source=empty_c
808
809     if not SET_TARGET_TYPE(bld, modname, target_type):
810         return
811
812     source = bld.EXPAND_VARIABLES(source, vars=vars)
813     if subdir:
814         source = bld.SUBDIR(subdir, source)
815     source = unique_list(TO_LIST(source))
816
817     deps += ' ' + public_deps
818
819     bld.SET_BUILD_GROUP(group)
820
821     features = 'c'
822     if pyext:
823         features += ' pyext'
824     if pyembed:
825         features += ' pyembed'
826
827     t = bld(
828         features       = features,
829         source         = source,
830         target         = modname,
831         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags,
832                                         allow_warnings=allow_warnings,
833                                         use_hostcc=use_hostcc,
834                                         hide_symbols=hide_symbols),
835         depends_on     = depends_on,
836         samba_deps     = TO_LIST(deps),
837         samba_includes = includes,
838         local_include  = local_include,
839         local_include_first  = local_include_first,
840         global_include = global_include,
841         samba_subsystem= subsystem_name,
842         samba_use_hostcc = use_hostcc,
843         samba_use_global_deps = use_global_deps,
844         samba_require_builtin_deps = __require_builtin_deps,
845         samba_builtin_subsystem = None,
846         )
847
848     if cflags_end is not None:
849         t.samba_cflags.extend(TO_LIST(cflags_end))
850
851     if autoproto is not None:
852         bld.SAMBA_AUTOPROTO(autoproto, source + TO_LIST(autoproto_extra_source))
853     if public_headers is not None:
854         bld.PUBLIC_HEADERS(public_headers, header_path=header_path,
855                            public_headers_install=public_headers_install)
856
857     if provide_builtin_linking:
858
859         if use_hostcc:
860             raise Errors.WafError("subsystem[%s] provide_builtin_linking=True " +
861                                   "not allowed with use_hostcc=True" %
862                                   modname)
863
864         if pyext or pyembed:
865             raise Errors.WafError("subsystem[%s] provide_builtin_linking=True " +
866                                   "not allowed with pyext=True nor pyembed=True" %
867                                   modname)
868
869         if __require_builtin_deps:
870             raise Errors.WafError("subsystem[%s] provide_builtin_linking=True " +
871                                   "not allowed with __require_builtin_deps=True" %
872                                   modname)
873
874         builtin_target = modname + '.builtin.objlist'
875         tbuiltin = __SAMBA_SUBSYSTEM_BUILTIN(bld, builtin_target, source,
876                                              deps=deps,
877                                              public_deps=public_deps,
878                                              includes=includes,
879                                              header_path=header_path,
880                                              builtin_cflags=builtin_cflags,
881                                              builtin_cflags_end='-D_PUBLIC_=_PRIVATE_',
882                                              group=group,
883                                              depends_on=depends_on,
884                                              local_include=local_include,
885                                              global_include=global_include,
886                                              allow_warnings=allow_warnings)
887         t.samba_builtin_subsystem = tbuiltin
888
889     return t
890
891
892 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
893
894
895 def SAMBA_GENERATOR(bld, name, rule, source='', target='',
896                     group='generators', enabled=True,
897                     public_headers=None,
898                     public_headers_install=True,
899                     private_headers=None,
900                     header_path=None,
901                     vars=None,
902                     dep_vars=[],
903                     always=False):
904     '''A generic source generator target'''
905
906     if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
907         return
908
909     if not enabled:
910         return
911
912     dep_vars = TO_LIST(dep_vars)
913     dep_vars.append('ruledeps')
914     dep_vars.append('SAMBA_GENERATOR_VARS')
915
916     bld.SET_BUILD_GROUP(group)
917     t = bld(
918         rule=rule,
919         source=bld.EXPAND_VARIABLES(source, vars=vars),
920         target=target,
921         shell=isinstance(rule, str),
922         update_outputs=True,
923         before='c',
924         ext_out='.c',
925         samba_type='GENERATOR',
926         dep_vars = dep_vars,
927         name=name)
928
929     if vars is None:
930         vars = {}
931     t.env.SAMBA_GENERATOR_VARS = vars
932
933     if always:
934         t.always = True
935
936     if public_headers is not None:
937         bld.PUBLIC_HEADERS(public_headers, header_path=header_path,
938                            public_headers_install=public_headers_install)
939     return t
940 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
941
942
943
944 @Utils.run_once
945 def SETUP_BUILD_GROUPS(bld):
946     '''setup build groups used to ensure that the different build
947     phases happen consecutively'''
948     bld.p_ln = bld.srcnode # we do want to see all targets!
949     bld.env['USING_BUILD_GROUPS'] = True
950     bld.add_group('setup')
951     bld.add_group('generators')
952     bld.add_group('hostcc_base_build_source')
953     bld.add_group('hostcc_base_build_main')
954     bld.add_group('hostcc_build_source')
955     bld.add_group('hostcc_build_main')
956     bld.add_group('vscripts')
957     bld.add_group('base_libraries')
958     bld.add_group('build_source')
959     bld.add_group('prototypes')
960     bld.add_group('headers')
961     bld.add_group('main')
962     bld.add_group('symbolcheck')
963     bld.add_group('syslibcheck')
964     bld.add_group('final')
965 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
966
967
968 def SET_BUILD_GROUP(bld, group):
969     '''set the current build group'''
970     if not 'USING_BUILD_GROUPS' in bld.env:
971         return
972     bld.set_group(group)
973 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
974
975
976
977 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
978     '''used to copy scripts from the source tree into the build directory
979        for use by selftest'''
980
981     source = bld.path.ant_glob(pattern, flat=True)
982
983     bld.SET_BUILD_GROUP('build_source')
984     for s in TO_LIST(source):
985         iname = s
986         if installname is not None:
987             iname = installname
988         target = os.path.join(installdir, iname)
989         tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
990         mkdir_p(tgtdir)
991         link_src = os.path.normpath(os.path.join(bld.path.abspath(), s))
992         link_dst = os.path.join(tgtdir, os.path.basename(iname))
993         if os.path.islink(link_dst) and os.readlink(link_dst) == link_src:
994             continue
995         if os.path.islink(link_dst):
996             os.unlink(link_dst)
997         Logs.info("symlink: %s -> %s/%s" % (s, installdir, iname))
998         symlink(link_src, link_dst)
999 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
1000
1001
1002 def copy_and_fix_python_path(task):
1003     pattern='sys.path.insert(0, "bin/python")'
1004     if task.env["PYTHONARCHDIR"] in sys.path and task.env["PYTHONDIR"] in sys.path:
1005         replacement = ""
1006     elif task.env["PYTHONARCHDIR"] == task.env["PYTHONDIR"]:
1007         replacement="""sys.path.insert(0, "%s")""" % task.env["PYTHONDIR"]
1008     else:
1009         replacement="""sys.path.insert(0, "%s")
1010 sys.path.insert(1, "%s")""" % (task.env["PYTHONARCHDIR"], task.env["PYTHONDIR"])
1011
1012     if task.env["PYTHON"][0].startswith("/"):
1013         replacement_shebang = "#!%s\n" % task.env["PYTHON"][0]
1014     else:
1015         replacement_shebang = "#!/usr/bin/env %s\n" % task.env["PYTHON"][0]
1016
1017     installed_location=task.outputs[0].bldpath(task.env)
1018     source_file = open(task.inputs[0].srcpath(task.env))
1019     installed_file = open(installed_location, 'w')
1020     lineno = 0
1021     for line in source_file:
1022         newline = line
1023         if (lineno == 0 and
1024                 line[:2] == "#!"):
1025             newline = replacement_shebang
1026         elif pattern in line:
1027             newline = line.replace(pattern, replacement)
1028         installed_file.write(newline)
1029         lineno = lineno + 1
1030     installed_file.close()
1031     os.chmod(installed_location, 0o755)
1032     return 0
1033
1034 def copy_and_fix_perl_path(task):
1035     pattern='use lib "$RealBin/lib";'
1036
1037     replacement = ""
1038     if not task.env["PERL_LIB_INSTALL_DIR"] in task.env["PERL_INC"]:
1039          replacement = 'use lib "%s";' % task.env["PERL_LIB_INSTALL_DIR"]
1040
1041     if task.env["PERL"][0] == "/":
1042         replacement_shebang = "#!%s\n" % task.env["PERL"]
1043     else:
1044         replacement_shebang = "#!/usr/bin/env %s\n" % task.env["PERL"]
1045
1046     installed_location=task.outputs[0].bldpath(task.env)
1047     source_file = open(task.inputs[0].srcpath(task.env))
1048     installed_file = open(installed_location, 'w')
1049     lineno = 0
1050     for line in source_file:
1051         newline = line
1052         if lineno == 0 and task.env["PERL_SPECIFIED"] == True and line[:2] == "#!":
1053             newline = replacement_shebang
1054         elif pattern in line:
1055             newline = line.replace(pattern, replacement)
1056         installed_file.write(newline)
1057         lineno = lineno + 1
1058     installed_file.close()
1059     os.chmod(installed_location, 0o755)
1060     return 0
1061
1062
1063 def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
1064                  python_fixup=False, perl_fixup=False,
1065                  destname=None, base_name=None):
1066     '''install a file'''
1067     if not isinstance(file, str):
1068         file = file.abspath()
1069     destdir = bld.EXPAND_VARIABLES(destdir)
1070     if not destname:
1071         destname = file
1072         if flat:
1073             destname = os.path.basename(destname)
1074     dest = os.path.join(destdir, destname)
1075     if python_fixup:
1076         # fix the path python will use to find Samba modules
1077         inst_file = file + '.inst'
1078         bld.SAMBA_GENERATOR('python_%s' % destname,
1079                             rule=copy_and_fix_python_path,
1080                             dep_vars=["PYTHON","PYTHON_SPECIFIED","PYTHONDIR","PYTHONARCHDIR"],
1081                             source=file,
1082                             target=inst_file)
1083         file = inst_file
1084     if perl_fixup:
1085         # fix the path perl will use to find Samba modules
1086         inst_file = file + '.inst'
1087         bld.SAMBA_GENERATOR('perl_%s' % destname,
1088                             rule=copy_and_fix_perl_path,
1089                             dep_vars=["PERL","PERL_SPECIFIED","PERL_LIB_INSTALL_DIR"],
1090                             source=file,
1091                             target=inst_file)
1092         file = inst_file
1093     if base_name:
1094         file = os.path.join(base_name, file)
1095     bld.install_as(dest, file, chmod=chmod)
1096
1097
1098 def INSTALL_FILES(bld, destdir, files, chmod=MODE_644, flat=False,
1099                   python_fixup=False, perl_fixup=False,
1100                   destname=None, base_name=None):
1101     '''install a set of files'''
1102     for f in TO_LIST(files):
1103         install_file(bld, destdir, f, chmod=chmod, flat=flat,
1104                      python_fixup=python_fixup, perl_fixup=perl_fixup,
1105                      destname=destname, base_name=base_name)
1106 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
1107
1108
1109 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
1110                      python_fixup=False, exclude=None, trim_path=None):
1111     '''install a set of files matching a wildcard pattern'''
1112     files=TO_LIST(bld.path.ant_glob(pattern, flat=True))
1113     if trim_path:
1114         files2 = []
1115         for f in files:
1116             files2.append(os.path.relpath(f, trim_path))
1117         files = files2
1118
1119     if exclude:
1120         for f in files[:]:
1121             if fnmatch.fnmatch(f, exclude):
1122                 files.remove(f)
1123     INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat,
1124                   python_fixup=python_fixup, base_name=trim_path)
1125 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
1126
1127 def INSTALL_DIR(bld, path, chmod=0o755, env=None):
1128     """Install a directory if it doesn't exist, always set permissions."""
1129
1130     if not path:
1131         return []
1132
1133     destpath = bld.EXPAND_VARIABLES(path)
1134     if Options.options.destdir:
1135         destpath = os.path.join(Options.options.destdir, destpath.lstrip(os.sep))
1136
1137     if bld.is_install > 0:
1138         if not os.path.isdir(destpath):
1139             try:
1140                 Logs.info('* create %s', destpath)
1141                 os.makedirs(destpath)
1142                 os.chmod(destpath, chmod)
1143             except OSError as e:
1144                 if not os.path.isdir(destpath):
1145                     raise Errors.WafError("Cannot create the folder '%s' (error: %s)" % (path, e))
1146 Build.BuildContext.INSTALL_DIR = INSTALL_DIR
1147
1148 def INSTALL_DIRS(bld, destdir, dirs, chmod=0o755, env=None):
1149     '''install a set of directories'''
1150     destdir = bld.EXPAND_VARIABLES(destdir)
1151     dirs = bld.EXPAND_VARIABLES(dirs)
1152     for d in TO_LIST(dirs):
1153         INSTALL_DIR(bld, os.path.join(destdir, d), chmod, env)
1154 Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
1155
1156
1157 def MANPAGES(bld, manpages, install):
1158     '''build and install manual pages'''
1159     bld.env.MAN_XSL = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
1160     for m in manpages.split():
1161         source = m + '.xml'
1162         bld.SAMBA_GENERATOR(m,
1163                             source=source,
1164                             target=m,
1165                             group='final',
1166                             rule='${XSLTPROC} --xinclude -o ${TGT} --nonet ${MAN_XSL} ${SRC}'
1167                             )
1168         if install:
1169             bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
1170 Build.BuildContext.MANPAGES = MANPAGES
1171
1172 def SAMBAMANPAGES(bld, manpages, extra_source=None):
1173     '''build and install manual pages'''
1174     bld.env.SAMBA_EXPAND_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/expand-sambadoc.xsl'
1175     bld.env.SAMBA_MAN_XSL = bld.srcnode.abspath() + '/docs-xml/xslt/man.xsl'
1176     bld.env.SAMBA_CATALOG = bld.bldnode.abspath() + '/docs-xml/build/catalog.xml'
1177     bld.env.SAMBA_CATALOGS = 'file:///etc/xml/catalog file:///usr/local/share/xml/catalog file://' + bld.env.SAMBA_CATALOG
1178
1179     for m in manpages.split():
1180         source = [m + '.xml']
1181         if extra_source is not None:
1182             source = [source, extra_source]
1183         # ${SRC[1]}, ${SRC[2]} and ${SRC[3]} are not referenced in the
1184         # SAMBA_GENERATOR but trigger the dependency calculation so
1185         # ensures that manpages are rebuilt when these change.
1186         source += ['build/DTD/samba.build.pathconfig', 'build/DTD/samba.entities', 'build/DTD/samba.build.version']
1187         bld.SAMBA_GENERATOR(m,
1188                             source=source,
1189                             target=m,
1190                             group='final',
1191                             dep_vars=['SAMBA_MAN_XSL', 'SAMBA_EXPAND_XSL', 'SAMBA_CATALOG'],
1192                             rule='''XML_CATALOG_FILES="${SAMBA_CATALOGS}"
1193                                     export XML_CATALOG_FILES
1194                                     ${XSLTPROC} --xinclude --stringparam noreference 0 -o ${TGT}.xml --nonet ${SAMBA_EXPAND_XSL} ${SRC[0].abspath(env)}
1195                                     ${XSLTPROC} --nonet -o ${TGT} ${SAMBA_MAN_XSL} ${TGT}.xml'''
1196                             )
1197         bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
1198 Build.BuildContext.SAMBAMANPAGES = SAMBAMANPAGES
1199
1200 @after('apply_link')
1201 @feature('cshlib')
1202 def apply_bundle_remove_dynamiclib_patch(self):
1203     if self.env['MACBUNDLE'] or getattr(self,'mac_bundle',False):
1204         if not getattr(self,'vnum',None):
1205             try:
1206                 self.env['LINKFLAGS'].remove('-dynamiclib')
1207                 self.env['LINKFLAGS'].remove('-single_module')
1208             except ValueError:
1209                 pass