2fc7eceee51538f43941063a3cc61a7e0f10ee4f
[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 Build, os, Options, Task, Utils, cc, TaskGen, fnmatch, re, shutil, Logs
5 from Configure import conf
6 from Logs import debug
7 from samba_utils import SUBST_VARS_RECURSIVE
8
9 # bring in the other samba modules
10 from samba_optimisation import *
11 from samba_utils import *
12 from samba_autoconf import *
13 from samba_patterns import *
14 from samba_pidl import *
15 from samba_errtable import *
16 from samba_asn1 import *
17 from samba_autoproto import *
18 from samba_python import *
19 from samba_deps import *
20 from samba_bundled import *
21 import samba_conftests
22 import nothreads
23
24 LIB_PATH="shared"
25
26 os.putenv('PYTHONUNBUFFERED', '1')
27
28 @conf
29 def SAMBA_BUILD_ENV(conf):
30     '''create the samba build environment'''
31     conf.env['BUILD_DIRECTORY'] = conf.blddir
32     mkdir_p(os.path.join(conf.blddir, LIB_PATH))
33     mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
34     # this allows all of the bin/shared and bin/python targets
35     # to be expressed in terms of build directory paths
36     for p in ['python','shared']:
37         link_target = os.path.join(conf.blddir, 'default/' + p)
38         if not os.path.lexists(link_target):
39             os.symlink('../' + p, link_target)
40
41     # get perl to put the blib files in the build directory
42     blib_bld = os.path.join(conf.blddir, 'default/pidl/blib')
43     blib_src = os.path.join(conf.srcdir, 'pidl/blib')
44     mkdir_p(blib_bld + '/man1')
45     mkdir_p(blib_bld + '/man3')
46     if os.path.islink(blib_src):
47         os.unlink(blib_src)
48     elif os.path.exists(blib_src):
49         shutil.rmtree(blib_src)
50     os.symlink(blib_bld, blib_src)
51
52
53
54 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
55     '''add an init_function to the list for a subsystem'''
56     if init_function is None:
57         return
58     bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
59     cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
60     if not subsystem in cache:
61         cache[subsystem] = []
62     cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
63 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
64
65
66
67 #################################################################
68 def SAMBA_LIBRARY(bld, libname, source,
69                   deps='',
70                   public_deps='',
71                   includes='',
72                   public_headers=None,
73                   header_path=None,
74                   pc_files=None,
75                   vnum=None,
76                   cflags='',
77                   external_library=False,
78                   realname=None,
79                   autoproto=None,
80                   group='main',
81                   depends_on='',
82                   local_include=True,
83                   vars=None,
84                   install_path=None,
85                   install=True,
86                   needs_python=False,
87                   target_type='LIBRARY',
88                   bundled_extension=True,
89                   link_name=None,
90                   enabled=True):
91     '''define a Samba library'''
92
93     if not enabled:
94         SET_TARGET_TYPE(bld, libname, 'DISABLED')
95         return
96
97     source = bld.EXPAND_VARIABLES(source, vars=vars)
98
99     # remember empty libraries, so we can strip the dependencies
100     if (source == '') or (source == []):
101         SET_TARGET_TYPE(bld, libname, 'EMPTY')
102         return
103
104     if target_type != 'PYTHON' and BUILTIN_LIBRARY(bld, libname):
105         obj_target = libname
106     else:
107         obj_target = libname + '.objlist'
108
109     # first create a target for building the object files for this library
110     # by separating in this way, we avoid recompiling the C files
111     # separately for the install library and the build library
112     bld.SAMBA_SUBSYSTEM(obj_target,
113                         source         = source,
114                         deps           = deps,
115                         public_deps    = public_deps,
116                         includes       = includes,
117                         public_headers = public_headers,
118                         header_path    = header_path,
119                         cflags         = cflags,
120                         group          = group,
121                         autoproto      = autoproto,
122                         depends_on     = depends_on,
123                         needs_python   = needs_python,
124                         local_include  = local_include)
125
126     if libname == obj_target:
127         return
128
129     if not SET_TARGET_TYPE(bld, libname, target_type):
130         return
131
132     # the library itself will depend on that object target
133     deps += ' ' + public_deps
134     deps = TO_LIST(deps)
135     deps.append(obj_target)
136
137     if needs_python:
138         bundled_name = libname
139     else:
140         bundled_name = BUNDLED_NAME(bld, libname, bundled_extension)
141
142     features = 'cc cshlib'
143     if needs_python:
144         features += ' pyext'
145
146     bld.SET_BUILD_GROUP(group)
147     t = bld(
148         features        = features + ' symlink_lib',
149         source          = [],
150         target          = bundled_name,
151         samba_cflags    = CURRENT_CFLAGS(bld, libname, cflags),
152         depends_on      = depends_on,
153         samba_deps      = deps,
154         samba_includes  = includes,
155         local_include   = local_include,
156         vnum            = vnum,
157         install_path    = None,
158         ldflags         = build_rpath(bld),
159         name            = libname
160         )
161
162     if link_name:
163         t.link_name = link_name
164
165     if install_path is None:
166         install_path = '${LIBDIR}'
167     install_path = SUBST_VARS_RECURSIVE(install_path, bld.env)
168
169     # we don't need the double libraries if rpath is off
170     if (bld.env.RPATH_ON_INSTALL == False and
171         bld.env.RPATH_ON_BUILD == False):
172         install_target = bundled_name
173     else:
174         install_target = bundled_name + '.inst'
175
176     if install and install_target != bundled_name:
177         # create a separate install library, which may have
178         # different rpath settings
179         SET_TARGET_TYPE(bld, install_target, target_type)
180         t = bld(
181             features        = features,
182             source          = [],
183             target          = install_target,
184             samba_cflags    = CURRENT_CFLAGS(bld, libname, cflags),
185             depends_on      = depends_on,
186             samba_deps      = deps,
187             samba_includes  = includes,
188             local_include   = local_include,
189             vnum            = vnum,
190             install_as      = bundled_name,
191             install_path    = None,
192             ldflags         = install_rpath(bld)
193             )
194
195     if install:
196         if realname:
197             install_name = realname
198             install_link = None
199             inst_name    = install_target + '.so'
200         elif vnum:
201             vnum_base = vnum.split('.')[0]
202             install_name = 'lib%s.so.%s' % (bundled_name, vnum)
203             install_link = 'lib%s.so.%s' % (bundled_name, vnum_base)
204             inst_name    = 'lib%s.so' % install_target
205         else:
206             install_name = 'lib%s.so' % bundled_name
207             install_link = None
208             inst_name    = 'lib%s.so' % install_target
209
210         bld.install_as(os.path.join(install_path, install_name), inst_name)
211         if install_link:
212             bld.symlink_as(os.path.join(install_path, install_link), install_name)
213
214     if autoproto is not None:
215         bld.SAMBA_AUTOPROTO(autoproto, source)
216
217     if public_headers is not None:
218         bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
219
220     if pc_files is not None:
221         bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
222
223 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
224
225
226 #################################################################
227 def SAMBA_BINARY(bld, binname, source,
228                  deps='',
229                  includes='',
230                  public_headers=None,
231                  header_path=None,
232                  modules=None,
233                  installdir=None,
234                  ldflags=None,
235                  cflags='',
236                  autoproto=None,
237                  use_hostcc=None,
238                  compiler=None,
239                  group='binaries',
240                  manpages=None,
241                  local_include=True,
242                  subsystem_name=None,
243                  needs_python=False,
244                  vars=None,
245                  install=True,
246                  install_path=None):
247     '''define a Samba binary'''
248
249     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
250         return
251
252     features = 'cc cprogram'
253     if needs_python:
254         features += ' pyembed'
255
256     obj_target = binname + '.objlist'
257
258     source = bld.EXPAND_VARIABLES(source, vars=vars)
259
260     # first create a target for building the object files for this binary
261     # by separating in this way, we avoid recompiling the C files
262     # separately for the install binary and the build binary
263     bld.SAMBA_SUBSYSTEM(obj_target,
264                         source         = source,
265                         deps           = deps,
266                         includes       = includes,
267                         cflags         = cflags,
268                         group          = group,
269                         autoproto      = autoproto,
270                         subsystem_name = subsystem_name,
271                         needs_python   = needs_python,
272                         local_include  = local_include)
273
274     bld.SET_BUILD_GROUP(group)
275
276     # the library itself will depend on that object target
277     deps = TO_LIST(deps)
278     deps.append(obj_target)
279
280     bld(
281         features       = features + ' symlink_bin',
282         source         = [],
283         target         = binname,
284         samba_cflags   = CURRENT_CFLAGS(bld, binname, cflags),
285         samba_deps     = deps,
286         samba_includes = includes,
287         local_include  = local_include,
288         samba_modules  = modules,
289         top            = True,
290         samba_subsystem= subsystem_name,
291         install_path   = None,
292         ldflags        = build_rpath(bld)
293         )
294
295     if install_path is None:
296         install_path = '${BINDIR}'
297     install_path = SUBST_VARS_RECURSIVE(install_path, bld.env)
298
299     # we don't need the double binaries if rpath is off
300     if (bld.env.RPATH_ON_INSTALL == False and
301         bld.env.RPATH_ON_BUILD == False):
302         install_target = binname
303     else:
304         install_target = binname + '.inst'
305
306     if install and install_target != binname:
307         # we create a separate 'install' binary, which
308         # will have different rpath settings
309         SET_TARGET_TYPE(bld, install_target, 'BINARY')
310         t = bld(
311             features       = features,
312             source         = [],
313             target         = install_target,
314             samba_cflags   = CURRENT_CFLAGS(bld, binname, cflags),
315             samba_deps     = deps,
316             samba_includes = includes,
317             local_include  = local_include,
318             samba_modules  = modules,
319             top            = True,
320             samba_subsystem= subsystem_name,
321             install_path   = None,
322             ldflags        = install_rpath(bld)
323             )
324
325     if install:
326         bld.install_as(os.path.join(install_path, binname),
327                        install_target,
328                        chmod=0755)
329
330     # setup the subsystem_name as an alias for the real
331     # binary name, so it can be found when expanding
332     # subsystem dependencies
333     if subsystem_name is not None:
334         bld.TARGET_ALIAS(subsystem_name, binname)
335
336     if autoproto is not None:
337         bld.SAMBA_AUTOPROTO(autoproto, source)
338     if public_headers is not None:
339         bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
340 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
341
342
343 #################################################################
344 def SAMBA_MODULE(bld, modname, source,
345                  deps='',
346                  includes='',
347                  subsystem=None,
348                  init_function=None,
349                  autoproto=None,
350                  autoproto_extra_source='',
351                  aliases=None,
352                  cflags='',
353                  internal_module=True,
354                  local_include=True,
355                  vars=None,
356                  enabled=True):
357     '''define a Samba module.'''
358
359     # we add the init function regardless of whether the module
360     # is enabled or not, as we need to generate a null list if
361     # all disabled
362     bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
363
364     if internal_module or BUILTIN_LIBRARY(bld, modname):
365         # treat internal modules as subsystems for now
366         SAMBA_SUBSYSTEM(bld, modname, source,
367                         deps=deps,
368                         includes=includes,
369                         autoproto=autoproto,
370                         autoproto_extra_source=autoproto_extra_source,
371                         cflags=cflags,
372                         local_include=local_include,
373                         enabled=enabled)
374         return
375
376     if not enabled:
377         SET_TARGET_TYPE(bld, modname, 'DISABLED')
378         return
379
380     source = bld.EXPAND_VARIABLES(source, vars=vars)
381
382     # remember empty modules, so we can strip the dependencies
383     if (source == '') or (source == []):
384         SET_TARGET_TYPE(bld, modname, 'EMPTY')
385         return
386
387     if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
388         return
389
390     if subsystem is not None:
391         deps += ' ' + subsystem
392
393     bld.SET_BUILD_GROUP('main')
394     bld(
395         features       = 'cc',
396         source         = source,
397         target         = modname,
398         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags),
399         samba_includes = includes,
400         local_include  = local_include,
401         samba_deps     = TO_LIST(deps)
402         )
403
404     if autoproto is not None:
405         bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
406
407 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
408
409
410 #################################################################
411 def SAMBA_SUBSYSTEM(bld, modname, source,
412                     deps='',
413                     public_deps='',
414                     includes='',
415                     public_headers=None,
416                     header_path=None,
417                     cflags='',
418                     cflags_end=None,
419                     group='main',
420                     init_function_sentinal=None,
421                     heimdal_autoproto=None,
422                     heimdal_autoproto_options=None,
423                     heimdal_autoproto_private=None,
424                     autoproto=None,
425                     autoproto_extra_source='',
426                     depends_on='',
427                     local_include=True,
428                     local_include_first=True,
429                     subsystem_name=None,
430                     enabled=True,
431                     vars=None,
432                     needs_python=False):
433     '''define a Samba subsystem'''
434
435     if not enabled:
436         SET_TARGET_TYPE(bld, modname, 'DISABLED')
437         return
438
439     # remember empty subsystems, so we can strip the dependencies
440     if (source == '') or (source == []):
441         SET_TARGET_TYPE(bld, modname, 'EMPTY')
442         return
443
444     if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
445         return
446
447     source = bld.EXPAND_VARIABLES(source, vars=vars)
448
449     deps += ' ' + public_deps
450
451     bld.SET_BUILD_GROUP(group)
452
453     features = 'cc'
454     if needs_python:
455         features += ' pyext'
456
457     t = bld(
458         features       = features,
459         source         = source,
460         target         = modname,
461         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags),
462         depends_on     = depends_on,
463         samba_deps     = TO_LIST(deps),
464         samba_includes = includes,
465         local_include  = local_include,
466         local_include_first  = local_include_first,
467         samba_subsystem= subsystem_name
468         )
469
470     if cflags_end is not None:
471         t.samba_cflags.extend(TO_LIST(cflags_end))
472
473     if heimdal_autoproto is not None:
474         bld.HEIMDAL_AUTOPROTO(heimdal_autoproto, source, options=heimdal_autoproto_options)
475     if heimdal_autoproto_private is not None:
476         bld.HEIMDAL_AUTOPROTO_PRIVATE(heimdal_autoproto_private, source)
477     if autoproto is not None:
478         bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
479     if public_headers is not None:
480         bld.PUBLIC_HEADERS(public_headers, header_path=header_path)
481     return t
482
483
484 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
485
486
487 def SAMBA_GENERATOR(bld, name, rule, source, target,
488                     group='generators', enabled=True,
489                     public_headers=None,
490                     header_path=None,
491                     vars=None):
492     '''A generic source generator target'''
493
494     if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
495         return
496
497     if not enabled:
498         return
499
500     bld.SET_BUILD_GROUP(group)
501     t = bld(
502         rule=rule,
503         source=bld.EXPAND_VARIABLES(source, vars=vars),
504         target=target,
505         shell=isinstance(rule, str),
506         on_results=True,
507         before='cc',
508         ext_out='.c',
509         name=name)
510
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
515
516
517
518 def BUILD_SUBDIR(bld, dir):
519     '''add a new set of build rules from a subdirectory'''
520     path = os.path.normpath(bld.curdir + '/' + dir)
521     cache = LOCAL_CACHE(bld, 'SUBDIR_LIST')
522     if path in cache: return
523     cache[path] = True
524     debug("build: Processing subdirectory %s" % dir)
525     bld.add_subdirs(dir)
526 Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
527
528
529
530 @runonce
531 def SETUP_BUILD_GROUPS(bld):
532     '''setup build groups used to ensure that the different build
533     phases happen consecutively'''
534     bld.p_ln = bld.srcnode # we do want to see all targets!
535     bld.env['USING_BUILD_GROUPS'] = True
536     bld.add_group('setup')
537     bld.add_group('build_compiler_source')
538     bld.add_group('base_libraries')
539     bld.add_group('generators')
540     bld.add_group('compiler_prototypes')
541     bld.add_group('compiler_libraries')
542     bld.add_group('build_compilers')
543     bld.add_group('build_source')
544     bld.add_group('prototypes')
545     bld.add_group('main')
546     bld.add_group('binaries')
547     bld.add_group('final')
548 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
549
550
551 def SET_BUILD_GROUP(bld, group):
552     '''set the current build group'''
553     if not 'USING_BUILD_GROUPS' in bld.env:
554         return
555     bld.set_group(group)
556 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
557
558
559
560 @conf
561 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
562     """use timestamps instead of file contents for deps
563     this currently doesn't work"""
564     def h_file(filename):
565         import stat
566         st = os.stat(filename)
567         if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
568         m = Utils.md5()
569         m.update(str(st.st_mtime))
570         m.update(str(st.st_size))
571         m.update(filename)
572         return m.digest()
573     Utils.h_file = h_file
574
575
576
577 ##############################
578 # handle the creation of links for libraries and binaries
579 # note that we use a relative symlink path to allow the whole tree
580 # to me moved/copied elsewhere without breaking the links
581 t = Task.simple_task_type('symlink_lib', 'rm -f ${LINK_TARGET} && ln -s ${LINK_SOURCE} ${LINK_TARGET}',
582                           shell=True, color='PINK', ext_in='.bin')
583 t.quiet = True
584
585 @feature('symlink_lib')
586 @after('apply_link')
587 def symlink_lib(self):
588     '''symlink a shared lib'''
589     tsk = self.create_task('symlink_lib', self.link_task.outputs[0])
590
591     # calculat the link target and put it in the environment
592     soext=""
593     vnum = getattr(self, 'vnum', None)
594     if vnum is not None:
595         soext = '.' + vnum.split('.')[0]
596
597     link_target = getattr(self, 'link_name', '')
598     if link_target == '':
599         link_target = '%s/lib%s.so%s' % (LIB_PATH, self.target, soext)
600
601
602     link_source = os_path_relpath(self.link_task.outputs[0].abspath(self.env),
603                                   os.path.join(self.env.BUILD_DIRECTORY, link_target))
604
605     tsk.env.LINK_TARGET = link_target
606     tsk.env.LINK_SOURCE = link_source[3:]
607     debug('task_gen: LINK for %s is %s -> %s',
608           self.name, tsk.env.LINK_SOURCE, tsk.env.LINK_TARGET)
609
610
611 t = Task.simple_task_type('symlink_bin', 'rm -f ${BIN_TARGET} && ln -s ${SRC} ${BIN_TARGET}',
612                           shell=True, color='PINK', ext_in='.bin')
613 t.quiet = True
614
615 @feature('symlink_bin')
616 @after('apply_link')
617 def symlink_bin(self):
618     '''symlink a binary'''
619     if Options.is_install:
620         # we don't want to copy the install binary, as
621         # that has the install rpath, not the build rpath
622         # The rpath of the binaries in bin/default/foo/blah is different
623         # during the install phase, as distros insist on not using rpath in installed binaries
624         return
625     tsk = self.create_task('symlink_bin', self.link_task.outputs[0])
626
627     tsk.env.BIN_TARGET = self.target
628     debug('task_gen: BIN_TARGET for %s is %s', self.name, tsk.env.BIN_TARGET)
629
630
631
632
633 t = Task.simple_task_type('copy_script', 'rm -f ${LINK_TARGET} && ln -s ${SRC[0].abspath(env)} ${LINK_TARGET}',
634                           shell=True, color='PINK', ext_in='.bin')
635 t.quiet = True
636
637 @feature('copy_script')
638 @before('apply_link')
639 def copy_script(self):
640     tsk = self.create_task('copy_script', self.allnodes[0])
641     tsk.env.TARGET = self.target
642
643 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
644     '''used to copy scripts from the source tree into the build directory
645        for use by selftest'''
646
647     source = bld.path.ant_glob(pattern)
648
649     bld.SET_BUILD_GROUP('build_source')
650     for s in TO_LIST(source):
651         iname = s
652         if installname != None:
653             iname = installname
654         target = os.path.join(installdir, iname)
655         tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
656         mkdir_p(tgtdir)
657         t = bld(features='copy_script',
658                 source       = s,
659                 target       = target,
660                 always       = True,
661                 install_path = None)
662         t.env.LINK_TARGET = target
663
664 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
665
666
667 def install_file(bld, destdir, file, chmod=0644, flat=False,
668                  python_fixup=False, destname=None):
669     '''install a file'''
670     destdir = bld.EXPAND_VARIABLES(destdir)
671     if not destname:
672         destname = file
673         if flat:
674             destname = os.path.basename(destname)
675     dest = os.path.join(destdir, destname)
676     if python_fixup:
677         # fixup the python path it will use to find Samba modules
678         inst_file = file + '.inst'
679         bld.SAMBA_GENERATOR('python_%s' % destname,
680                             rule="sed 's|\(sys.path.insert.*\)bin/python\(.*\)$|\\1${PYTHONDIR}\\2|g' < ${SRC} > ${TGT}",
681                             source=file,
682                             target=inst_file)
683         file = inst_file
684     bld.install_as(dest, file, chmod=chmod)
685
686
687 def INSTALL_FILES(bld, destdir, files, chmod=0644, flat=False,
688                   python_fixup=False, destname=None):
689     '''install a set of files'''
690     for f in TO_LIST(files):
691         install_file(bld, destdir, f, chmod=chmod, flat=flat,
692                      python_fixup=python_fixup, destname=destname)
693 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
694
695
696 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=0644, flat=False,
697                      python_fixup=False, exclude=None):
698     '''install a set of files matching a wildcard pattern'''
699     files=TO_LIST(bld.path.ant_glob(pattern))
700     if exclude:
701         for f in files[:]:
702             if fnmatch.fnmatch(f, exclude):
703                 files.remove(f)
704     INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat, python_fixup=python_fixup)
705 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
706
707
708 def PUBLIC_HEADERS(bld, public_headers, header_path=None):
709     '''install some headers
710
711     header_path may either be a string that is added to the INCLUDEDIR,
712     or it can be a dictionary of wildcard patterns which map to destination
713     directories relative to INCLUDEDIR
714     '''
715     dest = '${INCLUDEDIR}'
716     if isinstance(header_path, str):
717         dest += '/' + header_path
718     for h in TO_LIST(public_headers):
719         hdest = dest
720         if isinstance(header_path, list):
721             for (p1, dir) in header_path:
722                 found_match=False
723                 lst = TO_LIST(p1)
724                 for p2 in lst:
725                     if fnmatch.fnmatch(h, p2):
726                         if dir:
727                             hdest = os.path.join(hdest, dir)
728                         found_match=True
729                         break
730                 if found_match: break
731         if h.find(':') != -1:
732             hs=h.split(':')
733             INSTALL_FILES(bld, hdest, hs[0], flat=True, destname=hs[1])
734         else:
735             INSTALL_FILES(bld, hdest, h, flat=True)
736 Build.BuildContext.PUBLIC_HEADERS = PUBLIC_HEADERS
737
738
739 def subst_at_vars(task):
740     '''substiture @VAR@ style variables in a file'''
741     src = task.inputs[0].srcpath(task.env)
742     tgt = task.outputs[0].bldpath(task.env)
743
744     f = open(src, 'r')
745     s = f.read()
746     f.close()
747     # split on the vars
748     a = re.split('(@\w+@)', s)
749     out = []
750     for v in a:
751         if re.match('@\w+@', v):
752             vname = v[1:-1]
753             if not vname in task.env and vname.upper() in task.env:
754                 vname = vname.upper()
755             if not vname in task.env:
756                 print "Unknown substitution %s in %s" % (v, task.name)
757                 raise
758             v = task.env[vname]
759         out.append(v)
760     contents = ''.join(out)
761     f = open(tgt, 'w')
762     s = f.write(contents)
763     f.close()
764     return 0
765
766
767
768 def PKG_CONFIG_FILES(bld, pc_files, vnum=None):
769     '''install some pkg_config pc files'''
770     dest = '${PKGCONFIGDIR}'
771     dest = bld.EXPAND_VARIABLES(dest)
772     for f in TO_LIST(pc_files):
773         base=os.path.basename(f)
774         t = bld.SAMBA_GENERATOR('PKGCONFIG_%s' % base,
775                                 rule=subst_at_vars,
776                                 source=f+'.in',
777                                 target=f)
778         if vnum:
779             t.env.PACKAGE_VERSION = vnum
780         INSTALL_FILES(bld, dest, f, flat=True, destname=base)
781 Build.BuildContext.PKG_CONFIG_FILES = PKG_CONFIG_FILES
782
783
784
785 #############################################################
786 # give a nicer display when building different types of files
787 def progress_display(self, msg, fname):
788     col1 = Logs.colors(self.color)
789     col2 = Logs.colors.NORMAL
790     total = self.position[1]
791     n = len(str(total))
792     fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg)
793     return fs % (self.position[0], self.position[1], col1, fname, col2)
794
795 def link_display(self):
796     if Options.options.progress_bar != 0:
797         return Task.Task.old_display(self)
798     fname = self.outputs[0].bldpath(self.env)
799     return progress_display(self, 'Linking', fname)
800 Task.TaskBase.classes['cc_link'].display = link_display
801
802 def samba_display(self):
803     if Options.options.progress_bar != 0:
804         return Task.Task.old_display(self)
805     fname = self.inputs[0].bldpath(self.env)
806     if fname[0:3] == '../':
807         fname = fname[3:]
808     ext_loc = fname.rfind('.')
809     if ext_loc == -1:
810         return Task.Task.old_display(self)
811     ext = fname[ext_loc:]
812
813     ext_map = { '.idl' : 'Compiling IDL',
814                 '.et'  : 'Compiling ERRTABLE',
815                 '.asn1': 'Compiling ASN1',
816                 '.c'   : 'Compiling' }
817     if ext in ext_map:
818         return progress_display(self, ext_map[ext], fname)
819     return Task.Task.old_display(self)
820
821 Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display
822 Task.TaskBase.classes['Task'].display = samba_display