wafbuild: create missing private library symlinks on platforms without soname support...
[sfrench/samba-autobuild/.git] / buildtools / wafsamba / samba_install.py
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
6 import os
7 from waflib import Utils, Errors
8 from waflib.TaskGen import feature, before, after
9 from 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')
14 def install_binary(self):
15     '''install a binary, taking account of the different rpath varients'''
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')
56 def install_library(self):
57     '''install a library, taking account of the different rpath varients'''
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         if self.env['IS_EXTRA_PYTHON']:
66             bld.all_envs['default'] = bld.all_envs['extrapython']
67
68         install_ldflags = install_rpath(self)
69         build_ldflags   = build_rpath(bld)
70
71         if not self.bld.is_install or not getattr(self, 'samba_install', True):
72             # just need to set the build rpath if we are not installing
73             self.env.RPATH = build_ldflags
74             return
75
76         # setup the install path, expanding variables
77         install_path = getattr(self, 'samba_inst_path', None)
78         if install_path is None:
79             if getattr(self, 'private_library', False):
80                 install_path = '${PRIVATELIBDIR}'
81             else:
82                 install_path = '${LIBDIR}'
83         install_path = bld.EXPAND_VARIABLES(install_path)
84
85         target_name = self.target
86
87         if install_ldflags != build_ldflags:
88             # we will be creating a new target name, and using that for the
89             # install link. That stops us from overwriting the existing build
90             # target, which has different ldflags
91             self.done_install_library = True
92             t = self.clone(self.env)
93             t.posted = False
94             t.target += '.inst'
95             t.name = self.name + '.inst'
96             self.env.RPATH = build_ldflags
97         else:
98             t = self
99
100         t.env.RPATH = install_ldflags
101
102         dev_link     = None
103
104         # in the following the names are:
105         # - inst_name is the name with .inst. in it, in the build
106         #   directory
107         # - install_name is the name in the install directory
108         # - install_link is a symlink in the install directory, to install_name
109
110         if getattr(self, 'samba_realname', None):
111             install_name = self.samba_realname
112             install_link = None
113             if getattr(self, 'soname', ''):
114                 install_link = self.soname
115             if getattr(self, 'samba_type', None) == 'PYTHON':
116                 inst_name    = bld.make_libname(t.target, nolibprefix=True, python=True)
117             else:
118                 inst_name    = bld.make_libname(t.target)
119         elif self.vnum:
120             vnum_base    = self.vnum.split('.')[0]
121             install_name = bld.make_libname(target_name, version=self.vnum)
122             install_link = bld.make_libname(target_name, version=vnum_base)
123             inst_name    = bld.make_libname(t.target)
124             if not self.private_library or not t.env.SONAME_ST:
125                 # only generate the dev link for non-bundled libs
126                 dev_link     = bld.make_libname(target_name)
127         elif getattr(self, 'soname', ''):
128             install_name = bld.make_libname(target_name)
129             install_link = self.soname
130             inst_name    = bld.make_libname(t.target)
131         else:
132             install_name = bld.make_libname(target_name)
133             install_link = None
134             inst_name    = bld.make_libname(t.target)
135
136         if t.env.SONAME_ST:
137             # ensure we get the right names in the library
138             if install_link:
139                 t.env.append_value('LINKFLAGS', t.env.SONAME_ST % install_link)
140             else:
141                 t.env.append_value('LINKFLAGS', t.env.SONAME_ST % install_name)
142             t.env.SONAME_ST = ''
143
144         # tell waf to install the library
145         bld.install_as(os.path.join(install_path, install_name),
146                        self.path.find_or_declare(inst_name),
147                        chmod=MODE_755)
148
149         if install_link and install_link != install_name:
150             # and the symlink if needed
151             bld.symlink_as(os.path.join(install_path, install_link), os.path.basename(install_name))
152         if dev_link:
153             bld.symlink_as(os.path.join(install_path, dev_link), os.path.basename(install_name))
154     finally:
155         bld.all_envs['default'] = default_env
156
157
158 @feature('cshlib')
159 @after('apply_implib')
160 @before('apply_vnum')
161 def apply_soname(self):
162     '''install a library, taking account of the different rpath varients'''
163
164     if self.env.SONAME_ST and getattr(self, 'soname', ''):
165         self.env.append_value('LINKFLAGS', self.env.SONAME_ST % self.soname)
166         self.env.SONAME_ST = ''
167
168 @feature('cshlib')
169 @after('apply_implib')
170 @before('apply_vnum')
171 def apply_vscript(self):
172     '''add version-script arguments to library build'''
173
174     if self.env.HAVE_LD_VERSION_SCRIPT and getattr(self, 'version_script', ''):
175         self.env.append_value('LINKFLAGS', "-Wl,--version-script=%s" %
176             self.version_script)
177         self.version_script = None
178
179
180 ##############################
181 # handle the creation of links for libraries and binaries in the build tree
182
183 @feature('symlink_lib')
184 @after('apply_link')
185 def symlink_lib(self):
186     '''symlink a shared lib'''
187
188     if self.target.endswith('.inst'):
189         return
190
191     blddir = os.path.dirname(self.bld.srcnode.abspath(self.bld.env))
192     libpath = self.link_task.outputs[0].abspath(self.env)
193
194     # calculat the link target and put it in the environment
195     soext=""
196     vnum = getattr(self, 'vnum', None)
197     if vnum is not None:
198         soext = '.' + vnum.split('.')[0]
199
200     link_target = getattr(self, 'link_name', '')
201     if link_target == '':
202         basename = os.path.basename(self.bld.make_libname(self.target, version=soext))
203         if getattr(self, "private_library", False):
204             link_target = '%s/private/%s' % (LIB_PATH, basename)
205         else:
206             link_target = '%s/%s' % (LIB_PATH, basename)
207
208     link_target = os.path.join(blddir, link_target)
209
210     if os.path.lexists(link_target):
211         if os.path.islink(link_target) and os.readlink(link_target) == libpath:
212             return
213         os.unlink(link_target)
214
215     link_container = os.path.dirname(link_target)
216     if not os.path.isdir(link_container):
217         os.makedirs(link_container)
218
219     os.symlink(libpath, link_target)
220
221
222 @feature('symlink_bin')
223 @after('apply_link')
224 def symlink_bin(self):
225     '''symlink a binary into the build directory'''
226
227     if self.target.endswith('.inst'):
228         return
229
230     if not self.link_task.outputs or not self.link_task.outputs[0]:
231         raise Errors.WafError('no outputs found for %s in symlink_bin' % self.name)
232     binpath = self.link_task.outputs[0].abspath(self.env)
233     bldpath = os.path.join(self.bld.env.BUILD_DIRECTORY, self.link_task.outputs[0].name)
234
235     if os.path.lexists(bldpath):
236         if os.path.islink(bldpath) and os.readlink(bldpath) == binpath:
237             return
238         os.unlink(bldpath)
239     os.symlink(binpath, bldpath)