1 # a waf tool to add autoconf-like macros to the configure section
2 # and for SAMBA_ macros for building libraries, binaries etc
4 import Build, os, Options, Task, Utils, cc, TaskGen
5 from Configure import conf
7 from samba_utils import SUBST_VARS_RECURSIVE
9 # bring in the other samba modules
10 from samba_optimisation import *
11 from samba_utils import *
12 from samba_autoconf import *
13 from samba_patterns import *
14 from samba_pidl import *
15 from samba_errtable import *
16 from samba_asn1 import *
17 from samba_autoproto import *
18 from samba_python import *
19 from samba_deps import *
20 import samba_conftests
24 os.putenv('PYTHONUNBUFFERED', '1')
26 #################################################################
27 # create the samba build environment
29 def SAMBA_BUILD_ENV(conf):
30 conf.env['BUILD_DIRECTORY'] = conf.blddir
31 mkdir_p(os.path.join(conf.blddir, LIB_PATH))
32 mkdir_p(os.path.join(conf.blddir, 'python/samba/dcerpc'))
33 # this allows all of the bin/shared and bin/python targets
34 # to be expressed in terms of build directory paths
35 for p in ['python','shared']:
36 link_target = os.path.join(conf.blddir, 'default/' + p)
37 if not os.path.lexists(link_target):
38 os.symlink('../' + p, link_target)
42 ################################################################
43 # add an init_function to the list for a subsystem
44 def ADD_INIT_FUNCTION(bld, subsystem, target, init_function):
45 if init_function is None:
47 bld.ASSERT(subsystem is not None, "You must specify a subsystem for init_function '%s'" % init_function)
48 cache = LOCAL_CACHE(bld, 'INIT_FUNCTIONS')
49 if not subsystem in cache:
51 cache[subsystem].append( { 'TARGET':target, 'INIT_FUNCTION':init_function } )
52 Build.BuildContext.ADD_INIT_FUNCTION = ADD_INIT_FUNCTION
55 #################################################################
56 # define a Samba library
57 def SAMBA_LIBRARY(bld, libname, source,
64 external_library=False,
76 SET_TARGET_TYPE(bld, libname, 'DISABLED')
79 source = bld.EXPAND_VARIABLES(source, vars=vars)
81 # remember empty libraries, so we can strip the dependencies
82 if (source == '') or (source == []):
83 SET_TARGET_TYPE(bld, libname, 'EMPTY')
86 if bld.env.DISABLE_SHARED:
89 obj_target = libname + '.objlist'
91 # first create a target for building the object files for this library
92 # by separating in this way, we avoid recompiling the C files
93 # separately for the install library and the build library
94 bld.SAMBA_SUBSYSTEM(obj_target,
97 public_deps = public_deps,
99 public_headers = public_headers,
102 autoproto = autoproto,
103 depends_on = depends_on,
104 local_include = local_include)
106 if bld.env.DISABLE_SHARED:
109 if not SET_TARGET_TYPE(bld, libname, 'LIBRARY'):
112 # the library itself will depend on that object target
113 deps += ' ' + public_deps
115 deps.append(obj_target)
117 bld.SET_BUILD_GROUP(group)
119 features = 'cc cshlib symlink_lib',
122 samba_cflags = CURRENT_CFLAGS(bld, libname, cflags),
123 depends_on = depends_on,
125 samba_includes = includes,
126 local_include = local_include,
129 ldflags = build_rpath(bld)
132 if install_path is None:
133 install_path = '${LIBDIR}'
134 install_path = SUBST_VARS_RECURSIVE(install_path, bld.env)
136 # we don't need the double libraries if rpath is off
137 if (bld.env.RPATH_ON_INSTALL == False and
138 bld.env.RPATH_ON_BUILD == False):
139 install_target = libname
141 install_target = libname + '.inst'
143 if install and install_target != libname:
144 # create a separate install library, which may have
145 # different rpath settings
146 SET_TARGET_TYPE(bld, install_target, 'LIBRARY')
148 features = 'cc cshlib',
150 target = install_target,
151 samba_cflags = CURRENT_CFLAGS(bld, libname, cflags),
152 depends_on = depends_on,
154 samba_includes = includes,
155 local_include = local_include,
157 install_as = libname,
159 ldflags = install_rpath(bld)
164 vnum_base = vnum.split('.')[0]
165 install_name = 'lib%s.so.%s' % (libname, vnum)
166 install_link = 'lib%s.so.%s' % (libname, vnum_base)
168 install_name = 'lib%s.so' % libname
171 bld.install_as(os.path.join(install_path, install_name),
172 'lib%s.inst.so' % libname)
174 bld.symlink_as(os.path.join(install_path, install_link), install_name)
176 if autoproto is not None:
177 bld.SAMBA_AUTOPROTO(autoproto, source)
179 Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY
182 #################################################################
183 # define a Samba binary
184 def SAMBA_BINARY(bld, binname, source,
204 if not SET_TARGET_TYPE(bld, binname, 'BINARY'):
207 features = 'cc cprogram'
209 features += ' pyembed'
211 bld.SET_BUILD_GROUP(group)
213 obj_target = binname + '.objlist'
215 source = bld.EXPAND_VARIABLES(source, vars=vars)
217 # first create a target for building the object files for this binary
218 # by separating in this way, we avoid recompiling the C files
219 # separately for the install binary and the build binary
220 bld.SAMBA_SUBSYSTEM(obj_target,
226 autoproto = autoproto,
227 subsystem_name = subsystem_name,
228 needs_python = needs_python,
229 local_include = local_include)
231 # the library itself will depend on that object target
233 deps.append(obj_target)
236 features = features + ' symlink_bin',
239 samba_cflags = CURRENT_CFLAGS(bld, binname, cflags),
241 samba_includes = includes,
242 local_include = local_include,
243 samba_modules = modules,
245 samba_subsystem= subsystem_name,
247 ldflags = build_rpath(bld)
250 if install_path is None:
251 install_path = '${BINDIR}'
252 install_path = SUBST_VARS_RECURSIVE(install_path, bld.env)
254 # we don't need the double binaries if rpath is off
255 if (bld.env.RPATH_ON_INSTALL == False and
256 bld.env.RPATH_ON_BUILD == False):
257 install_target = binname
259 install_target = binname + '.inst'
261 if install and install_target != binname:
262 # we create a separate 'install' binary, which
263 # will have different rpath settings
264 SET_TARGET_TYPE(bld, install_target, 'BINARY')
268 target = install_target,
269 samba_cflags = CURRENT_CFLAGS(bld, binname, cflags),
271 samba_includes = includes,
272 local_include = local_include,
273 samba_modules = modules,
275 samba_subsystem= subsystem_name,
277 ldflags = install_rpath(bld)
281 bld.install_as(os.path.join(install_path, binname),
285 # setup the subsystem_name as an alias for the real
286 # binary name, so it can be found when expanding
287 # subsystem dependencies
288 if subsystem_name is not None:
289 bld.TARGET_ALIAS(subsystem_name, binname)
291 if autoproto is not None:
292 bld.SAMBA_AUTOPROTO(autoproto, source)
293 Build.BuildContext.SAMBA_BINARY = SAMBA_BINARY
296 #################################################################
297 # define a Samba module.
298 def SAMBA_MODULE(bld, modname, source,
304 autoproto_extra_source='',
307 internal_module=True,
312 # we add the init function regardless of whether the module
313 # is enabled or not, as we need to generate a null list if
315 bld.ADD_INIT_FUNCTION(subsystem, modname, init_function)
317 if internal_module or bld.env.DISABLE_SHARED:
318 # treat internal modules as subsystems for now
319 SAMBA_SUBSYSTEM(bld, modname, source,
323 autoproto_extra_source=autoproto_extra_source,
325 local_include=local_include,
330 SET_TARGET_TYPE(bld, modname, 'DISABLED')
333 source = bld.EXPAND_VARIABLES(source, vars=vars)
335 # remember empty modules, so we can strip the dependencies
336 if (source == '') or (source == []):
337 SET_TARGET_TYPE(bld, modname, 'EMPTY')
340 if not SET_TARGET_TYPE(bld, modname, 'MODULE'):
343 if subsystem is not None:
344 deps += ' ' + subsystem
346 bld.SET_BUILD_GROUP('main')
351 samba_cflags = CURRENT_CFLAGS(bld, modname, cflags),
352 samba_includes = includes,
353 local_include = local_include,
354 samba_deps = TO_LIST(deps)
357 if autoproto is not None:
358 bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
360 Build.BuildContext.SAMBA_MODULE = SAMBA_MODULE
363 #################################################################
364 # define a Samba subsystem
365 def SAMBA_SUBSYSTEM(bld, modname, source,
373 init_function_sentinal=None,
374 heimdal_autoproto=None,
375 heimdal_autoproto_options=None,
376 heimdal_autoproto_private=None,
378 autoproto_extra_source='',
381 local_include_first=True,
388 SET_TARGET_TYPE(bld, modname, 'DISABLED')
391 # remember empty subsystems, so we can strip the dependencies
392 if (source == '') or (source == []):
393 SET_TARGET_TYPE(bld, modname, 'EMPTY')
396 if not SET_TARGET_TYPE(bld, modname, 'SUBSYSTEM'):
399 source = bld.EXPAND_VARIABLES(source, vars=vars)
401 deps += ' ' + public_deps
403 bld.SET_BUILD_GROUP(group)
413 samba_cflags = CURRENT_CFLAGS(bld, modname, cflags),
414 depends_on = depends_on,
415 samba_deps = TO_LIST(deps),
416 samba_includes = includes,
417 local_include = local_include,
418 local_include_first = local_include_first,
419 samba_subsystem= subsystem_name
422 if cflags_end is not None:
423 t.samba_cflags.extend(TO_LIST(cflags_end))
425 if heimdal_autoproto is not None:
426 bld.HEIMDAL_AUTOPROTO(heimdal_autoproto, source, options=heimdal_autoproto_options)
427 if heimdal_autoproto_private is not None:
428 bld.HEIMDAL_AUTOPROTO_PRIVATE(heimdal_autoproto_private, source)
429 if autoproto is not None:
430 bld.SAMBA_AUTOPROTO(autoproto, source + ' ' + autoproto_extra_source)
433 Build.BuildContext.SAMBA_SUBSYSTEM = SAMBA_SUBSYSTEM
436 def SAMBA_GENERATOR(bld, name, rule, source, target,
437 group='build_source', enabled=True,
439 '''A generic source generator target'''
441 if not SET_TARGET_TYPE(bld, name, 'GENERATOR'):
447 bld.SET_BUILD_GROUP(group)
450 source=bld.EXPAND_VARIABLES(source, vars=vars),
457 Build.BuildContext.SAMBA_GENERATOR = SAMBA_GENERATOR
461 ###############################################################
462 # add a new set of build rules from a subdirectory
463 # the @runonce decorator ensures we don't end up
464 # with duplicate rules
465 def BUILD_SUBDIR(bld, dir):
466 path = os.path.normpath(bld.curdir + '/' + dir)
467 cache = LOCAL_CACHE(bld, 'SUBDIR_LIST')
468 if path in cache: return
470 debug("build: Processing subdirectory %s" % dir)
473 Build.BuildContext.BUILD_SUBDIR = BUILD_SUBDIR
476 ##########################################################
477 # add a new top level command to waf
478 def ADD_COMMAND(opt, name, function):
479 Utils.g_module.__dict__[name] = function
481 Options.Handler.ADD_COMMAND = ADD_COMMAND
483 ###########################################################
484 # setup build groups used to ensure that the different build
485 # phases happen consecutively
487 def SETUP_BUILD_GROUPS(bld):
488 bld.p_ln = bld.srcnode # we do want to see all targets!
489 bld.env['USING_BUILD_GROUPS'] = True
490 bld.add_group('setup')
491 bld.add_group('build_compiler_source')
492 bld.add_group('base_libraries')
493 bld.add_group('build_compilers')
494 bld.add_group('build_source')
495 bld.add_group('prototypes')
496 bld.add_group('main')
497 bld.add_group('binaries')
498 bld.add_group('final')
499 Build.BuildContext.SETUP_BUILD_GROUPS = SETUP_BUILD_GROUPS
502 ###########################################################
503 # set the current build group
504 def SET_BUILD_GROUP(bld, group):
505 if not 'USING_BUILD_GROUPS' in bld.env:
508 Build.BuildContext.SET_BUILD_GROUP = SET_BUILD_GROUP
511 def h_file(filename):
513 st = os.stat(filename)
514 if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file')
516 m.update(str(st.st_mtime))
517 m.update(str(st.st_size))
522 def ENABLE_TIMESTAMP_DEPENDENCIES(conf):
523 Utils.h_file = h_file
526 ##############################
527 # handle the creation of links for libraries and binaries
528 # note that we use a relative symlink path to allow the whole tree
529 # to me moved/copied elsewhere without breaking the links
530 t = Task.simple_task_type('symlink_lib', 'rm -f ${LINK_TARGET} && ln -s ${LINK_SOURCE} ${LINK_TARGET}',
531 shell=True, color='PINK', ext_in='.bin')
534 @feature('symlink_lib')
536 def symlink_lib(self):
537 tsk = self.create_task('symlink_lib', self.link_task.outputs[0])
539 # calculat the link target and put it in the environment
541 vnum = getattr(self, 'vnum', None)
543 soext = '.' + vnum.split('.')[0]
545 link_target = getattr(self, 'link_name', '')
546 if link_target == '':
547 link_target = '%s/lib%s.so%s' % (LIB_PATH, self.sname, soext)
550 link_source = os_path_relpath(self.link_task.outputs[0].abspath(self.env),
551 os.path.join(self.env.BUILD_DIRECTORY, link_target))
553 tsk.env.LINK_TARGET = link_target
554 tsk.env.LINK_SOURCE = link_source[3:]
555 debug('task_gen: LINK for %s is %s -> %s',
556 self.name, tsk.env.LINK_SOURCE, tsk.env.LINK_TARGET)
559 t = Task.simple_task_type('symlink_bin', 'rm -f ${BIN_TARGET} && ln -s ${SRC} ${BIN_TARGET}',
560 shell=True, color='PINK', ext_in='.bin')
563 @feature('symlink_bin')
565 def symlink_bin(self):
566 if Options.is_install:
567 # we don't want to copy the install binary, as
568 # that has the install rpath, not the build rpath
569 # The rpath of the binaries in bin/default/foo/blah is different
570 # during the install phase, as distros insist on not using rpath in installed binaries
572 tsk = self.create_task('symlink_bin', self.link_task.outputs[0])
574 tsk.env.BIN_TARGET = self.target
575 debug('task_gen: BIN_TARGET for %s is %s', self.name, tsk.env.BIN_TARGET)
580 t = Task.simple_task_type('copy_script', 'rm -f && ln -s ${SRC[0].abspath(env)} ${LINK_TARGET}',
581 shell=True, color='PINK', ext_in='.bin')
584 @feature('copy_script')
585 @before('apply_link')
586 def copy_script(self):
587 tsk = self.create_task('copy_script', self.allnodes[0])
588 tsk.env.TARGET = self.target
590 def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None):
591 '''used to copy scripts from the source tree into the build directory
592 for use by selftest'''
594 source = bld.path.ant_glob(pattern)
596 bld.SET_BUILD_GROUP('build_source')
597 for s in TO_LIST(source):
599 if installname != None:
601 target = os.path.join(installdir, iname)
602 tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target))
604 t = bld(features='copy_script',
609 t.env.LINK_TARGET = target
611 Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT