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