1########################### 2# this handles the magic we need to do for installing 3# with all the configure options that affect rpath and shared 4# library use 5 6import os 7from waflib import Utils, Errors 8from waflib.TaskGen import feature, before, after 9from samba_utils import LIB_PATH, MODE_755, install_rpath, build_rpath 10 11@feature('install_bin') 12@after('apply_core') 13@before('apply_link', 'apply_obj_vars') 14def install_binary(self): 15 '''install a binary, taking account of the different rpath variants''' 16 bld = self.bld 17 18 # get the ldflags we will use for install and build 19 install_ldflags = install_rpath(self) 20 build_ldflags = build_rpath(bld) 21 22 if not self.bld.is_install: 23 # just need to set rpath if we are not installing 24 self.env.RPATH = build_ldflags 25 return 26 27 # work out the install path, expanding variables 28 install_path = getattr(self, 'samba_inst_path', None) or '${BINDIR}' 29 install_path = bld.EXPAND_VARIABLES(install_path) 30 31 orig_target = os.path.basename(self.target) 32 33 if install_ldflags != build_ldflags: 34 # we will be creating a new target name, and using that for the 35 # install link. That stops us from overwriting the existing build 36 # target, which has different ldflags 37 self.target += '.inst' 38 39 # setup the right rpath link flags for the install 40 self.env.RPATH = install_ldflags 41 42 if not self.samba_install: 43 # this binary is marked not to be installed 44 return 45 46 # tell waf to install the right binary 47 bld.install_as(os.path.join(install_path, orig_target), 48 self.path.find_or_declare(self.target), 49 chmod=MODE_755) 50 51 52 53@feature('install_lib') 54@after('apply_core') 55@before('apply_link', 'apply_obj_vars') 56def install_library(self): 57 '''install a library, taking account of the different rpath variants''' 58 if getattr(self, 'done_install_library', False): 59 return 60 61 bld = self.bld 62 63 default_env = bld.all_envs['default'] 64 try: 65 install_ldflags = install_rpath(self) 66 build_ldflags = build_rpath(bld) 67 68 if not self.bld.is_install or not getattr(self, 'samba_install', True): 69 # just need to set the build rpath if we are not installing 70 self.env.RPATH = build_ldflags 71 return 72 73 # setup the install path, expanding variables 74 install_path = getattr(self, 'samba_inst_path', None) 75 if install_path is None: 76 if getattr(self, 'private_library', False): 77 install_path = '${PRIVATELIBDIR}' 78 else: 79 install_path = '${LIBDIR}' 80 install_path = bld.EXPAND_VARIABLES(install_path) 81 82 target_name = self.target 83 84 if install_ldflags != build_ldflags: 85 # we will be creating a new target name, and using that for the 86 # install link. That stops us from overwriting the existing build 87 # target, which has different ldflags 88 self.done_install_library = True 89 t = self.clone(self.env) 90 t.posted = False 91 t.target += '.inst' 92 t.name = self.name + '.inst' 93 self.env.RPATH = build_ldflags 94 else: 95 t = self 96 97 t.env.RPATH = install_ldflags 98 99 dev_link = None 100 101 # in the following the names are: 102 # - inst_name is the name with .inst. in it, in the build 103 # directory 104 # - install_name is the name in the install directory 105 # - install_link is a symlink in the install directory, to install_name 106 107 if getattr(self, 'samba_realname', None): 108 install_name = self.samba_realname 109 install_link = None 110 if getattr(self, 'soname', ''): 111 install_link = self.soname 112 if getattr(self, 'samba_type', None) == 'PYTHON': 113 inst_name = bld.make_libname(t.target, nolibprefix=True, python=True) 114 else: 115 inst_name = bld.make_libname(t.target) 116 elif self.vnum: 117 vnum_base = self.vnum.split('.')[0] 118 install_name = bld.make_libname(target_name, version=vnum_base) 119 install_link = bld.make_libname(target_name, version=vnum_base) 120 inst_name = bld.make_libname(t.target) 121 if not self.private_library or not t.env.SONAME_ST: 122 # only generate the dev link for non-bundled libs 123 dev_link = bld.make_libname(target_name) 124 elif getattr(self, 'soname', ''): 125 install_name = bld.make_libname(target_name) 126 install_link = self.soname 127 inst_name = bld.make_libname(t.target) 128 else: 129 install_name = bld.make_libname(target_name) 130 install_link = None 131 inst_name = bld.make_libname(t.target) 132 133 if t.env.SONAME_ST: 134 # ensure we get the right names in the library 135 if install_link: 136 t.env.append_value('LINKFLAGS', t.env.SONAME_ST % install_link) 137 else: 138 t.env.append_value('LINKFLAGS', t.env.SONAME_ST % install_name) 139 t.env.SONAME_ST = '' 140 141 # tell waf to install the library 142 bld.install_as(os.path.join(install_path, install_name), 143 self.path.find_or_declare(inst_name), 144 chmod=MODE_755) 145 146 if install_link and install_link != install_name: 147 # and the symlink if needed 148 bld.symlink_as(os.path.join(install_path, install_link), os.path.basename(install_name)) 149 if dev_link: 150 bld.symlink_as(os.path.join(install_path, dev_link), os.path.basename(install_name)) 151 finally: 152 bld.all_envs['default'] = default_env 153 154 155@feature('cshlib') 156@after('apply_implib') 157@before('apply_vnum') 158def apply_soname(self): 159 '''install a library, taking account of the different rpath variants''' 160 161 if self.env.SONAME_ST and getattr(self, 'soname', ''): 162 self.env.append_value('LINKFLAGS', self.env.SONAME_ST % self.soname) 163 self.env.SONAME_ST = '' 164 165@feature('cshlib') 166@after('apply_implib') 167@before('apply_vnum') 168def apply_vscript(self): 169 '''add version-script arguments to library build''' 170 171 if self.env.HAVE_LD_VERSION_SCRIPT and getattr(self, 'version_script', ''): 172 self.env.append_value('LINKFLAGS', "-Wl,--version-script=%s" % 173 self.version_script) 174 self.version_script = None 175 176 177############################## 178# handle the creation of links for libraries and binaries in the build tree 179 180@feature('symlink_lib') 181@after('apply_link') 182def symlink_lib(self): 183 '''symlink a shared lib''' 184 185 if self.target.endswith('.inst'): 186 return 187 188 blddir = os.path.dirname(self.bld.srcnode.abspath(self.bld.env)) 189 libpath = self.link_task.outputs[0].abspath(self.env) 190 191 # calculat the link target and put it in the environment 192 soext="" 193 vnum = getattr(self, 'vnum', None) 194 if vnum is not None: 195 soext = '.' + vnum.split('.')[0] 196 197 link_target = getattr(self, 'link_name', '') 198 if link_target == '': 199 basename = os.path.basename(self.bld.make_libname(self.target, version=soext)) 200 if getattr(self, "private_library", False): 201 link_target = '%s/private/%s' % (LIB_PATH, basename) 202 else: 203 link_target = '%s/%s' % (LIB_PATH, basename) 204 205 link_target = os.path.join(blddir, link_target) 206 207 if os.path.lexists(link_target): 208 if os.path.islink(link_target) and os.readlink(link_target) == libpath: 209 return 210 os.unlink(link_target) 211 212 link_container = os.path.dirname(link_target) 213 if not os.path.isdir(link_container): 214 os.makedirs(link_container) 215 216 os.symlink(libpath, link_target) 217 218 219@feature('symlink_bin') 220@after('apply_link') 221def symlink_bin(self): 222 '''symlink a binary into the build directory''' 223 224 if self.target.endswith('.inst'): 225 return 226 227 if not self.link_task.outputs or not self.link_task.outputs[0]: 228 raise Errors.WafError('no outputs found for %s in symlink_bin' % self.name) 229 binpath = self.link_task.outputs[0].abspath(self.env) 230 bldpath = os.path.join(self.bld.env.BUILD_DIRECTORY, self.link_task.outputs[0].name) 231 232 if os.path.lexists(bldpath): 233 if os.path.islink(bldpath) and os.readlink(bldpath) == binpath: 234 return 235 os.unlink(bldpath) 236 os.symlink(binpath, bldpath) 237