buildtools: make sure we have no '+' in the version scripts
[Samba/gebeck_regimport.git] / buildtools / wafsamba / wafsamba.py
blobbf03973f88a0ebe780779bb274602927701d57e1
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_file=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 if private_library:
195 if vnum:
196 Logs.error("vnum is invalid for private libraries")
197 sys.exit(1)
198 vnum = Utils.g_module.VERSION.split(".")[0]
199 version = "%s_%s" % (Utils.g_module.APPNAME, Utils.g_module.VERSION)
200 else:
201 version = "%s_%s" % (Utils.g_module.APPNAME, Utils.g_module.VERSION.split(".")[0])
203 if bld.env.HAVE_LD_VERSION_SCRIPT:
204 vscript = "%s.vscript" % libname
205 bld.SAMBA_GENERATOR(vscript,
206 rule="echo %s \{ global: \*\; \}\; > ${TGT}" % version.replace("-","_").replace("+","_").upper(),
207 group='vscripts',
208 target=vscript)
209 ldflags.append("-Wl,--version-script=%s/%s" % (bld.path.abspath(bld.env), vscript))
211 features = 'cc cshlib symlink_lib install_lib'
212 if target_type == 'PYTHON':
213 features += ' pyext'
214 if pyext or pyembed:
215 # this is quite strange. we should add pyext feature for pyext
216 # but that breaks the build. This may be a bug in the waf python tool
217 features += ' pyembed'
218 if abi_file:
219 features += ' abi_check'
221 if abi_file:
222 abi_file = os.path.join(bld.curdir, abi_file)
224 bld.SET_BUILD_GROUP(group)
225 t = bld(
226 features = features,
227 source = [],
228 target = bundled_name,
229 depends_on = depends_on,
230 ldflags = ldflags,
231 samba_deps = deps,
232 samba_includes = includes,
233 local_include = local_include,
234 vnum = vnum,
235 soname = soname,
236 install_path = None,
237 samba_inst_path = install_path,
238 name = libname,
239 samba_realname = realname,
240 samba_install = install,
241 abi_file = abi_file,
242 abi_match = abi_match,
243 private_library = private_library,
244 grouping_library=grouping_library
247 if realname and not link_name:
248 link_name = 'shared/%s' % realname
250 if link_name:
251 t.link_name = link_name
253 if pc_files is not None:
254 bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
256 if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
257 bld.MANPAGES(manpages)
260 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
263 #################################################################
264 def SAMBA_BINARY(bld, binname, source,
265 deps='',
266 includes='',
267 public_headers=None,
268 header_path=None,
269 modules=None,
270 ldflags=None,
271 cflags='',
272 autoproto=None,
273 use_hostcc=False,
274 use_global_deps=True,
275 compiler=None,
276 group='binaries',
277 manpages=None,
278 local_include=True,
279 subsystem_name=None,
280 pyembed=False,
281 vars=None,
282 install=True,
283 install_path=None,
284 enabled=True):
285 '''define a Samba binary'''
287 if not enabled:
288 SET_TARGET_TYPE(bld, binname, 'DISABLED')
289 return
291 if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
292 return
294 features = 'cc cprogram symlink_bin install_bin'
295 if pyembed:
296 features += ' pyembed'
298 obj_target = binname + '.objlist'
300 source = bld.EXPAND_VARIABLES(source, vars=vars)
301 source = unique_list(TO_LIST(source))
303 if group == 'binaries':
304 subsystem_group = 'main'
305 else:
306 subsystem_group = group
308 # first create a target for building the object files for this binary
309 # by separating in this way, we avoid recompiling the C files
310 # separately for the install binary and the build binary
311 bld.SAMBA_SUBSYSTEM(obj_target,
312 source = source,
313 deps = deps,
314 includes = includes,
315 cflags = cflags,
316 group = subsystem_group,
317 autoproto = autoproto,
318 subsystem_name = subsystem_name,
319 local_include = local_include,
320 use_hostcc = use_hostcc,
321 pyext = pyembed,
322 use_global_deps= use_global_deps)
324 bld.SET_BUILD_GROUP(group)
326 # the binary itself will depend on that object target
327 deps = TO_LIST(deps)
328 deps.append(obj_target)
330 t = bld(
331 features = features,
332 source = [],
333 target = binname,
334 samba_deps = deps,
335 samba_includes = includes,
336 local_include = local_include,
337 samba_modules = modules,
338 top = True,
339 samba_subsystem= subsystem_name,
340 install_path = None,
341 samba_inst_path= install_path,
342 samba_install = install
345 if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
346 bld.MANPAGES(manpages)
348 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
351 #################################################################
352 def SAMBA_MODULE(bld, modname, source,
353 deps='',
354 includes='',
355 subsystem=None,
356 init_function=None,
357 module_init_name='samba_init_module',
358 autoproto=None,
359 autoproto_extra_source='',
360 cflags='',
361 internal_module=True,
362 local_include=True,
363 vars=None,
364 enabled=True,
365 pyembed=True,
367 '''define a Samba module.'''
369 source = bld.EXPAND_VARIABLES(source, vars=vars)
371 if internal_module or BUILTIN_LIBRARY(bld, modname):
372 bld.SAMBA_SUBSYSTEM(modname, source,
373 deps=deps,
374 includes=includes,
375 autoproto=autoproto,
376 autoproto_extra_source=autoproto_extra_source,
377 cflags=cflags,
378 local_include=local_include,
379 enabled=enabled)
381 bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
382 return
384 if not enabled:
385 SET_TARGET_TYPE(bld, modname, 'DISABLED')
386 return
388 obj_target = modname + '.objlist'
390 realname = modname
391 if subsystem is not None:
392 deps += ' ' + subsystem
393 while realname.startswith("lib"+subsystem+"_"):
394 realname = realname[len("lib"+subsystem+"_"):]
395 while realname.startswith(subsystem+"_"):
396 realname = realname[len(subsystem+"_"):]
398 realname = bld.make_libname(realname)
399 while realname.startswith("lib"):
400 realname = realname[len("lib"):]
402 build_link_name = "modules/%s/%s" % (subsystem, realname)
404 if init_function:
405 cflags += " -D%s=%s" % (init_function, module_init_name)
407 bld.SAMBA_LIBRARY(modname,
408 source,
409 deps=deps,
410 cflags=cflags,
411 realname = realname,
412 autoproto = autoproto,
413 local_include=local_include,
414 vars=vars,
415 link_name=build_link_name,
416 install_path="${MODULESDIR}/%s" % subsystem,
417 pyembed=pyembed,
421 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
424 #################################################################
425 def SAMBA_SUBSYSTEM(bld, modname, source,
426 deps='',
427 public_deps='',
428 includes='',
429 public_headers=None,
430 header_path=None,
431 cflags='',
432 cflags_end=None,
433 group='main',
434 init_function_sentinal=None,
435 autoproto=None,
436 autoproto_extra_source='',
437 depends_on='',
438 local_include=True,
439 local_include_first=True,
440 subsystem_name=None,
441 enabled=True,
442 use_hostcc=False,
443 use_global_deps=True,
444 vars=None,
445 hide_symbols=False,
446 pyext=False):
447 '''define a Samba subsystem'''
449 if not enabled:
450 SET_TARGET_TYPE(bld, modname, 'DISABLED')
451 return
453 # remember empty subsystems, so we can strip the dependencies
454 if ((source == '') or (source == [])) and deps == '' and public_deps == '':
455 SET_TARGET_TYPE(bld, modname, 'EMPTY')
456 return
458 if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
459 return
461 source = bld.EXPAND_VARIABLES(source, vars=vars)
462 source = unique_list(TO_LIST(source))
464 deps += ' ' + public_deps
466 bld.SET_BUILD_GROUP(group)
468 features = 'cc'
469 if pyext:
470 features += ' pyext'
472 t = bld(
473 features = features,
474 source = source,
475 target = modname,
476 samba_cflags = CURRENT_CFLAGS(bld, modname, cflags, hide_symbols=hide_symbols),
477 depends_on = depends_on,
478 samba_deps = TO_LIST(deps),
479 samba_includes = includes,
480 local_include = local_include,
481 local_include_first = local_include_first,
482 samba_subsystem= subsystem_name,
483 samba_use_hostcc = use_hostcc,
484 samba_use_global_deps = use_global_deps
487 if cflags_end is not None:
488 t.samba_cflags.extend(TO_LIST(cflags_end))
490 if autoproto is not None:
491 bld.SAMBA_AUTOPROTO(autoproto, source + TO_LIST(autoproto_extra_source))
492 if public_headers is not None:
493 bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
494 return t
497 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
500 def SAMBA_GENERATOR(bld, name, rule, source='', target='',
501 group='generators', enabled=True,
502 public_headers=None,
503 header_path=None,
504 vars=None,
505 always=False):
506 '''A generic source generator target'''
508 if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
509 return
511 if not enabled:
512 return
514 bld.SET_BUILD_GROUP(group)
515 t = bld(
516 rule=rule,
517 source=bld.EXPAND_VARIABLES(source, vars=vars),
518 target=target,
519 shell=isinstance(rule, str),
520 on_results=True,
521 before='cc',
522 ext_out='.c',
523 samba_type='GENERATOR',
524 vars = [rule],
525 name=name)
527 if always:
528 t.always = True
530 if public_headers is not None:
531 bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
532 return t
533 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
537 @runonce
538 def SETUP_BUILD_GROUPS(bld):
539 '''setup build groups used to ensure that the different build
540 phases happen consecutively'''
541 bld.p_ln = bld.srcnode # we do want to see all targets!
542 bld.env['USING_BUILD_GROUPS'] = True
543 bld.add_group('setup')
544 bld.add_group('build_compiler_source')
545 bld.add_group('vscripts')
546 bld.add_group('base_libraries')
547 bld.add_group('generators')
548 bld.add_group('compiler_prototypes')
549 bld.add_group('compiler_libraries')
550 bld.add_group('build_compilers')
551 bld.add_group('build_source')
552 bld.add_group('prototypes')
553 bld.add_group('main')
554 bld.add_group('symbolcheck')
555 bld.add_group('libraries')
556 bld.add_group('binaries')
557 bld.add_group('syslibcheck')
558 bld.add_group('final')
559 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
562 def SET_BUILD_GROUP(bld, group):
563 '''set the current build group'''
564 if not 'USING_BUILD_GROUPS' in bld.env:
565 return
566 bld.set_group(group)
567 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
571 @conf
572 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
573 """use timestamps instead of file contents for deps
574 this currently doesn't work"""
575 def h_file(filename):
576 import stat
577 st = os.stat(filename)
578 if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
579 m = Utils.md5()
580 m.update(str(st.st_mtime))
581 m.update(str(st.st_size))
582 m.update(filename)
583 return m.digest()
584 Utils.h_file = h_file
588 t = Task.simple_task_type('copy_script', 'rm -f "${LINK_TARGET}" && ln -s "${SRC[0].abspath(env)}" ${LINK_TARGET}',
589 shell=True, color='PINK', ext_in='.bin')
590 t.quiet = True
592 @feature('copy_script')
593 @before('apply_link')
594 def copy_script(self):
595 tsk = self.create_task('copy_script', self.allnodes[0])
596 tsk.env.TARGET = self.target
598 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
599 '''used to copy scripts from the source tree into the build directory
600 for use by selftest'''
602 source = bld.path.ant_glob(pattern)
604 bld.SET_BUILD_GROUP('build_source')
605 for s in TO_LIST(source):
606 iname = s
607 if installname != None:
608 iname = installname
609 target = os.path.join(installdir, iname)
610 tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
611 mkdir_p(tgtdir)
612 t = bld(features='copy_script',
613 source = s,
614 target = target,
615 always = True,
616 install_path = None)
617 t.env.LINK_TARGET = target
619 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
622 def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
623 python_fixup=False, destname=None, base_name=None):
624 '''install a file'''
625 destdir = bld.EXPAND_VARIABLES(destdir)
626 if not destname:
627 destname = file
628 if flat:
629 destname = os.path.basename(destname)
630 dest = os.path.join(destdir, destname)
631 if python_fixup:
632 # fixup the python path it will use to find Samba modules
633 inst_file = file + '.inst'
634 if bld.env["PYTHONDIR"] not in sys.path:
635 regex = "s|\(sys.path.insert.*\)bin/python\(.*\)$|\\1${PYTHONDIR}\\2|g"
636 else:
637 # Eliminate updating sys.path if the target python dir is already
638 # in python path.
639 regex = "s|sys.path.insert.*bin/python.*$||g"
640 bld.SAMBA_GENERATOR('python_%s' % destname,
641 rule="sed '%s' < ${SRC} > ${TGT}" % regex,
642 source=file,
643 target=inst_file)
644 file = inst_file
645 if base_name:
646 file = os.path.join(base_name, file)
647 bld.install_as(dest, file, chmod=chmod)
650 def INSTALL_FILES(bld, destdir, files, chmod=MODE_644, flat=False,
651 python_fixup=False, destname=None, base_name=None):
652 '''install a set of files'''
653 for f in TO_LIST(files):
654 install_file(bld, destdir, f, chmod=chmod, flat=flat,
655 python_fixup=python_fixup, destname=destname,
656 base_name=base_name)
657 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
660 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
661 python_fixup=False, exclude=None, trim_path=None):
662 '''install a set of files matching a wildcard pattern'''
663 files=TO_LIST(bld.path.ant_glob(pattern))
664 if trim_path:
665 files2 = []
666 for f in files:
667 files2.append(os_path_relpath(f, trim_path))
668 files = files2
670 if exclude:
671 for f in files[:]:
672 if fnmatch.fnmatch(f, exclude):
673 files.remove(f)
674 INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat,
675 python_fixup=python_fixup, base_name=trim_path)
676 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
679 def INSTALL_DIRS(bld, destdir, dirs):
680 '''install a set of directories'''
681 destdir = bld.EXPAND_VARIABLES(destdir)
682 dirs = bld.EXPAND_VARIABLES(dirs)
683 for d in TO_LIST(dirs):
684 bld.install_dir(os.path.join(destdir, d))
685 Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
688 re_header = re.compile('#include[ \t]*"([^"]+)"', re.I | re.M)
689 class header_task(Task.Task):
691 The public headers (the one installed on the system) have both
692 different paths and contents, so the rename is not enough.
694 Intermediate .inst.h files are created because path manipulation
695 may be slow. The substitution is thus performed only once.
698 name = 'header'
699 color = 'PINK'
700 vars = ['INCLUDEDIR', 'HEADER_DEPS']
702 def run(self):
703 txt = self.inputs[0].read(self.env)
705 # hard-coded string, but only present in samba4 (I promise, you won't feel a thing)
706 txt = txt.replace('#if _SAMBA_BUILD_ == 4', '#if 1\n')
708 # use a regexp to substitute the #include lines in the files
709 map = self.generator.bld.hnodemap
710 dirnodes = self.generator.bld.hnodedirs
711 def repl(m):
712 if m.group(1):
713 s = m.group(1)
715 # pokemon headers: gotta catch'em all!
716 fin = s
717 if s.startswith('bin/default'):
718 node = self.generator.bld.srcnode.find_resource(s.replace('bin/default/', ''))
719 if not node:
720 Logs.warn('could not find the public header for %r' % s)
721 elif node.id in map:
722 fin = map[node.id]
723 else:
724 Logs.warn('could not find the public header replacement for build header %r' % s)
725 else:
726 # this part is more difficult since the path may be relative to anything
727 for dirnode in dirnodes:
728 node = dirnode.find_resource(s)
729 if node:
730 if node.id in map:
731 fin = map[node.id]
732 break
733 else:
734 Logs.warn('could not find the public header replacement for source header %r %r' % (s, node))
735 else:
736 Logs.warn('-> could not find the public header for %r' % s)
738 return "#include <%s>" % fin
739 return ''
741 txt = re_header.sub(repl, txt)
743 # and write the output file
744 f = None
745 try:
746 f = open(self.outputs[0].abspath(self.env), 'w')
747 f.write(txt)
748 finally:
749 if f:
750 f.close()
752 @TaskGen.feature('pubh')
753 def make_public_headers(self):
755 collect the public headers to process and to install, then
756 create the substitutions (name and contents)
759 if not self.bld.is_install:
760 # install time only (lazy)
761 return
763 # keep two variables
764 # hnodedirs: list of folders for searching the headers
765 # hnodemap: node ids and replacement string (node objects are unique)
766 try:
767 self.bld.hnodedirs.append(self.path)
768 except AttributeError:
769 self.bld.hnodemap = {}
770 self.bld.hnodedirs = [self.bld.srcnode, self.path]
772 for k in 'source4 source4/include lib/talloc lib/tevent/ source4/lib/ldb/include/'.split():
773 node = self.bld.srcnode.find_dir(k)
774 if node:
775 self.bld.hnodedirs.append(node)
777 header_path = getattr(self, 'header_path', None) or ''
779 for x in self.to_list(self.headers):
781 # too complicated, but what was the original idea?
782 if isinstance(header_path, list):
783 add_dir = ''
784 for (p1, dir) in header_path:
785 lst = self.to_list(p1)
786 for p2 in lst:
787 if fnmatch.fnmatch(x, p2):
788 add_dir = dir
789 break
790 else:
791 continue
792 break
793 inst_path = add_dir
794 else:
795 inst_path = header_path
797 dest = ''
798 name = x
799 if x.find(':') != -1:
800 s = x.split(':')
801 name = s[0]
802 dest = s[1]
804 inn = self.path.find_resource(name)
806 if not inn:
807 raise ValueError("could not find the public header %r in %r" % (name, self.path))
808 out = inn.change_ext('.inst.h')
809 self.create_task('header', inn, out)
811 if not dest:
812 dest = inn.name
814 if inst_path:
815 inst_path = inst_path + '/'
816 inst_path = inst_path + dest
818 self.bld.install_as('${INCLUDEDIR}/%s' % inst_path, out, self.env)
820 self.bld.hnodemap[inn.id] = inst_path
822 # create a hash (not md5) to make sure the headers are re-created if something changes
823 val = 0
824 lst = list(self.bld.hnodemap.keys())
825 lst.sort()
826 for k in lst:
827 val = hash((val, k, self.bld.hnodemap[k]))
828 self.bld.env.HEADER_DEPS = val
830 def PUBLIC_HEADERS(bld, public_headers, header_path=None):
831 '''install some headers
833 header_path may either be a string that is added to the INCLUDEDIR,
834 or it can be a dictionary of wildcard patterns which map to destination
835 directories relative to INCLUDEDIR
837 bld.SET_BUILD_GROUP('final')
838 ret = bld(features=['pubh'], headers=public_headers, header_path=header_path)
839 return ret
840 Build.BuildContext.PUBLIC_HEADERS = PUBLIC_HEADERS
843 def MANPAGES(bld, manpages):
844 '''build and install manual pages'''
845 bld.env.MAN_XSL = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
846 for m in manpages.split():
847 source = m + '.xml'
848 bld.SAMBA_GENERATOR(m,
849 source=source,
850 target=m,
851 group='final',
852 rule='${XSLTPROC} -o ${TGT} --nonet ${MAN_XSL} ${SRC}'
854 bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
855 Build.BuildContext.MANPAGES = MANPAGES
858 #############################################################
859 # give a nicer display when building different types of files
860 def progress_display(self, msg, fname):
861 col1 = Logs.colors(self.color)
862 col2 = Logs.colors.NORMAL
863 total = self.position[1]
864 n = len(str(total))
865 fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg)
866 return fs % (self.position[0], self.position[1], col1, fname, col2)
868 def link_display(self):
869 if Options.options.progress_bar != 0:
870 return Task.Task.old_display(self)
871 fname = self.outputs[0].bldpath(self.env)
872 return progress_display(self, 'Linking', fname)
873 Task.TaskBase.classes['cc_link'].display = link_display
875 def samba_display(self):
876 if Options.options.progress_bar != 0:
877 return Task.Task.old_display(self)
879 targets = LOCAL_CACHE(self, 'TARGET_TYPE')
880 if self.name in targets:
881 target_type = targets[self.name]
882 type_map = { 'GENERATOR' : 'Generating',
883 'PROTOTYPE' : 'Generating'
885 if target_type in type_map:
886 return progress_display(self, type_map[target_type], self.name)
888 if len(self.inputs) == 0:
889 return Task.Task.old_display(self)
891 fname = self.inputs[0].bldpath(self.env)
892 if fname[0:3] == '../':
893 fname = fname[3:]
894 ext_loc = fname.rfind('.')
895 if ext_loc == -1:
896 return Task.Task.old_display(self)
897 ext = fname[ext_loc:]
899 ext_map = { '.idl' : 'Compiling IDL',
900 '.et' : 'Compiling ERRTABLE',
901 '.asn1': 'Compiling ASN1',
902 '.c' : 'Compiling' }
903 if ext in ext_map:
904 return progress_display(self, ext_map[ext], fname)
905 return Task.Task.old_display(self)
907 Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display
908 Task.TaskBase.classes['Task'].display = samba_display
911 @after('apply_link')
912 @feature('cshlib')
913 def apply_bundle_remove_dynamiclib_patch(self):
914 if self.env['MACBUNDLE'] or getattr(self,'mac_bundle',False):
915 if not getattr(self,'vnum',None):
916 try:
917 self.env['LINKFLAGS'].remove('-dynamiclib')
918 self.env['LINKFLAGS'].remove('-single_module')
919 except ValueError:
920 pass