s3-dceprc: consolidate use of dcerpc_push_dcerpc_auth()
[Samba.git] / buildtools / wafsamba / wafsamba.py
blob21ed001372bbf40f510d73aa085e1908011608ba
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_errtable import *
18 from samba_asn1 import *
19 from samba_autoproto import *
20 from samba_python import *
21 from samba_deps import *
22 from samba_bundled import *
23 import samba_install
24 import samba_conftests
25 import samba_abi
26 import tru64cc
27 import irixcc
28 import generic_cc
29 import samba_dist
30 import samba_wildcard
32 # some systems have broken threading in python
33 if os.environ.get('WAF_NOTHREADS') == '1':
34 import nothreads
36 LIB_PATH="shared"
38 os.putenv('PYTHONUNBUFFERED', '1')
41 if Constants.HEXVERSION < 0x105016:
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.
47 Alternatively, please use ./autogen-waf.sh, and then
48 run ./configure and make as usual. That will call the right version of waf.
49 ''')
50 sys.exit(1)
53 @conf
54 def SAMBA_BUILD_ENV(conf):
55 '''create the samba build environment'''
56 conf.env.BUILD_DIRECTORY = conf.blddir
57 mkdir_p(os.path.join(conf.blddir, LIB_PATH))
58 mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
59 # this allows all of the bin/shared and bin/python targets
60 # to be expressed in terms of build directory paths
61 mkdir_p(os.path.join(conf.blddir, 'default'))
62 for p in ['python','shared']:
63 link_target = os.path.join(conf.blddir, 'default/' + p)
64 if not os.path.lexists(link_target):
65 os.symlink('../' + p, link_target)
67 # get perl to put the blib files in the build directory
68 blib_bld = os.path.join(conf.blddir, 'default/pidl/blib')
69 blib_src = os.path.join(conf.srcdir, 'pidl/blib')
70 mkdir_p(blib_bld + '/man1')
71 mkdir_p(blib_bld + '/man3')
72 if os.path.islink(blib_src):
73 os.unlink(blib_src)
74 elif os.path.exists(blib_src):
75 shutil.rmtree(blib_src)
78 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
79 '''add an init_function to the list for a subsystem'''
80 if init_function is None:
81 return
82 bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
83 cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
84 if not subsystem in cache:
85 cache[subsystem] = []
86 cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
87 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
91 #################################################################
92 def SAMBA_LIBRARY(bld, libname, source,
93 deps='',
94 public_deps='',
95 includes='',
96 public_headers=None,
97 header_path=None,
98 pc_files=None,
99 vnum=None,
100 cflags='',
101 external_library=False,
102 realname=None,
103 autoproto=None,
104 group='main',
105 depends_on='',
106 local_include=True,
107 vars=None,
108 install_path=None,
109 install=True,
110 needs_python=False,
111 target_type='LIBRARY',
112 bundled_extension=True,
113 link_name=None,
114 abi_file=None,
115 abi_match=None,
116 hide_symbols=False,
117 is_bundled=False,
118 manpages=None,
119 enabled=True):
120 '''define a Samba library'''
122 if not enabled:
123 SET_TARGET_TYPE(bld, libname, 'DISABLED')
124 return
126 source = bld.EXPAND_VARIABLES(source, vars=vars)
128 # remember empty libraries, so we can strip the dependencies
129 if ((source == '') or (source == [])) and deps == '' and public_deps == '':
130 SET_TARGET_TYPE(bld, libname, 'EMPTY')
131 return
133 if BUILTIN_LIBRARY(bld, libname):
134 obj_target = libname
135 else:
136 obj_target = libname + '.objlist'
138 # first create a target for building the object files for this library
139 # by separating in this way, we avoid recompiling the C files
140 # separately for the install library and the build library
141 bld.SAMBA_SUBSYSTEM(obj_target,
142 source = source,
143 deps = deps,
144 public_deps = public_deps,
145 includes = includes,
146 public_headers = public_headers,
147 header_path = header_path,
148 cflags = cflags,
149 group = group,
150 autoproto = autoproto,
151 depends_on = depends_on,
152 needs_python = needs_python,
153 hide_symbols = hide_symbols,
154 local_include = local_include)
156 if BUILTIN_LIBRARY(bld, libname):
157 return
159 if not SET_TARGET_TYPE(bld, libname, target_type):
160 return
162 # the library itself will depend on that object target
163 deps += ' ' + public_deps
164 deps = TO_LIST(deps)
165 deps.append(obj_target)
167 if target_type == 'PYTHON' or realname or not is_bundled:
168 # Sanitize the library name
169 bundled_name = libname.lower().replace('_', '-')
170 while bundled_name.startswith("lib"):
171 bundled_name = bundled_name[3:]
172 else:
173 bundled_name = BUNDLED_NAME(bld, libname, bundled_extension)
175 features = 'cc cshlib symlink_lib install_lib'
176 if target_type == 'PYTHON':
177 features += ' pyext'
178 elif needs_python:
179 features += ' pyembed'
180 if abi_file:
181 features += ' abi_check'
183 if abi_file:
184 abi_file = os.path.join(bld.curdir, abi_file)
186 bld.SET_BUILD_GROUP(group)
187 t = bld(
188 features = features,
189 source = [],
190 target = bundled_name,
191 samba_cflags = CURRENT_CFLAGS(bld, libname, cflags),
192 depends_on = depends_on,
193 samba_deps = deps,
194 samba_includes = includes,
195 local_include = local_include,
196 vnum = vnum,
197 install_path = None,
198 samba_inst_path = install_path,
199 name = libname,
200 samba_realname = realname,
201 samba_install = install,
202 abi_file = abi_file,
203 abi_match = abi_match,
204 is_bundled = is_bundled
207 if realname and not link_name:
208 link_name = 'shared/%s' % realname
210 if link_name:
211 t.link_name = link_name
213 if pc_files is not None:
214 bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
216 if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
217 bld.MANPAGES(manpages)
220 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
223 #################################################################
224 def SAMBA_BINARY(bld, binname, source,
225 deps='',
226 includes='',
227 public_headers=None,
228 header_path=None,
229 modules=None,
230 ldflags=None,
231 cflags='',
232 autoproto=None,
233 use_hostcc=False,
234 use_global_deps=True,
235 compiler=None,
236 group='binaries',
237 manpages=None,
238 local_include=True,
239 subsystem_name=None,
240 needs_python=False,
241 vars=None,
242 install=True,
243 install_path=None,
244 enabled=True):
245 '''define a Samba binary'''
247 if not enabled:
248 SET_TARGET_TYPE(bld, binname, 'DISABLED')
249 return
251 if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
252 return
254 features = 'cc cprogram symlink_bin install_bin'
255 if needs_python:
256 features += ' pyembed'
258 obj_target = binname + '.objlist'
260 source = bld.EXPAND_VARIABLES(source, vars=vars)
261 source = unique_list(TO_LIST(source))
263 # first create a target for building the object files for this binary
264 # by separating in this way, we avoid recompiling the C files
265 # separately for the install binary and the build binary
266 bld.SAMBA_SUBSYSTEM(obj_target,
267 source = source,
268 deps = deps,
269 includes = includes,
270 cflags = cflags,
271 group = group,
272 autoproto = autoproto,
273 subsystem_name = subsystem_name,
274 needs_python = needs_python,
275 local_include = local_include,
276 use_hostcc = use_hostcc,
277 use_global_deps= use_global_deps)
279 bld.SET_BUILD_GROUP(group)
281 # the binary itself will depend on that object target
282 deps = TO_LIST(deps)
283 deps.append(obj_target)
285 t = bld(
286 features = features,
287 source = [],
288 target = binname,
289 samba_cflags = CURRENT_CFLAGS(bld, binname, cflags),
290 samba_deps = deps,
291 samba_includes = includes,
292 local_include = local_include,
293 samba_modules = modules,
294 top = True,
295 samba_subsystem= subsystem_name,
296 install_path = None,
297 samba_inst_path= install_path,
298 samba_install = install
301 # setup the subsystem_name as an alias for the real
302 # binary name, so it can be found when expanding
303 # subsystem dependencies
304 if subsystem_name is not None:
305 bld.TARGET_ALIAS(subsystem_name, binname)
307 if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
308 bld.MANPAGES(manpages)
310 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
313 #################################################################
314 def SAMBA_MODULE(bld, modname, source,
315 deps='',
316 includes='',
317 subsystem=None,
318 init_function=None,
319 autoproto=None,
320 autoproto_extra_source='',
321 aliases=None,
322 cflags='',
323 internal_module=True,
324 local_include=True,
325 vars=None,
326 enabled=True):
327 '''define a Samba module.'''
329 source = bld.EXPAND_VARIABLES(source, vars=vars)
331 if internal_module or BUILTIN_LIBRARY(bld, modname):
332 # treat internal modules as subsystems for now
333 if subsystem is not None:
334 deps += ' ' + subsystem
336 bld.SAMBA_SUBSYSTEM(modname, source,
337 deps=deps,
338 includes=includes,
339 autoproto=autoproto,
340 autoproto_extra_source=autoproto_extra_source,
341 cflags=cflags,
342 local_include=local_include,
343 enabled=enabled)
345 bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
346 return
348 if not enabled:
349 SET_TARGET_TYPE(bld, modname, 'DISABLED')
350 return
352 if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
353 return
355 obj_target = modname + '.objlist'
357 bld.SAMBA_SUBSYSTEM(obj_target, source,
358 deps=deps,
359 includes=includes,
360 autoproto=autoproto,
361 autoproto_extra_source=autoproto_extra_source,
362 cflags=cflags,
363 local_include=local_include,
364 enabled=enabled)
366 deps = TO_LIST(deps)
367 deps.append(obj_target)
368 realname = modname
369 if subsystem is not None:
370 deps.append(subsystem)
371 while realname.startswith("lib"+subsystem+"_"):
372 realname = realname[len("lib"+subsystem+"_"):]
373 while realname.startswith(subsystem+"_"):
374 realname = realname[len(subsystem+"_"):]
375 while realname.startswith("lib"):
376 realname = realname[len("lib"):]
378 bld.SET_BUILD_GROUP('main')
379 t = bld(
380 features = 'cc cshlib install_lib',
381 source = [],
382 target = realname,
383 name = modname,
384 link_name = "modules/%s/%s.${SHLIBEXT}" % (subsystem, realname),
385 samba_cflags = CURRENT_CFLAGS(bld, modname, cflags),
386 samba_includes = includes,
387 local_include = local_include,
388 samba_deps = deps,
389 install_path = None,
390 samba_inst_path= "${MODULESDIR}/%s" % subsystem,
391 samba_realname = realname+ ".${SHLIBEXT}",
392 vnum = None,
393 samba_install = True,
394 is_bundled = False,
397 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
400 #################################################################
401 def SAMBA_SUBSYSTEM(bld, modname, source,
402 deps='',
403 public_deps='',
404 includes='',
405 public_headers=None,
406 header_path=None,
407 cflags='',
408 cflags_end=None,
409 group='main',
410 init_function_sentinal=None,
411 heimdal_autoproto=None,
412 heimdal_autoproto_options=None,
413 heimdal_autoproto_private=None,
414 autoproto=None,
415 autoproto_extra_source='',
416 depends_on='',
417 local_include=True,
418 local_include_first=True,
419 subsystem_name=None,
420 enabled=True,
421 use_hostcc=False,
422 use_global_deps=True,
423 vars=None,
424 hide_symbols=False,
425 needs_python=False):
426 '''define a Samba subsystem'''
428 if not enabled:
429 SET_TARGET_TYPE(bld, modname, 'DISABLED')
430 return
432 # remember empty subsystems, so we can strip the dependencies
433 if ((source == '') or (source == [])) and deps == '' and public_deps == '':
434 SET_TARGET_TYPE(bld, modname, 'EMPTY')
435 return
437 if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
438 return
440 source = bld.EXPAND_VARIABLES(source, vars=vars)
441 source = unique_list(TO_LIST(source))
443 deps += ' ' + public_deps
445 bld.SET_BUILD_GROUP(group)
447 features = 'cc'
448 if needs_python:
449 features += ' pyext'
451 t = bld(
452 features = features,
453 source = source,
454 target = modname,
455 samba_cflags = CURRENT_CFLAGS(bld, modname, cflags, hide_symbols=hide_symbols),
456 depends_on = depends_on,
457 samba_deps = TO_LIST(deps),
458 samba_includes = includes,
459 local_include = local_include,
460 local_include_first = local_include_first,
461 samba_subsystem= subsystem_name,
462 samba_use_hostcc = use_hostcc,
463 samba_use_global_deps = use_global_deps
466 if cflags_end is not None:
467 t.samba_cflags.extend(TO_LIST(cflags_end))
469 if heimdal_autoproto is not None:
470 bld.HEIMDAL_AUTOPROTO(heimdal_autoproto, source, options=heimdal_autoproto_options)
471 if heimdal_autoproto_private is not None:
472 bld.HEIMDAL_AUTOPROTO_PRIVATE(heimdal_autoproto_private, source)
473 if autoproto is not None:
474 bld.SAMBA_AUTOPROTO(autoproto, source + TO_LIST(autoproto_extra_source))
475 if public_headers is not None:
476 bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
477 return t
480 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
483 def SAMBA_GENERATOR(bld, name, rule, source='', target='',
484 group='generators', enabled=True,
485 public_headers=None,
486 header_path=None,
487 vars=None,
488 always=False):
489 '''A generic source generator target'''
491 if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
492 return
494 if not enabled:
495 return
497 bld.SET_BUILD_GROUP(group)
498 t = bld(
499 rule=rule,
500 source=bld.EXPAND_VARIABLES(source, vars=vars),
501 target=target,
502 shell=isinstance(rule, str),
503 on_results=True,
504 before='cc',
505 ext_out='.c',
506 name=name)
508 if always:
509 t.always = True
511 if public_headers is not None:
512 bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
513 return t
514 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
518 @runonce
519 def SETUP_BUILD_GROUPS(bld):
520 '''setup build groups used to ensure that the different build
521 phases happen consecutively'''
522 bld.p_ln = bld.srcnode # we do want to see all targets!
523 bld.env['USING_BUILD_GROUPS'] = True
524 bld.add_group('setup')
525 bld.add_group('build_compiler_source')
526 bld.add_group('base_libraries')
527 bld.add_group('generators')
528 bld.add_group('compiler_prototypes')
529 bld.add_group('compiler_libraries')
530 bld.add_group('build_compilers')
531 bld.add_group('build_source')
532 bld.add_group('prototypes')
533 bld.add_group('main')
534 bld.add_group('binaries')
535 bld.add_group('final')
536 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
539 def SET_BUILD_GROUP(bld, group):
540 '''set the current build group'''
541 if not 'USING_BUILD_GROUPS' in bld.env:
542 return
543 bld.set_group(group)
544 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
548 @conf
549 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
550 """use timestamps instead of file contents for deps
551 this currently doesn't work"""
552 def h_file(filename):
553 import stat
554 st = os.stat(filename)
555 if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
556 m = Utils.md5()
557 m.update(str(st.st_mtime))
558 m.update(str(st.st_size))
559 m.update(filename)
560 return m.digest()
561 Utils.h_file = h_file
565 t = Task.simple_task_type('copy_script', 'rm -f ${LINK_TARGET} && ln -s ${SRC[0].abspath(env)} ${LINK_TARGET}',
566 shell=True, color='PINK', ext_in='.bin')
567 t.quiet = True
569 @feature('copy_script')
570 @before('apply_link')
571 def copy_script(self):
572 tsk = self.create_task('copy_script', self.allnodes[0])
573 tsk.env.TARGET = self.target
575 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
576 '''used to copy scripts from the source tree into the build directory
577 for use by selftest'''
579 source = bld.path.ant_glob(pattern)
581 bld.SET_BUILD_GROUP('build_source')
582 for s in TO_LIST(source):
583 iname = s
584 if installname != None:
585 iname = installname
586 target = os.path.join(installdir, iname)
587 tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
588 mkdir_p(tgtdir)
589 t = bld(features='copy_script',
590 source = s,
591 target = target,
592 always = True,
593 install_path = None)
594 t.env.LINK_TARGET = target
596 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
599 def install_file(bld, destdir, file, chmod=0644, flat=False,
600 python_fixup=False, destname=None, base_name=None):
601 '''install a file'''
602 destdir = bld.EXPAND_VARIABLES(destdir)
603 if not destname:
604 destname = file
605 if flat:
606 destname = os.path.basename(destname)
607 dest = os.path.join(destdir, destname)
608 if python_fixup:
609 # fixup the python path it will use to find Samba modules
610 inst_file = file + '.inst'
611 bld.SAMBA_GENERATOR('python_%s' % destname,
612 rule="sed 's|\(sys.path.insert.*\)bin/python\(.*\)$|\\1${PYTHONDIR}\\2|g' < ${SRC} > ${TGT}",
613 source=file,
614 target=inst_file)
615 file = inst_file
616 if base_name:
617 file = os.path.join(base_name, file)
618 bld.install_as(dest, file, chmod=chmod)
621 def INSTALL_FILES(bld, destdir, files, chmod=0644, flat=False,
622 python_fixup=False, destname=None, base_name=None):
623 '''install a set of files'''
624 for f in TO_LIST(files):
625 install_file(bld, destdir, f, chmod=chmod, flat=flat,
626 python_fixup=python_fixup, destname=destname,
627 base_name=base_name)
628 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
631 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=0644, flat=False,
632 python_fixup=False, exclude=None, trim_path=None):
633 '''install a set of files matching a wildcard pattern'''
634 files=TO_LIST(bld.path.ant_glob(pattern))
635 if trim_path:
636 files2 = []
637 for f in files:
638 files2.append(os_path_relpath(f, trim_path))
639 files = files2
641 if exclude:
642 for f in files[:]:
643 if fnmatch.fnmatch(f, exclude):
644 files.remove(f)
645 INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat,
646 python_fixup=python_fixup, base_name=trim_path)
647 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
650 def INSTALL_DIRS(bld, destdir, dirs):
651 '''install a set of directories'''
652 destdir = bld.EXPAND_VARIABLES(destdir)
653 dirs = bld.EXPAND_VARIABLES(dirs)
654 for d in TO_LIST(dirs):
655 bld.install_dir(os.path.join(destdir, d))
656 Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
659 re_header = re.compile('#include[ \t]*"([^"]+)"', re.I | re.M)
660 class header_task(Task.Task):
662 The public headers (the one installed on the system) have both
663 different paths and contents, so the rename is not enough.
665 Intermediate .inst.h files are created because path manipulation
666 may be slow. The substitution is thus performed only once.
669 name = 'header'
670 color = 'PINK'
671 vars = ['INCLUDEDIR', 'HEADER_DEPS']
673 def run(self):
674 txt = self.inputs[0].read(self.env)
676 # hard-coded string, but only present in samba4 (I promise, you won't feel a thing)
677 txt = txt.replace('#if _SAMBA_BUILD_ == 4', '#if 1\n')
679 # use a regexp to substitute the #include lines in the files
680 map = self.generator.bld.hnodemap
681 dirnodes = self.generator.bld.hnodedirs
682 def repl(m):
683 if m.group(1):
684 s = m.group(1)
686 # pokemon headers: gotta catch'em all!
687 fin = s
688 if s.startswith('bin/default'):
689 node = self.generator.bld.srcnode.find_resource(s.replace('bin/default/', ''))
690 if not node:
691 Logs.warn('could not find the public header for %r' % s)
692 elif node.id in map:
693 fin = map[node.id]
694 else:
695 Logs.warn('could not find the public header replacement for build header %r' % s)
696 else:
697 # this part is more difficult since the path may be relative to anything
698 for dirnode in dirnodes:
699 node = dirnode.find_resource(s)
700 if node:
701 if node.id in map:
702 fin = map[node.id]
703 break
704 else:
705 Logs.warn('could not find the public header replacement for source header %r %r' % (s, node))
706 else:
707 Logs.warn('-> could not find the public header for %r' % s)
709 return "#include <%s>" % fin
710 return ''
712 txt = re_header.sub(repl, txt)
714 # and write the output file
715 f = None
716 try:
717 f = open(self.outputs[0].abspath(self.env), 'w')
718 f.write(txt)
719 finally:
720 if f:
721 f.close()
723 @TaskGen.feature('pubh')
724 def make_public_headers(self):
726 collect the public headers to process and to install, then
727 create the substitutions (name and contents)
730 if not self.bld.is_install:
731 # install time only (lazy)
732 return
734 # keep two variables
735 # hnodedirs: list of folders for searching the headers
736 # hnodemap: node ids and replacement string (node objects are unique)
737 try:
738 self.bld.hnodedirs.append(self.path)
739 except AttributeError:
740 self.bld.hnodemap = {}
741 self.bld.hnodedirs = [self.bld.srcnode, self.path]
743 for k in 'source4 source4/include lib/talloc lib/tevent/ source4/lib/ldb/include/'.split():
744 node = self.bld.srcnode.find_dir(k)
745 if node:
746 self.bld.hnodedirs.append(node)
748 header_path = getattr(self, 'header_path', None) or ''
750 for x in self.to_list(self.headers):
752 # too complicated, but what was the original idea?
753 if isinstance(header_path, list):
754 add_dir = ''
755 for (p1, dir) in header_path:
756 lst = self.to_list(p1)
757 for p2 in lst:
758 if fnmatch.fnmatch(x, p2):
759 add_dir = dir
760 break
761 else:
762 continue
763 break
764 inst_path = add_dir
765 else:
766 inst_path = header_path
768 dest = ''
769 name = x
770 if x.find(':') != -1:
771 s = x.split(':')
772 name = s[0]
773 dest = s[1]
775 inn = self.path.find_resource(name)
777 if not inn:
778 raise ValueError("could not find the public header %r in %r" % (name, self.path))
779 out = inn.change_ext('.inst.h')
780 self.create_task('header', inn, out)
782 if not dest:
783 dest = inn.name
785 if inst_path:
786 inst_path = inst_path + '/'
787 inst_path = inst_path + dest
789 self.bld.install_as('${INCLUDEDIR}/%s' % inst_path, out, self.env)
791 self.bld.hnodemap[inn.id] = inst_path
793 # create a hash (not md5) to make sure the headers are re-created if something changes
794 val = 0
795 lst = list(self.bld.hnodemap.keys())
796 lst.sort()
797 for k in lst:
798 val = hash((val, k, self.bld.hnodemap[k]))
799 self.bld.env.HEADER_DEPS = val
801 def PUBLIC_HEADERS(bld, public_headers, header_path=None):
802 '''install some headers
804 header_path may either be a string that is added to the INCLUDEDIR,
805 or it can be a dictionary of wildcard patterns which map to destination
806 directories relative to INCLUDEDIR
808 bld.SET_BUILD_GROUP('final')
809 ret = bld(features=['pubh'], headers=public_headers, header_path=header_path)
810 return ret
811 Build.BuildContext.PUBLIC_HEADERS = PUBLIC_HEADERS
814 def subst_at_vars(task):
815 '''substiture @VAR@ style variables in a file'''
816 src = task.inputs[0].srcpath(task.env)
817 tgt = task.outputs[0].bldpath(task.env)
819 f = open(src, 'r')
820 s = f.read()
821 f.close()
822 # split on the vars
823 a = re.split('(@\w+@)', s)
824 out = []
825 done_var = {}
826 back_sub = [ ('PREFIX', '${prefix}'), ('EXEC_PREFIX', '${exec_prefix}')]
827 for v in a:
828 if re.match('@\w+@', v):
829 vname = v[1:-1]
830 if not vname in task.env and vname.upper() in task.env:
831 vname = vname.upper()
832 if not vname in task.env:
833 Logs.error("Unknown substitution %s in %s" % (v, task.name))
834 sys.exit(1)
835 v = SUBST_VARS_RECURSIVE(task.env[vname], task.env)
836 # now we back substitute the allowed pc vars
837 for (b, m) in back_sub:
838 s = task.env[b]
839 if s == v[0:len(s)]:
840 if not b in done_var:
841 # we don't want to substitute the first usage
842 done_var[b] = True
843 else:
844 v = m + v[len(s):]
845 break
846 out.append(v)
847 contents = ''.join(out)
848 f = open(tgt, 'w')
849 s = f.write(contents)
850 f.close()
851 return 0
855 def PKG_CONFIG_FILES(bld, pc_files, vnum=None):
856 '''install some pkg_config pc files'''
857 dest = '${PKGCONFIGDIR}'
858 dest = bld.EXPAND_VARIABLES(dest)
859 for f in TO_LIST(pc_files):
860 base=os.path.basename(f)
861 t = bld.SAMBA_GENERATOR('PKGCONFIG_%s' % base,
862 rule=subst_at_vars,
863 source=f+'.in',
864 target=f)
865 if vnum:
866 t.env.PACKAGE_VERSION = vnum
867 INSTALL_FILES(bld, dest, f, flat=True, destname=base)
868 Build.BuildContext.PKG_CONFIG_FILES = PKG_CONFIG_FILES
871 def MANPAGES(bld, manpages):
872 '''build and install manual pages'''
873 bld.env.MAN_XSL = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
874 for m in manpages.split():
875 source = m + '.xml'
876 bld.SAMBA_GENERATOR(m,
877 source=source,
878 target=m,
879 group='final',
880 rule='${XSLTPROC} -o ${TGT} --nonet ${MAN_XSL} ${SRC}'
882 bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
883 Build.BuildContext.MANPAGES = MANPAGES
886 #############################################################
887 # give a nicer display when building different types of files
888 def progress_display(self, msg, fname):
889 col1 = Logs.colors(self.color)
890 col2 = Logs.colors.NORMAL
891 total = self.position[1]
892 n = len(str(total))
893 fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg)
894 return fs % (self.position[0], self.position[1], col1, fname, col2)
896 def link_display(self):
897 if Options.options.progress_bar != 0:
898 return Task.Task.old_display(self)
899 fname = self.outputs[0].bldpath(self.env)
900 return progress_display(self, 'Linking', fname)
901 Task.TaskBase.classes['cc_link'].display = link_display
903 def samba_display(self):
904 if Options.options.progress_bar != 0:
905 return Task.Task.old_display(self)
907 targets = LOCAL_CACHE(self, 'TARGET_TYPE')
908 if self.name in targets:
909 target_type = targets[self.name]
910 type_map = { 'GENERATOR' : 'Generating',
911 'PROTOTYPE' : 'Generating'
913 if target_type in type_map:
914 return progress_display(self, type_map[target_type], self.name)
916 fname = self.inputs[0].bldpath(self.env)
917 if fname[0:3] == '../':
918 fname = fname[3:]
919 ext_loc = fname.rfind('.')
920 if ext_loc == -1:
921 return Task.Task.old_display(self)
922 ext = fname[ext_loc:]
924 ext_map = { '.idl' : 'Compiling IDL',
925 '.et' : 'Compiling ERRTABLE',
926 '.asn1': 'Compiling ASN1',
927 '.c' : 'Compiling' }
928 if ext in ext_map:
929 return progress_display(self, ext_map[ext], fname)
930 return Task.Task.old_display(self)
932 Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display
933 Task.TaskBase.classes['Task'].display = samba_display