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