wafsamba: Use abi_match in version script files.
[Samba/bb.git] / buildtools / wafsamba / wafsamba.py
blobc532c4b413b42a9d4dba842d7c686ee63c83156d
1 # a waf tool to add autoconf-like macros to the configure section
2 # and for SAMBA_ macros for building libraries, binaries etc
4 import Build, os, Options, Task, Utils, cc, TaskGen, fnmatch, re, shutil, Logs, Constants
5 from Configure import conf
6 from Logs import debug
7 from samba_utils import SUBST_VARS_RECURSIVE
8 TaskGen.task_gen.apply_verif = Utils.nada
10 # bring in the other samba modules
11 from samba_optimisation import *
12 from samba_utils import *
13 from samba_version import *
14 from samba_autoconf import *
15 from samba_patterns import *
16 from samba_pidl import *
17 from samba_autoproto import *
18 from samba_python import *
19 from samba_deps import *
20 from samba_bundled import *
21 import samba_install
22 import samba_conftests
23 import samba_abi
24 import tru64cc
25 import irixcc
26 import hpuxcc
27 import generic_cc
28 import samba_dist
29 import samba_wildcard
30 import stale_files
31 import symbols
32 import pkgconfig
34 # some systems have broken threading in python
35 if os.environ.get('WAF_NOTHREADS') == '1':
36 import nothreads
38 LIB_PATH="shared"
40 os.putenv('PYTHONUNBUFFERED', '1')
43 if Constants.HEXVERSION < 0x105019:
44 Logs.error('''
45 Please use the version of waf that comes with Samba, not
46 a system installed version. See http://wiki.samba.org/index.php/Waf
47 for details.
49 Alternatively, please use ./autogen-waf.sh, and then
50 run ./configure and make as usual. That will call the right version of waf.
51 ''')
52 sys.exit(1)
55 @conf
56 def SAMBA_BUILD_ENV(conf):
57 '''create the samba build environment'''
58 conf.env.BUILD_DIRECTORY = conf.blddir
59 mkdir_p(os.path.join(conf.blddir, LIB_PATH))
60 mkdir_p(os.path.join(conf.blddir, LIB_PATH, "private"))
61 mkdir_p(os.path.join(conf.blddir, "modules"))
62 mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
63 # this allows all of the bin/shared and bin/python targets
64 # to be expressed in terms of build directory paths
65 mkdir_p(os.path.join(conf.blddir, 'default'))
66 for p in ['python','shared', 'modules']:
67 link_target = os.path.join(conf.blddir, 'default/' + p)
68 if not os.path.lexists(link_target):
69 os.symlink('../' + p, link_target)
71 # get perl to put the blib files in the build directory
72 blib_bld = os.path.join(conf.blddir, 'default/pidl/blib')
73 blib_src = os.path.join(conf.srcdir, 'pidl/blib')
74 mkdir_p(blib_bld + '/man1')
75 mkdir_p(blib_bld + '/man3')
76 if os.path.islink(blib_src):
77 os.unlink(blib_src)
78 elif os.path.exists(blib_src):
79 shutil.rmtree(blib_src)
82 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
83 '''add an init_function to the list for a subsystem'''
84 if init_function is None:
85 return
86 bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
87 cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
88 if not subsystem in cache:
89 cache[subsystem] = []
90 cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
91 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
95 #################################################################
96 def SAMBA_LIBRARY(bld, libname, source,
97 deps='',
98 public_deps='',
99 includes='',
100 public_headers=None,
101 header_path=None,
102 pc_files=None,
103 vnum=None,
104 soname=None,
105 cflags='',
106 ldflags='',
107 external_library=False,
108 realname=None,
109 autoproto=None,
110 group='libraries',
111 depends_on='',
112 local_include=True,
113 vars=None,
114 install_path=None,
115 install=True,
116 pyembed=False,
117 pyext=False,
118 target_type='LIBRARY',
119 bundled_extension=True,
120 link_name=None,
121 abi_directory=None,
122 abi_match=None,
123 hide_symbols=False,
124 manpages=None,
125 private_library=False,
126 grouping_library=False,
127 enabled=True):
128 '''define a Samba library'''
130 if not enabled:
131 SET_TARGET_TYPE(bld, libname, 'DISABLED')
132 return
134 source = bld.EXPAND_VARIABLES(source, vars=vars)
136 # remember empty libraries, so we can strip the dependencies
137 if ((source == '') or (source == [])) and deps == '' and public_deps == '':
138 SET_TARGET_TYPE(bld, libname, 'EMPTY')
139 return
141 if BUILTIN_LIBRARY(bld, libname):
142 obj_target = libname
143 else:
144 obj_target = libname + '.objlist'
146 if group == 'libraries':
147 subsystem_group = 'main'
148 else:
149 subsystem_group = group
151 # first create a target for building the object files for this library
152 # by separating in this way, we avoid recompiling the C files
153 # separately for the install library and the build library
154 bld.SAMBA_SUBSYSTEM(obj_target,
155 source = source,
156 deps = deps,
157 public_deps = public_deps,
158 includes = includes,
159 public_headers = public_headers,
160 header_path = header_path,
161 cflags = cflags,
162 group = subsystem_group,
163 autoproto = autoproto,
164 depends_on = depends_on,
165 hide_symbols = hide_symbols,
166 pyext = pyext or (target_type == "PYTHON"),
167 local_include = local_include)
169 if BUILTIN_LIBRARY(bld, libname):
170 return
172 if not SET_TARGET_TYPE(bld, libname, target_type):
173 return
175 # the library itself will depend on that object target
176 deps += ' ' + public_deps
177 deps = TO_LIST(deps)
178 deps.append(obj_target)
180 realname = bld.map_shlib_extension(realname, python=(target_type=='PYTHON'))
181 link_name = bld.map_shlib_extension(link_name, python=(target_type=='PYTHON'))
183 # we don't want any public libraries without version numbers
184 if not private_library and vnum is None and soname is None and target_type != 'PYTHON' and not realname:
185 raise Utils.WafError("public library '%s' must have a vnum" % libname)
187 if target_type == 'PYTHON' or realname or not private_library:
188 bundled_name = libname.replace('_', '-')
189 else:
190 bundled_name = PRIVATE_NAME(bld, libname, bundled_extension, private_library)
192 ldflags = TO_LIST(ldflags)
194 features = 'cc cshlib symlink_lib install_lib'
195 if target_type == 'PYTHON':
196 features += ' pyext'
197 if pyext or pyembed:
198 # this is quite strange. we should add pyext feature for pyext
199 # but that breaks the build. This may be a bug in the waf python tool
200 features += ' pyembed'
202 if abi_directory:
203 features += ' abi_check'
205 vscript = None
206 if bld.env.HAVE_LD_VERSION_SCRIPT:
207 if private_library:
208 version = "%s_%s" % (Utils.g_module.APPNAME, Utils.g_module.VERSION)
209 elif vnum:
210 version = "%s_%s" % (libname, vnum)
211 else:
212 version = None
213 if version:
214 vscript = "%s.vscript" % libname
215 bld.ABI_VSCRIPT(libname, abi_directory, version, vscript,
216 abi_match)
217 fullname = bld.env.shlib_PATTERN % bundled_name
218 bld.add_manual_dependency(bld.path.find_or_declare(fullname), bld.path.find_or_declare(vscript))
219 if Options.is_install:
220 # also make the .inst file depend on the vscript
221 instname = bld.env.shlib_PATTERN % (bundled_name + '.inst')
222 bld.add_manual_dependency(bld.path.find_or_declare(instname), bld.path.find_or_declare(vscript))
223 vscript = os.path.join(bld.path.abspath(bld.env), vscript)
225 bld.SET_BUILD_GROUP(group)
226 t = bld(
227 features = features,
228 source = [],
229 target = bundled_name,
230 depends_on = depends_on,
231 samba_ldflags = ldflags,
232 samba_deps = deps,
233 samba_includes = includes,
234 version_script = vscript,
235 local_include = local_include,
236 vnum = vnum,
237 soname = soname,
238 install_path = None,
239 samba_inst_path = install_path,
240 name = libname,
241 samba_realname = realname,
242 samba_install = install,
243 abi_directory = "%s/%s" % (bld.path.abspath(), abi_directory),
244 abi_match = abi_match,
245 private_library = private_library,
246 grouping_library=grouping_library
249 if realname and not link_name:
250 link_name = 'shared/%s' % realname
252 if link_name:
253 t.link_name = link_name
255 if pc_files is not None:
256 bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
258 if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
259 bld.MANPAGES(manpages)
262 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
265 #################################################################
266 def SAMBA_BINARY(bld, binname, source,
267 deps='',
268 includes='',
269 public_headers=None,
270 header_path=None,
271 modules=None,
272 ldflags=None,
273 cflags='',
274 autoproto=None,
275 use_hostcc=False,
276 use_global_deps=True,
277 compiler=None,
278 group='binaries',
279 manpages=None,
280 local_include=True,
281 subsystem_name=None,
282 pyembed=False,
283 vars=None,
284 install=True,
285 install_path=None,
286 enabled=True):
287 '''define a Samba binary'''
289 if not enabled:
290 SET_TARGET_TYPE(bld, binname, 'DISABLED')
291 return
293 if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
294 return
296 features = 'cc cprogram symlink_bin install_bin'
297 if pyembed:
298 features += ' pyembed'
300 obj_target = binname + '.objlist'
302 source = bld.EXPAND_VARIABLES(source, vars=vars)
303 source = unique_list(TO_LIST(source))
305 if group == 'binaries':
306 subsystem_group = 'main'
307 else:
308 subsystem_group = group
310 # first create a target for building the object files for this binary
311 # by separating in this way, we avoid recompiling the C files
312 # separately for the install binary and the build binary
313 bld.SAMBA_SUBSYSTEM(obj_target,
314 source = source,
315 deps = deps,
316 includes = includes,
317 cflags = cflags,
318 group = subsystem_group,
319 autoproto = autoproto,
320 subsystem_name = subsystem_name,
321 local_include = local_include,
322 use_hostcc = use_hostcc,
323 pyext = pyembed,
324 use_global_deps= use_global_deps)
326 bld.SET_BUILD_GROUP(group)
328 # the binary itself will depend on that object target
329 deps = TO_LIST(deps)
330 deps.append(obj_target)
332 t = bld(
333 features = features,
334 source = [],
335 target = binname,
336 samba_deps = deps,
337 samba_includes = includes,
338 local_include = local_include,
339 samba_modules = modules,
340 top = True,
341 samba_subsystem= subsystem_name,
342 install_path = None,
343 samba_inst_path= install_path,
344 samba_install = install,
345 samba_ldflags = TO_LIST(ldflags)
348 if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
349 bld.MANPAGES(manpages)
351 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
354 #################################################################
355 def SAMBA_MODULE(bld, modname, source,
356 deps='',
357 includes='',
358 subsystem=None,
359 init_function=None,
360 module_init_name='samba_init_module',
361 autoproto=None,
362 autoproto_extra_source='',
363 cflags='',
364 internal_module=True,
365 local_include=True,
366 vars=None,
367 enabled=True,
368 pyembed=False,
370 '''define a Samba module.'''
372 source = bld.EXPAND_VARIABLES(source, vars=vars)
374 if internal_module or BUILTIN_LIBRARY(bld, modname):
375 bld.SAMBA_SUBSYSTEM(modname, source,
376 deps=deps,
377 includes=includes,
378 autoproto=autoproto,
379 autoproto_extra_source=autoproto_extra_source,
380 cflags=cflags,
381 local_include=local_include,
382 enabled=enabled)
384 bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
385 return
387 if not enabled:
388 SET_TARGET_TYPE(bld, modname, 'DISABLED')
389 return
391 obj_target = modname + '.objlist'
393 realname = modname
394 if subsystem is not None:
395 deps += ' ' + subsystem
396 while realname.startswith("lib"+subsystem+"_"):
397 realname = realname[len("lib"+subsystem+"_"):]
398 while realname.startswith(subsystem+"_"):
399 realname = realname[len(subsystem+"_"):]
401 realname = bld.make_libname(realname)
402 while realname.startswith("lib"):
403 realname = realname[len("lib"):]
405 build_link_name = "modules/%s/%s" % (subsystem, realname)
407 if init_function:
408 cflags += " -D%s=%s" % (init_function, module_init_name)
410 bld.SAMBA_LIBRARY(modname,
411 source,
412 deps=deps,
413 cflags=cflags,
414 realname = realname,
415 autoproto = autoproto,
416 local_include=local_include,
417 vars=vars,
418 link_name=build_link_name,
419 install_path="${MODULESDIR}/%s" % subsystem,
420 pyembed=pyembed,
424 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
427 #################################################################
428 def SAMBA_SUBSYSTEM(bld, modname, source,
429 deps='',
430 public_deps='',
431 includes='',
432 public_headers=None,
433 header_path=None,
434 cflags='',
435 cflags_end=None,
436 group='main',
437 init_function_sentinal=None,
438 autoproto=None,
439 autoproto_extra_source='',
440 depends_on='',
441 local_include=True,
442 local_include_first=True,
443 subsystem_name=None,
444 enabled=True,
445 use_hostcc=False,
446 use_global_deps=True,
447 vars=None,
448 hide_symbols=False,
449 pyext=False):
450 '''define a Samba subsystem'''
452 if not enabled:
453 SET_TARGET_TYPE(bld, modname, 'DISABLED')
454 return
456 # remember empty subsystems, so we can strip the dependencies
457 if ((source == '') or (source == [])) and deps == '' and public_deps == '':
458 SET_TARGET_TYPE(bld, modname, 'EMPTY')
459 return
461 if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
462 return
464 source = bld.EXPAND_VARIABLES(source, vars=vars)
465 source = unique_list(TO_LIST(source))
467 deps += ' ' + public_deps
469 bld.SET_BUILD_GROUP(group)
471 features = 'cc'
472 if pyext:
473 features += ' pyext'
475 t = bld(
476 features = features,
477 source = source,
478 target = modname,
479 samba_cflags = CURRENT_CFLAGS(bld, modname, cflags, hide_symbols=hide_symbols),
480 depends_on = depends_on,
481 samba_deps = TO_LIST(deps),
482 samba_includes = includes,
483 local_include = local_include,
484 local_include_first = local_include_first,
485 samba_subsystem= subsystem_name,
486 samba_use_hostcc = use_hostcc,
487 samba_use_global_deps = use_global_deps
490 if cflags_end is not None:
491 t.samba_cflags.extend(TO_LIST(cflags_end))
493 if autoproto is not None:
494 bld.SAMBA_AUTOPROTO(autoproto, source + TO_LIST(autoproto_extra_source))
495 if public_headers is not None:
496 bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
497 return t
500 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
503 def SAMBA_GENERATOR(bld, name, rule, source='', target='',
504 group='generators', enabled=True,
505 public_headers=None,
506 header_path=None,
507 vars=None,
508 always=False):
509 '''A generic source generator target'''
511 if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
512 return
514 if not enabled:
515 return
517 bld.SET_BUILD_GROUP(group)
518 t = bld(
519 rule=rule,
520 source=bld.EXPAND_VARIABLES(source, vars=vars),
521 target=target,
522 shell=isinstance(rule, str),
523 on_results=True,
524 before='cc',
525 ext_out='.c',
526 samba_type='GENERATOR',
527 vars = [rule],
528 name=name)
530 if always:
531 t.always = True
533 if public_headers is not None:
534 bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
535 return t
536 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
540 @runonce
541 def SETUP_BUILD_GROUPS(bld):
542 '''setup build groups used to ensure that the different build
543 phases happen consecutively'''
544 bld.p_ln = bld.srcnode # we do want to see all targets!
545 bld.env['USING_BUILD_GROUPS'] = True
546 bld.add_group('setup')
547 bld.add_group('build_compiler_source')
548 bld.add_group('vscripts')
549 bld.add_group('base_libraries')
550 bld.add_group('generators')
551 bld.add_group('compiler_prototypes')
552 bld.add_group('compiler_libraries')
553 bld.add_group('build_compilers')
554 bld.add_group('build_source')
555 bld.add_group('prototypes')
556 bld.add_group('main')
557 bld.add_group('symbolcheck')
558 bld.add_group('libraries')
559 bld.add_group('binaries')
560 bld.add_group('syslibcheck')
561 bld.add_group('final')
562 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
565 def SET_BUILD_GROUP(bld, group):
566 '''set the current build group'''
567 if not 'USING_BUILD_GROUPS' in bld.env:
568 return
569 bld.set_group(group)
570 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
574 @conf
575 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
576 """use timestamps instead of file contents for deps
577 this currently doesn't work"""
578 def h_file(filename):
579 import stat
580 st = os.stat(filename)
581 if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
582 m = Utils.md5()
583 m.update(str(st.st_mtime))
584 m.update(str(st.st_size))
585 m.update(filename)
586 return m.digest()
587 Utils.h_file = h_file
591 t = Task.simple_task_type('copy_script', 'rm -f "${LINK_TARGET}" && ln -s "${SRC[0].abspath(env)}" ${LINK_TARGET}',
592 shell=True, color='PINK', ext_in='.bin')
593 t.quiet = True
595 @feature('copy_script')
596 @before('apply_link')
597 def copy_script(self):
598 tsk = self.create_task('copy_script', self.allnodes[0])
599 tsk.env.TARGET = self.target
601 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
602 '''used to copy scripts from the source tree into the build directory
603 for use by selftest'''
605 source = bld.path.ant_glob(pattern)
607 bld.SET_BUILD_GROUP('build_source')
608 for s in TO_LIST(source):
609 iname = s
610 if installname != None:
611 iname = installname
612 target = os.path.join(installdir, iname)
613 tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
614 mkdir_p(tgtdir)
615 t = bld(features='copy_script',
616 source = s,
617 target = target,
618 always = True,
619 install_path = None)
620 t.env.LINK_TARGET = target
622 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
625 def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
626 python_fixup=False, destname=None, base_name=None):
627 '''install a file'''
628 destdir = bld.EXPAND_VARIABLES(destdir)
629 if not destname:
630 destname = file
631 if flat:
632 destname = os.path.basename(destname)
633 dest = os.path.join(destdir, destname)
634 if python_fixup:
635 # fixup the python path it will use to find Samba modules
636 inst_file = file + '.inst'
637 if bld.env["PYTHONDIR"] not in sys.path:
638 regex = "s|\(sys.path.insert.*\)bin/python\(.*\)$|\\1${PYTHONDIR}\\2|g"
639 else:
640 # Eliminate updating sys.path if the target python dir is already
641 # in python path.
642 regex = "s|sys.path.insert.*bin/python.*$||g"
643 bld.SAMBA_GENERATOR('python_%s' % destname,
644 rule="sed '%s' < ${SRC} > ${TGT}" % regex,
645 source=file,
646 target=inst_file)
647 file = inst_file
648 if base_name:
649 file = os.path.join(base_name, file)
650 bld.install_as(dest, file, chmod=chmod)
653 def INSTALL_FILES(bld, destdir, files, chmod=MODE_644, flat=False,
654 python_fixup=False, destname=None, base_name=None):
655 '''install a set of files'''
656 for f in TO_LIST(files):
657 install_file(bld, destdir, f, chmod=chmod, flat=flat,
658 python_fixup=python_fixup, destname=destname,
659 base_name=base_name)
660 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
663 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
664 python_fixup=False, exclude=None, trim_path=None):
665 '''install a set of files matching a wildcard pattern'''
666 files=TO_LIST(bld.path.ant_glob(pattern))
667 if trim_path:
668 files2 = []
669 for f in files:
670 files2.append(os_path_relpath(f, trim_path))
671 files = files2
673 if exclude:
674 for f in files[:]:
675 if fnmatch.fnmatch(f, exclude):
676 files.remove(f)
677 INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat,
678 python_fixup=python_fixup, base_name=trim_path)
679 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
682 def INSTALL_DIRS(bld, destdir, dirs):
683 '''install a set of directories'''
684 destdir = bld.EXPAND_VARIABLES(destdir)
685 dirs = bld.EXPAND_VARIABLES(dirs)
686 for d in TO_LIST(dirs):
687 bld.install_dir(os.path.join(destdir, d))
688 Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
691 re_header = re.compile('#include[ \t]*"([^"]+)"', re.I | re.M)
692 class header_task(Task.Task):
694 The public headers (the one installed on the system) have both
695 different paths and contents, so the rename is not enough.
697 Intermediate .inst.h files are created because path manipulation
698 may be slow. The substitution is thus performed only once.
701 name = 'header'
702 color = 'PINK'
703 vars = ['INCLUDEDIR', 'HEADER_DEPS']
705 def run(self):
706 txt = self.inputs[0].read(self.env)
708 # hard-coded string, but only present in samba4 (I promise, you won't feel a thing)
709 txt = txt.replace('#if _SAMBA_BUILD_ == 4', '#if 1\n')
711 # use a regexp to substitute the #include lines in the files
712 map = self.generator.bld.hnodemap
713 dirnodes = self.generator.bld.hnodedirs
714 def repl(m):
715 if m.group(1):
716 s = m.group(1)
718 # pokemon headers: gotta catch'em all!
719 fin = s
720 if s.startswith('bin/default'):
721 node = self.generator.bld.srcnode.find_resource(s.replace('bin/default/', ''))
722 if not node:
723 Logs.warn('could not find the public header for %r' % s)
724 elif node.id in map:
725 fin = map[node.id]
726 else:
727 Logs.warn('could not find the public header replacement for build header %r' % s)
728 else:
729 # this part is more difficult since the path may be relative to anything
730 for dirnode in dirnodes:
731 node = dirnode.find_resource(s)
732 if node:
733 if node.id in map:
734 fin = map[node.id]
735 break
736 else:
737 Logs.warn('could not find the public header replacement for source header %r %r' % (s, node))
738 else:
739 Logs.warn('-> could not find the public header for %r' % s)
741 return "#include <%s>" % fin
742 return ''
744 txt = re_header.sub(repl, txt)
746 # and write the output file
747 f = None
748 try:
749 f = open(self.outputs[0].abspath(self.env), 'w')
750 f.write(txt)
751 finally:
752 if f:
753 f.close()
755 @TaskGen.feature('pubh')
756 def make_public_headers(self):
758 collect the public headers to process and to install, then
759 create the substitutions (name and contents)
762 if not self.bld.is_install:
763 # install time only (lazy)
764 return
766 # keep two variables
767 # hnodedirs: list of folders for searching the headers
768 # hnodemap: node ids and replacement string (node objects are unique)
769 try:
770 self.bld.hnodedirs.append(self.path)
771 except AttributeError:
772 self.bld.hnodemap = {}
773 self.bld.hnodedirs = [self.bld.srcnode, self.path]
775 for k in 'source4 source4/include lib/talloc lib/tevent/ source4/lib/ldb/include/'.split():
776 node = self.bld.srcnode.find_dir(k)
777 if node:
778 self.bld.hnodedirs.append(node)
780 header_path = getattr(self, 'header_path', None) or ''
782 for x in self.to_list(self.headers):
784 # too complicated, but what was the original idea?
785 if isinstance(header_path, list):
786 add_dir = ''
787 for (p1, dir) in header_path:
788 lst = self.to_list(p1)
789 for p2 in lst:
790 if fnmatch.fnmatch(x, p2):
791 add_dir = dir
792 break
793 else:
794 continue
795 break
796 inst_path = add_dir
797 else:
798 inst_path = header_path
800 dest = ''
801 name = x
802 if x.find(':') != -1:
803 s = x.split(':')
804 name = s[0]
805 dest = s[1]
807 inn = self.path.find_resource(name)
809 if not inn:
810 raise ValueError("could not find the public header %r in %r" % (name, self.path))
811 out = inn.change_ext('.inst.h')
812 self.create_task('header', inn, out)
814 if not dest:
815 dest = inn.name
817 if inst_path:
818 inst_path = inst_path + '/'
819 inst_path = inst_path + dest
821 self.bld.install_as('${INCLUDEDIR}/%s' % inst_path, out, self.env)
823 self.bld.hnodemap[inn.id] = inst_path
825 # create a hash (not md5) to make sure the headers are re-created if something changes
826 val = 0
827 lst = list(self.bld.hnodemap.keys())
828 lst.sort()
829 for k in lst:
830 val = hash((val, k, self.bld.hnodemap[k]))
831 self.bld.env.HEADER_DEPS = val
833 def PUBLIC_HEADERS(bld, public_headers, header_path=None):
834 '''install some headers
836 header_path may either be a string that is added to the INCLUDEDIR,
837 or it can be a dictionary of wildcard patterns which map to destination
838 directories relative to INCLUDEDIR
840 bld.SET_BUILD_GROUP('final')
841 ret = bld(features=['pubh'], headers=public_headers, header_path=header_path)
842 return ret
843 Build.BuildContext.PUBLIC_HEADERS = PUBLIC_HEADERS
846 def MANPAGES(bld, manpages):
847 '''build and install manual pages'''
848 bld.env.MAN_XSL = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
849 for m in manpages.split():
850 source = m + '.xml'
851 bld.SAMBA_GENERATOR(m,
852 source=source,
853 target=m,
854 group='final',
855 rule='${XSLTPROC} -o ${TGT} --nonet ${MAN_XSL} ${SRC}'
857 bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
858 Build.BuildContext.MANPAGES = MANPAGES
861 #############################################################
862 # give a nicer display when building different types of files
863 def progress_display(self, msg, fname):
864 col1 = Logs.colors(self.color)
865 col2 = Logs.colors.NORMAL
866 total = self.position[1]
867 n = len(str(total))
868 fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg)
869 return fs % (self.position[0], self.position[1], col1, fname, col2)
871 def link_display(self):
872 if Options.options.progress_bar != 0:
873 return Task.Task.old_display(self)
874 fname = self.outputs[0].bldpath(self.env)
875 return progress_display(self, 'Linking', fname)
876 Task.TaskBase.classes['cc_link'].display = link_display
878 def samba_display(self):
879 if Options.options.progress_bar != 0:
880 return Task.Task.old_display(self)
882 targets = LOCAL_CACHE(self, 'TARGET_TYPE')
883 if self.name in targets:
884 target_type = targets[self.name]
885 type_map = { 'GENERATOR' : 'Generating',
886 'PROTOTYPE' : 'Generating'
888 if target_type in type_map:
889 return progress_display(self, type_map[target_type], self.name)
891 if len(self.inputs) == 0:
892 return Task.Task.old_display(self)
894 fname = self.inputs[0].bldpath(self.env)
895 if fname[0:3] == '../':
896 fname = fname[3:]
897 ext_loc = fname.rfind('.')
898 if ext_loc == -1:
899 return Task.Task.old_display(self)
900 ext = fname[ext_loc:]
902 ext_map = { '.idl' : 'Compiling IDL',
903 '.et' : 'Compiling ERRTABLE',
904 '.asn1': 'Compiling ASN1',
905 '.c' : 'Compiling' }
906 if ext in ext_map:
907 return progress_display(self, ext_map[ext], fname)
908 return Task.Task.old_display(self)
910 Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display
911 Task.TaskBase.classes['Task'].display = samba_display
914 @after('apply_link')
915 @feature('cshlib')
916 def apply_bundle_remove_dynamiclib_patch(self):
917 if self.env['MACBUNDLE'] or getattr(self,'mac_bundle',False):
918 if not getattr(self,'vnum',None):
919 try:
920 self.env['LINKFLAGS'].remove('-dynamiclib')
921 self.env['LINKFLAGS'].remove('-single_module')
922 except ValueError:
923 pass