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