wafsamba: Require public libraries to have headers.
[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, sys, Options, Task, Utils, cc, TaskGen, fnmatch, re, shutil, Logs, Constants
5 from Configure import conf
6 from Logs import debug
7 from samba_utils import SUBST_VARS_RECURSIVE
8 TaskGen.task_gen.apply_verif = Utils.nada
9
10 # bring in the other samba modules
11 from samba_optimisation import *
12 from samba_utils import *
13 from samba_version import *
14 from samba_autoconf import *
15 from samba_patterns import *
16 from samba_pidl import *
17 from samba_autoproto import *
18 from samba_python import *
19 from samba_deps import *
20 from samba_bundled import *
21 import samba_install
22 import samba_conftests
23 import samba_abi
24 import samba_headers
25 import tru64cc
26 import irixcc
27 import hpuxcc
28 import generic_cc
29 import samba_dist
30 import samba_wildcard
31 import stale_files
32 import symbols
33 import pkgconfig
34
35 # some systems have broken threading in python
36 if os.environ.get('WAF_NOTHREADS') == '1':
37     import nothreads
38
39 LIB_PATH="shared"
40
41 os.environ['PYTHONUNBUFFERED'] = '1'
42
43
44 if Constants.HEXVERSION < 0x105019:
45     Logs.error('''
46 Please use the version of waf that comes with Samba, not
47 a system installed version. See http://wiki.samba.org/index.php/Waf
48 for details.
49
50 Alternatively, please run ./configure and make as usual. That will
51 call the right version of waf.''')
52     sys.exit(1)
53
54
55 @conf
56 def SAMBA_BUILD_ENV(conf):
57     '''create the samba build environment'''
58     conf.env.BUILD_DIRECTORY = conf.blddir
59     mkdir_p(os.path.join(conf.blddir, LIB_PATH))
60     mkdir_p(os.path.join(conf.blddir, LIB_PATH, "private"))
61     mkdir_p(os.path.join(conf.blddir, "modules"))
62     mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
63     # this allows all of the bin/shared and bin/python targets
64     # to be expressed in terms of build directory paths
65     mkdir_p(os.path.join(conf.blddir, 'default'))
66     for p in ['python','shared', 'modules']:
67         link_target = os.path.join(conf.blddir, 'default/' + p)
68         if not os.path.lexists(link_target):
69             os.symlink('../' + p, link_target)
70
71     # get perl to put the blib files in the build directory
72     blib_bld = os.path.join(conf.blddir, 'default/pidl/blib')
73     blib_src = os.path.join(conf.srcdir, 'pidl/blib')
74     mkdir_p(blib_bld + '/man1')
75     mkdir_p(blib_bld + '/man3')
76     if os.path.islink(blib_src):
77         os.unlink(blib_src)
78     elif os.path.exists(blib_src):
79         shutil.rmtree(blib_src)
80
81
82 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
83     '''add an init_function to the list for a subsystem'''
84     if init_function is None:
85         return
86     bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
87     cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
88     if not subsystem in cache:
89         cache[subsystem] = []
90     cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
91 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
92
93
94
95 #################################################################
96 def SAMBA_LIBRARY(bld, libname, source,
97                   deps='',
98                   public_deps='',
99                   includes='',
100                   public_headers=None,
101                   public_headers_install=True,
102                   header_path=None,
103                   pc_files=None,
104                   vnum=None,
105                   soname=None,
106                   cflags='',
107                   ldflags='',
108                   external_library=False,
109                   realname=None,
110                   autoproto=None,
111                   autoproto_extra_source='',
112                   group='libraries',
113                   depends_on='',
114                   local_include=True,
115                   global_include=True,
116                   vars=None,
117                   subdir=None,
118                   install_path=None,
119                   install=True,
120                   pyembed=False,
121                   pyext=False,
122                   target_type='LIBRARY',
123                   bundled_extension=True,
124                   link_name=None,
125                   abi_directory=None,
126                   abi_match=None,
127                   hide_symbols=False,
128                   manpages=None,
129                   private_library=False,
130                   grouping_library=False,
131                   allow_undefined_symbols=False,
132                   enabled=True):
133     '''define a Samba library'''
134
135     if not enabled:
136         SET_TARGET_TYPE(bld, libname, 'DISABLED')
137         return
138
139     source = bld.EXPAND_VARIABLES(source, vars=vars)
140     if subdir:
141         source = bld.SUBDIR(subdir, source)
142
143     # remember empty libraries, so we can strip the dependencies
144     if ((source == '') or (source == [])) and deps == '' and public_deps == '':
145         SET_TARGET_TYPE(bld, libname, 'EMPTY')
146         return
147
148     if BUILTIN_LIBRARY(bld, libname):
149         obj_target = libname
150     else:
151         obj_target = libname + '.objlist'
152
153     if group == 'libraries':
154         subsystem_group = 'main'
155     else:
156         subsystem_group = group
157
158     # first create a target for building the object files for this library
159     # by separating in this way, we avoid recompiling the C files
160     # separately for the install library and the build library
161     bld.SAMBA_SUBSYSTEM(obj_target,
162                         source         = source,
163                         deps           = deps,
164                         public_deps    = public_deps,
165                         includes       = includes,
166                         public_headers = public_headers,
167                         public_headers_install = public_headers_install,
168                         header_path    = header_path,
169                         cflags         = cflags,
170                         group          = subsystem_group,
171                         autoproto      = autoproto,
172                         autoproto_extra_source=autoproto_extra_source,
173                         depends_on     = depends_on,
174                         hide_symbols   = hide_symbols,
175                         pyext          = pyext or (target_type == "PYTHON"),
176                         local_include  = local_include,
177                         global_include = global_include)
178
179     if BUILTIN_LIBRARY(bld, libname):
180         return
181
182     if not SET_TARGET_TYPE(bld, libname, target_type):
183         return
184
185     # the library itself will depend on that object target
186     deps += ' ' + public_deps
187     deps = TO_LIST(deps)
188     deps.append(obj_target)
189
190     realname = bld.map_shlib_extension(realname, python=(target_type=='PYTHON'))
191     link_name = bld.map_shlib_extension(link_name, python=(target_type=='PYTHON'))
192
193     # we don't want any public libraries without version numbers
194     if (not private_library and target_type != 'PYTHON' and not realname):
195         if vnum is None and soname is None:
196             raise Utils.WafError("public library '%s' must have a vnum" %
197                     libname)
198         if pc_files is None:
199             raise Utils.WafError("public library '%s' must have pkg-config file" %
200                        libname)
201         if public_headers is None:
202             raise Utils.WafError("public library '%s' must have header files" %
203                        libname)
204
205     if target_type == 'PYTHON' or realname or not private_library:
206         bundled_name = libname.replace('_', '-')
207     else:
208         bundled_name = PRIVATE_NAME(bld, libname, bundled_extension,
209             private_library)
210
211     ldflags = TO_LIST(ldflags)
212
213     features = 'cc cshlib symlink_lib install_lib'
214     if target_type == 'PYTHON':
215         features += ' pyext'
216     if pyext or pyembed:
217         # this is quite strange. we should add pyext feature for pyext
218         # but that breaks the build. This may be a bug in the waf python tool
219         features += ' pyembed'
220
221     if abi_directory:
222         features += ' abi_check'
223
224     vscript = None
225     if bld.env.HAVE_LD_VERSION_SCRIPT:
226         if private_library:
227             version = "%s_%s" % (Utils.g_module.APPNAME, Utils.g_module.VERSION)
228         elif vnum:
229             version = "%s_%s" % (libname, vnum)
230         else:
231             version = None
232         if version:
233             vscript = "%s.vscript" % libname
234             bld.ABI_VSCRIPT(libname, abi_directory, version, vscript,
235                             abi_match)
236             fullname = apply_pattern(bundled_name, bld.env.shlib_PATTERN)
237             fullpath = bld.path.find_or_declare(fullname)
238             vscriptpath = bld.path.find_or_declare(vscript)
239             if not fullpath:
240                 raise Utils.WafError("unable to find fullpath for %s" % fullname)
241             if not vscriptpath:
242                 raise Utils.WafError("unable to find vscript path for %s" % vscript)
243             bld.add_manual_dependency(fullpath, vscriptpath)
244             if Options.is_install:
245                 # also make the .inst file depend on the vscript
246                 instname = apply_pattern(bundled_name + '.inst', bld.env.shlib_PATTERN)
247                 bld.add_manual_dependency(bld.path.find_or_declare(instname), bld.path.find_or_declare(vscript))
248             vscript = os.path.join(bld.path.abspath(bld.env), vscript)
249
250     bld.SET_BUILD_GROUP(group)
251     t = bld(
252         features        = features,
253         source          = [],
254         target          = bundled_name,
255         depends_on      = depends_on,
256         samba_ldflags   = ldflags,
257         samba_deps      = deps,
258         samba_includes  = includes,
259         version_script  = vscript,
260         local_include   = local_include,
261         global_include  = global_include,
262         vnum            = vnum,
263         soname          = soname,
264         install_path    = None,
265         samba_inst_path = install_path,
266         name            = libname,
267         samba_realname  = realname,
268         samba_install   = install,
269         abi_directory   = "%s/%s" % (bld.path.abspath(), abi_directory),
270         abi_match       = abi_match,
271         private_library = private_library,
272         grouping_library=grouping_library,
273         allow_undefined_symbols=allow_undefined_symbols
274         )
275
276     if realname and not link_name:
277         link_name = 'shared/%s' % realname
278
279     if link_name:
280         t.link_name = link_name
281
282     if pc_files is not None:
283         bld.PKG_CONFIG_FILES(pc_files, vnum=vnum)
284
285     if (manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and 
286         bld.env['XSLTPROC_MANPAGES']):
287         bld.MANPAGES(manpages)
288
289
290 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
291
292
293 #################################################################
294 def SAMBA_BINARY(bld, binname, source,
295                  deps='',
296                  includes='',
297                  public_headers=None,
298                  header_path=None,
299                  modules=None,
300                  ldflags=None,
301                  cflags='',
302                  autoproto=None,
303                  use_hostcc=False,
304                  use_global_deps=True,
305                  compiler=None,
306                  group='binaries',
307                  manpages=None,
308                  local_include=True,
309                  global_include=True,
310                  subsystem_name=None,
311                  pyembed=False,
312                  vars=None,
313                  subdir=None,
314                  install=True,
315                  install_path=None,
316                  enabled=True):
317     '''define a Samba binary'''
318
319     if not enabled:
320         SET_TARGET_TYPE(bld, binname, 'DISABLED')
321         return
322
323     if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
324         return
325
326     features = 'cc cprogram symlink_bin install_bin'
327     if pyembed:
328         features += ' pyembed'
329
330     obj_target = binname + '.objlist'
331
332     source = bld.EXPAND_VARIABLES(source, vars=vars)
333     if subdir:
334         source = bld.SUBDIR(subdir, source)
335     source = unique_list(TO_LIST(source))
336
337     if group == 'binaries':
338         subsystem_group = 'main'
339     else:
340         subsystem_group = group
341
342     # first create a target for building the object files for this binary
343     # by separating in this way, we avoid recompiling the C files
344     # separately for the install binary and the build binary
345     bld.SAMBA_SUBSYSTEM(obj_target,
346                         source         = source,
347                         deps           = deps,
348                         includes       = includes,
349                         cflags         = cflags,
350                         group          = subsystem_group,
351                         autoproto      = autoproto,
352                         subsystem_name = subsystem_name,
353                         local_include  = local_include,
354                         global_include = global_include,
355                         use_hostcc     = use_hostcc,
356                         pyext          = pyembed,
357                         use_global_deps= use_global_deps)
358
359     bld.SET_BUILD_GROUP(group)
360
361     # the binary itself will depend on that object target
362     deps = TO_LIST(deps)
363     deps.append(obj_target)
364
365     t = bld(
366         features       = features,
367         source         = [],
368         target         = binname,
369         samba_deps     = deps,
370         samba_includes = includes,
371         local_include  = local_include,
372         global_include = global_include,
373         samba_modules  = modules,
374         top            = True,
375         samba_subsystem= subsystem_name,
376         install_path   = None,
377         samba_inst_path= install_path,
378         samba_install  = install,
379         samba_ldflags  = TO_LIST(ldflags)
380         )
381
382     if manpages is not None and 'XSLTPROC_MANPAGES' in bld.env and bld.env['XSLTPROC_MANPAGES']:
383         bld.MANPAGES(manpages)
384
385 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
386
387
388 #################################################################
389 def SAMBA_MODULE(bld, modname, source,
390                  deps='',
391                  includes='',
392                  subsystem=None,
393                  init_function=None,
394                  module_init_name='samba_init_module',
395                  autoproto=None,
396                  autoproto_extra_source='',
397                  cflags='',
398                  internal_module=True,
399                  local_include=True,
400                  global_include=True,
401                  vars=None,
402                  subdir=None,
403                  enabled=True,
404                  pyembed=False,
405                  allow_undefined_symbols=False
406                  ):
407     '''define a Samba module.'''
408
409     source = bld.EXPAND_VARIABLES(source, vars=vars)
410     if subdir:
411         source = bld.SUBDIR(subdir, source)
412
413     if internal_module or BUILTIN_LIBRARY(bld, modname):
414         bld.SAMBA_SUBSYSTEM(modname, source,
415                     deps=deps,
416                     includes=includes,
417                     autoproto=autoproto,
418                     autoproto_extra_source=autoproto_extra_source,
419                     cflags=cflags,
420                     local_include=local_include,
421                     global_include=global_include,
422                     enabled=enabled)
423
424         bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
425         return
426
427     if not enabled:
428         SET_TARGET_TYPE(bld, modname, 'DISABLED')
429         return
430
431     obj_target = modname + '.objlist'
432
433     realname = modname
434     if subsystem is not None:
435         deps += ' ' + subsystem
436         while realname.startswith("lib"+subsystem+"_"):
437             realname = realname[len("lib"+subsystem+"_"):]
438         while realname.startswith(subsystem+"_"):
439             realname = realname[len(subsystem+"_"):]
440
441     realname = bld.make_libname(realname)
442     while realname.startswith("lib"):
443         realname = realname[len("lib"):]
444
445     build_link_name = "modules/%s/%s" % (subsystem, realname)
446
447     if init_function:
448         cflags += " -D%s=%s" % (init_function, module_init_name)
449
450     bld.SAMBA_LIBRARY(modname,
451                       source,
452                       deps=deps,
453                       includes=includes,
454                       cflags=cflags,
455                       realname = realname,
456                       autoproto = autoproto,
457                       local_include=local_include,
458                       global_include=global_include,
459                       vars=vars,
460                       link_name=build_link_name,
461                       install_path="${MODULESDIR}/%s" % subsystem,
462                       pyembed=pyembed,
463                       allow_undefined_symbols=allow_undefined_symbols
464                       )
465
466
467 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
468
469
470 #################################################################
471 def SAMBA_SUBSYSTEM(bld, modname, source,
472                     deps='',
473                     public_deps='',
474                     includes='',
475                     public_headers=None,
476                     public_headers_install=True,
477                     header_path=None,
478                     cflags='',
479                     cflags_end=None,
480                     group='main',
481                     init_function_sentinal=None,
482                     autoproto=None,
483                     autoproto_extra_source='',
484                     depends_on='',
485                     local_include=True,
486                     local_include_first=True,
487                     global_include=True,
488                     subsystem_name=None,
489                     enabled=True,
490                     use_hostcc=False,
491                     use_global_deps=True,
492                     vars=None,
493                     subdir=None,
494                     hide_symbols=False,
495                     pyext=False):
496     '''define a Samba subsystem'''
497
498     if not enabled:
499         SET_TARGET_TYPE(bld, modname, 'DISABLED')
500         return
501
502     # remember empty subsystems, so we can strip the dependencies
503     if ((source == '') or (source == [])) and deps == '' and public_deps == '':
504         SET_TARGET_TYPE(bld, modname, 'EMPTY')
505         return
506
507     if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
508         return
509
510     source = bld.EXPAND_VARIABLES(source, vars=vars)
511     if subdir:
512         source = bld.SUBDIR(subdir, source)
513     source = unique_list(TO_LIST(source))
514
515     deps += ' ' + public_deps
516
517     bld.SET_BUILD_GROUP(group)
518
519     features = 'cc'
520     if pyext:
521         features += ' pyext'
522
523     t = bld(
524         features       = features,
525         source         = source,
526         target         = modname,
527         samba_cflags   = CURRENT_CFLAGS(bld, modname, cflags, hide_symbols=hide_symbols),
528         depends_on     = depends_on,
529         samba_deps     = TO_LIST(deps),
530         samba_includes = includes,
531         local_include  = local_include,
532         local_include_first  = local_include_first,
533         global_include = global_include,
534         samba_subsystem= subsystem_name,
535         samba_use_hostcc = use_hostcc,
536         samba_use_global_deps = use_global_deps
537         )
538
539     if cflags_end is not None:
540         t.samba_cflags.extend(TO_LIST(cflags_end))
541
542     if autoproto is not None:
543         bld.SAMBA_AUTOPROTO(autoproto, source + TO_LIST(autoproto_extra_source))
544     if public_headers is not None:
545         bld.PUBLIC_HEADERS(public_headers, header_path=header_path,
546                            public_headers_install=public_headers_install)
547     return t
548
549
550 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
551
552
553 def SAMBA_GENERATOR(bld, name, rule, source='', target='',
554                     group='generators', enabled=True,
555                     public_headers=None,
556                     public_headers_install=True,
557                     header_path=None,
558                     vars=None,
559                     always=False):
560     '''A generic source generator target'''
561
562     if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
563         return
564
565     if not enabled:
566         return
567
568     bld.SET_BUILD_GROUP(group)
569     t = bld(
570         rule=rule,
571         source=bld.EXPAND_VARIABLES(source, vars=vars),
572         target=target,
573         shell=isinstance(rule, str),
574         on_results=True,
575         before='cc',
576         ext_out='.c',
577         samba_type='GENERATOR',
578         dep_vars = [rule] + (vars or []),
579         name=name)
580
581     if always:
582         t.always = True
583
584     if public_headers is not None:
585         bld.PUBLIC_HEADERS(public_headers, header_path=header_path,
586                            public_headers_install=public_headers_install)
587     return t
588 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
589
590
591
592 @runonce
593 def SETUP_BUILD_GROUPS(bld):
594     '''setup build groups used to ensure that the different build
595     phases happen consecutively'''
596     bld.p_ln = bld.srcnode # we do want to see all targets!
597     bld.env['USING_BUILD_GROUPS'] = True
598     bld.add_group('setup')
599     bld.add_group('build_compiler_source')
600     bld.add_group('vscripts')
601     bld.add_group('base_libraries')
602     bld.add_group('generators')
603     bld.add_group('compiler_prototypes')
604     bld.add_group('compiler_libraries')
605     bld.add_group('build_compilers')
606     bld.add_group('build_source')
607     bld.add_group('prototypes')
608     bld.add_group('headers')
609     bld.add_group('main')
610     bld.add_group('symbolcheck')
611     bld.add_group('libraries')
612     bld.add_group('binaries')
613     bld.add_group('syslibcheck')
614     bld.add_group('final')
615 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
616
617
618 def SET_BUILD_GROUP(bld, group):
619     '''set the current build group'''
620     if not 'USING_BUILD_GROUPS' in bld.env:
621         return
622     bld.set_group(group)
623 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
624
625
626
627 @conf
628 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
629     """use timestamps instead of file contents for deps
630     this currently doesn't work"""
631     def h_file(filename):
632         import stat
633         st = os.stat(filename)
634         if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
635         m = Utils.md5()
636         m.update(str(st.st_mtime))
637         m.update(str(st.st_size))
638         m.update(filename)
639         return m.digest()
640     Utils.h_file = h_file
641
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         link_src = os.path.normpath(os.path.join(bld.curdir, s))
658         link_dst = os.path.join(tgtdir, os.path.basename(iname))
659         if os.path.islink(link_dst) and os.readlink(link_dst) == link_src:
660             continue
661         if os.path.exists(link_dst):
662             os.unlink(link_dst)
663         Logs.info("symlink: %s -> %s/%s" % (s, installdir, iname))
664         os.symlink(link_src, link_dst)
665 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT
666
667
668 def copy_and_fix_python_path(task):
669     pattern='sys.path.insert(0, "bin/python")'
670     if task.env["PYTHONARCHDIR"] in sys.path and task.env["PYTHONDIR"] in sys.path:
671         replacement = ""
672     elif task.env["PYTHONARCHDIR"] == task.env["PYTHONDIR"]:
673         replacement="""sys.path.insert(0, "%s")""" % task.env["PYTHONDIR"]
674     else:
675         replacement="""sys.path.insert(0, "%s")
676 sys.path.insert(1, "%s")""" % (task.env["PYTHONARCHDIR"], task.env["PYTHONDIR"])
677
678     installed_location=task.outputs[0].bldpath(task.env)
679     source_file = open(task.inputs[0].srcpath(task.env))
680     installed_file = open(installed_location, 'w')
681     for line in source_file:
682         newline = line
683         if pattern in line:
684             newline = line.replace(pattern, replacement)
685         installed_file.write(newline)
686     installed_file.close()
687     os.chmod(installed_location, 0755)
688     return 0
689
690
691 def install_file(bld, destdir, file, chmod=MODE_644, flat=False,
692                  python_fixup=False, destname=None, base_name=None):
693     '''install a file'''
694     destdir = bld.EXPAND_VARIABLES(destdir)
695     if not destname:
696         destname = file
697         if flat:
698             destname = os.path.basename(destname)
699     dest = os.path.join(destdir, destname)
700     if python_fixup:
701         # fixup the python path it will use to find Samba modules
702         inst_file = file + '.inst'
703         bld.SAMBA_GENERATOR('python_%s' % destname,
704                             rule=copy_and_fix_python_path,
705                             source=file,
706                             target=inst_file)
707         bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHONARCHDIR"])
708         bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHONDIR"])
709         file = inst_file
710     if base_name:
711         file = os.path.join(base_name, file)
712     bld.install_as(dest, file, chmod=chmod)
713
714
715 def INSTALL_FILES(bld, destdir, files, chmod=MODE_644, flat=False,
716                   python_fixup=False, destname=None, base_name=None):
717     '''install a set of files'''
718     for f in TO_LIST(files):
719         install_file(bld, destdir, f, chmod=chmod, flat=flat,
720                      python_fixup=python_fixup, destname=destname,
721                      base_name=base_name)
722 Build.BuildContext.INSTALL_FILES = INSTALL_FILES
723
724
725 def INSTALL_WILDCARD(bld, destdir, pattern, chmod=MODE_644, flat=False,
726                      python_fixup=False, exclude=None, trim_path=None):
727     '''install a set of files matching a wildcard pattern'''
728     files=TO_LIST(bld.path.ant_glob(pattern))
729     if trim_path:
730         files2 = []
731         for f in files:
732             files2.append(os_path_relpath(f, trim_path))
733         files = files2
734
735     if exclude:
736         for f in files[:]:
737             if fnmatch.fnmatch(f, exclude):
738                 files.remove(f)
739     INSTALL_FILES(bld, destdir, files, chmod=chmod, flat=flat,
740                   python_fixup=python_fixup, base_name=trim_path)
741 Build.BuildContext.INSTALL_WILDCARD = INSTALL_WILDCARD
742
743
744 def INSTALL_DIRS(bld, destdir, dirs):
745     '''install a set of directories'''
746     destdir = bld.EXPAND_VARIABLES(destdir)
747     dirs = bld.EXPAND_VARIABLES(dirs)
748     for d in TO_LIST(dirs):
749         bld.install_dir(os.path.join(destdir, d))
750 Build.BuildContext.INSTALL_DIRS = INSTALL_DIRS
751
752
753 def MANPAGES(bld, manpages):
754     '''build and install manual pages'''
755     bld.env.MAN_XSL = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
756     for m in manpages.split():
757         source = m + '.xml'
758         bld.SAMBA_GENERATOR(m,
759                             source=source,
760                             target=m,
761                             group='final',
762                             rule='${XSLTPROC} -o ${TGT} --nonet ${MAN_XSL} ${SRC}'
763                             )
764         bld.INSTALL_FILES('${MANDIR}/man%s' % m[-1], m, flat=True)
765 Build.BuildContext.MANPAGES = MANPAGES
766
767
768 #############################################################
769 # give a nicer display when building different types of files
770 def progress_display(self, msg, fname):
771     col1 = Logs.colors(self.color)
772     col2 = Logs.colors.NORMAL
773     total = self.position[1]
774     n = len(str(total))
775     fs = '[%%%dd/%%%dd] %s %%s%%s%%s\n' % (n, n, msg)
776     return fs % (self.position[0], self.position[1], col1, fname, col2)
777
778 def link_display(self):
779     if Options.options.progress_bar != 0:
780         return Task.Task.old_display(self)
781     fname = self.outputs[0].bldpath(self.env)
782     return progress_display(self, 'Linking', fname)
783 Task.TaskBase.classes['cc_link'].display = link_display
784
785 def samba_display(self):
786     if Options.options.progress_bar != 0:
787         return Task.Task.old_display(self)
788
789     targets    = LOCAL_CACHE(self, 'TARGET_TYPE')
790     if self.name in targets:
791         target_type = targets[self.name]
792         type_map = { 'GENERATOR' : 'Generating',
793                      'PROTOTYPE' : 'Generating'
794                      }
795         if target_type in type_map:
796             return progress_display(self, type_map[target_type], self.name)
797
798     if len(self.inputs) == 0:
799         return Task.Task.old_display(self)
800
801     fname = self.inputs[0].bldpath(self.env)
802     if fname[0:3] == '../':
803         fname = fname[3:]
804     ext_loc = fname.rfind('.')
805     if ext_loc == -1:
806         return Task.Task.old_display(self)
807     ext = fname[ext_loc:]
808
809     ext_map = { '.idl' : 'Compiling IDL',
810                 '.et'  : 'Compiling ERRTABLE',
811                 '.asn1': 'Compiling ASN1',
812                 '.c'   : 'Compiling' }
813     if ext in ext_map:
814         return progress_display(self, ext_map[ext], fname)
815     return Task.Task.old_display(self)
816
817 Task.TaskBase.classes['Task'].old_display = Task.TaskBase.classes['Task'].display
818 Task.TaskBase.classes['Task'].display = samba_display
819
820
821 @after('apply_link')
822 @feature('cshlib')
823 def apply_bundle_remove_dynamiclib_patch(self):
824     if self.env['MACBUNDLE'] or getattr(self,'mac_bundle',False):
825         if not getattr(self,'vnum',None):
826             try:
827                 self.env['LINKFLAGS'].remove('-dynamiclib')
828                 self.env['LINKFLAGS'].remove('-single_module')
829             except ValueError:
830                 pass