From e9fd67f4deaa822bec025f8cc2557b825a05f3ef Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Mar 2010 23:47:48 +1100 Subject: build: split build and install libraries/binaries we need to split these to avoid re-compilation on install as install has different rpath settings --- buildtools/wafsamba/samba_deps.py | 19 ++++- buildtools/wafsamba/samba_utils.py | 23 +++--- buildtools/wafsamba/wafsamba.py | 160 +++++++++++++++++++++++++++++++------ 3 files changed, 162 insertions(+), 40 deletions(-) (limited to 'buildtools') diff --git a/buildtools/wafsamba/samba_deps.py b/buildtools/wafsamba/samba_deps.py index f20bccba06..fa34cb8fcf 100644 --- a/buildtools/wafsamba/samba_deps.py +++ b/buildtools/wafsamba/samba_deps.py @@ -15,7 +15,9 @@ def ADD_GLOBAL_DEPENDENCY(ctx, dep): def TARGET_ALIAS(bld, target, alias): '''define an alias for a target name''' cache = LOCAL_CACHE(bld, 'TARGET_ALIAS') - bld.ASSERT(alias not in cache, "Target alias %s already set" % alias) + if alias in cache: + print("Target alias %s already set to %s : newalias %s" % (alias, cache[alias], target)) + raise cache[alias] = target Build.BuildContext.TARGET_ALIAS = TARGET_ALIAS @@ -173,9 +175,14 @@ def add_init_functions(self): subsystems = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') + # cope with the separated object lists from BINARY and LIBRARY targets + sname = self.sname + if sname.endswith('.objlist'): + sname = sname[0:-8] + modules = [] - if self.sname in subsystems: - modules.append(self.sname) + if sname in subsystems: + modules.append(sname) m = getattr(self, 'samba_modules', None) if m is not None: @@ -544,6 +551,9 @@ def calculate_final_deps(bld, tgt_list): for l in t.final_libs.copy(): t2 = bld.name_to_obj(l, bld.env) if t.sname in t2.final_libs: + # we could break this in either direction. If one of the libraries + # has a version number, and will this be distributed publicly, then + # we should make it the lower level library in the DAG debug('deps: removing library loop %s<->%s', t.sname, l) t2.final_libs.remove(t.sname) loops[t2.sname] = t.sname; @@ -702,6 +712,9 @@ def check_project_rules(bld): if not type in ['SUBSYSTEM', 'MODULE', 'BINARY', 'LIBRARY', 'ASN1', 'PYTHON']: continue t = bld.name_to_obj(tgt, bld.env) + if t is None: + print "Target %s of type %s has no task generator" % (tgt, type) + raise tgt_list.append(t) add_samba_attributes(bld, tgt_list) diff --git a/buildtools/wafsamba/samba_utils.py b/buildtools/wafsamba/samba_utils.py index 5fbb801ef6..a5d42e4f7f 100644 --- a/buildtools/wafsamba/samba_utils.py +++ b/buildtools/wafsamba/samba_utils.py @@ -51,23 +51,18 @@ def runonce(function): -################################################################ -# magic rpath handling -# -# we want a different rpath when installing and when building -# Note that this should really check if rpath is available on this platform -# and it should also honor an --enable-rpath option def set_rpath(bld): - if Options.is_install: - if bld.env['RPATH_ON_INSTALL']: - bld.env['RPATH'] = ['-Wl,-rpath=%s/lib' % bld.env.PREFIX] - else: - bld.env['RPATH'] = [] - else: - rpath = os.path.normpath('%s/%s' % (bld.env['BUILD_DIRECTORY'], LIB_PATH)) - bld.env.append_value('RPATH', '-Wl,-rpath=%s' % rpath) + '''setup the default rpath''' + rpath = os.path.normpath('%s/%s' % (bld.env['BUILD_DIRECTORY'], LIB_PATH)) + bld.env.append_value('RPATH', '-Wl,-rpath=%s' % rpath) Build.BuildContext.set_rpath = set_rpath +def install_rpath(bld): + '''the rpath value for installation''' + if bld.env['RPATH_ON_INSTALL']: + return ['-Wl,-rpath=%s/lib' % bld.env.PREFIX] + return [] + ############################################################# # return a named build cache dictionary, used to store diff --git a/buildtools/wafsamba/wafsamba.py b/buildtools/wafsamba/wafsamba.py index 6cdcc35dd4..c0d428e507 100644 --- a/buildtools/wafsamba/wafsamba.py +++ b/buildtools/wafsamba/wafsamba.py @@ -1,7 +1,7 @@ # a waf tool to add autoconf-like macros to the configure section # and for SAMBA_ macros for building libraries, binaries etc -import Build, os, Options, Task, Utils, cc +import Build, os, Options, Task, Utils, cc, TaskGen from Configure import conf from Logs import debug @@ -64,7 +64,14 @@ def SAMBA_LIBRARY(bld, libname, source, autoproto=None, group='main', depends_on='', - local_include=True): + local_include=True, + install_path=None, + install=True, + enabled=True): + + if not enabled: + SET_TARGET_TYPE(bld, libname, 'DISABLED') + return # remember empty libraries, so we can strip the dependencies if (source == '') or (source == []): @@ -74,26 +81,84 @@ def SAMBA_LIBRARY(bld, libname, source, if not SET_TARGET_TYPE(bld, libname, 'LIBRARY'): return + obj_target = libname + '.objlist' + + # first create a target for building the object files for this library + # by separating in this way, we avoid recompiling the C files + # separately for the install library and the build library + bld.SAMBA_SUBSYSTEM(obj_target, + source = source, + deps = deps, + public_deps = public_deps, + includes = includes, + public_headers = public_headers, + cflags = cflags, + group = group, + autoproto = autoproto, + depends_on = depends_on, + local_include = local_include) + + # the library itself will depend on that object target deps += ' ' + public_deps + deps = TO_LIST(deps) + deps.append(obj_target) - # this print below should show that we're runnig this code bld.SET_BUILD_GROUP(group) t = bld( features = 'cc cshlib symlink_lib', - source = source, + source = [], target = libname, samba_cflags = CURRENT_CFLAGS(bld, libname, cflags), depends_on = depends_on, - samba_deps = TO_LIST(deps), + samba_deps = deps, samba_includes = includes, local_include = local_include, - vnum = vnum + vnum = vnum, + install_path = None ) + + if install_path is None: + install_path = '${PREFIX}/lib' + + if install: + # create a separate install library, which may have + # different rpath settings + SET_TARGET_TYPE(bld, libname + '.inst', 'LIBRARY') + t = bld( + features = 'cc cshlib', + source = [], + target = libname + '.inst', + samba_cflags = CURRENT_CFLAGS(bld, libname, cflags), + depends_on = depends_on, + samba_deps = deps, + samba_includes = includes, + local_include = local_include, + vnum = vnum, + install_as = libname, + install_path = None, + ) + t.env['RPATH'] = install_rpath(bld) + + if vnum: + vnum_base = vnum.split('.')[0] + install_name = 'lib%s.so.%s' % (libname, vnum) + install_link = 'lib%s.so.%s' % (libname, vnum_base) + else: + install_name = 'lib%s.so' % libname + install_link = None + + bld.install_as(os.path.join(install_path, install_name), + 'lib%s.inst.so' % libname) + if install_link: + bld.symlink_as(os.path.join(install_path, install_link), install_name) + + if autoproto is not None: bld.SAMBA_AUTOPROTO(autoproto, source) Build.BuildContext.SAMBA_LIBRARY = SAMBA_LIBRARY + ################################################################# # define a Samba binary def SAMBA_BINARY(bld, binname, source, @@ -111,29 +176,79 @@ def SAMBA_BINARY(bld, binname, source, manpages=None, local_include=True, subsystem_name=None, - needs_python=False): + needs_python=False, + install=True, + install_path=None): if not SET_TARGET_TYPE(bld, binname, 'BINARY'): return - features = 'cc cprogram copy_bin' + features = 'cc cprogram' if needs_python: features += ' pyembed' bld.SET_BUILD_GROUP(group) + + obj_target = binname + '.objlist' + + # first create a target for building the object files for this binary + # by separating in this way, we avoid recompiling the C files + # separately for the install binary and the build binary + bld.SAMBA_SUBSYSTEM(obj_target, + source = source, + deps = deps, + includes = includes, + cflags = cflags, + group = group, + autoproto = autoproto, + subsystem_name = subsystem_name, + needs_python = needs_python, + local_include = local_include) + + # the library itself will depend on that object target + deps = TO_LIST(deps) + deps.append(obj_target) + bld( - features = features, - source = source, + features = features + ' symlink_bin', + source = [], target = binname, samba_cflags = CURRENT_CFLAGS(bld, binname, cflags), - samba_deps = TO_LIST(deps), + samba_deps = deps, samba_includes = includes, local_include = local_include, samba_modules = modules, top = True, - samba_subsystem= subsystem_name + samba_subsystem= subsystem_name, + install_path = None ) + if install_path is None: + install_path = '${PREFIX}/bin' + + if install: + # we create a separate 'install' binary, which + # will have different rpath settings + SET_TARGET_TYPE(bld, binname + '.inst', 'BINARY') + t = bld( + features = features, + source = [], + target = binname + '.inst', + samba_cflags = CURRENT_CFLAGS(bld, binname, cflags), + samba_deps = deps, + samba_includes = includes, + local_include = local_include, + samba_modules = modules, + top = True, + samba_subsystem= subsystem_name, + install_path = None + ) + t.env['RPATH'] = install_rpath(bld) + + bld.install_as(os.path.join(install_path, binname), + binname + '.inst', + chmod=0755) + # setup the subsystem_name as an alias for the real # binary name, so it can be found when expanding # subsystem dependencies @@ -223,7 +338,6 @@ def SAMBA_SUBSYSTEM(bld, modname, source, cflags='', cflags_end=None, group='main', - config_option=None, init_function_sentinal=None, heimdal_autoproto=None, heimdal_autoproto_options=None, @@ -398,22 +512,21 @@ def symlink_lib(self): debug('task_gen: LINK for %s is %s -> %s', self.name, tsk.env.LINK_SOURCE, tsk.env.LINK_TARGET) -# for binaries we need to copy the executable to avoid the rpath changing -# in the local bin/ directory on install -t = Task.simple_task_type('copy_bin', 'rm -f ${BIN_TARGET} && cp ${SRC} ${BIN_TARGET}', color='PINK', - ext_in='.bin', shell=True) + +t = Task.simple_task_type('symlink_bin', 'ln -sf ${SRC} ${BIN_TARGET}', + color='PINK', ext_in='.bin') t.quiet = True -@feature('copy_bin') +@feature('symlink_bin') @after('apply_link') -def copy_bin(self): +def symlink_bin(self): if Options.is_install: # we don't want to copy the install binary, as # that has the install rpath, not the build rpath # The rpath of the binaries in bin/default/foo/blah is different # during the install phase, as distros insist on not using rpath in installed binaries return - tsk = self.create_task('copy_bin', self.link_task.outputs[0]) + tsk = self.create_task('symlink_bin', self.link_task.outputs[0]) tsk.env.BIN_TARGET = self.target debug('task_gen: BIN_TARGET for %s is %s', self.name, tsk.env.BIN_TARGET) @@ -446,9 +559,10 @@ def SAMBA_SCRIPT(bld, name, pattern, installdir, installname=None): tgtdir = os.path.dirname(os.path.join(bld.srcnode.abspath(bld.env), '..', target)) mkdir_p(tgtdir) t = bld(features='copy_script', - source=s, - target = target, - always=True) + source = s, + target = target, + always = True, + install_path = None) t.env.LINK_TARGET = target Build.BuildContext.SAMBA_SCRIPT = SAMBA_SCRIPT -- cgit