~ubuntu-branches/ubuntu/utopic/tdb/utopic-proposed

« back to all changes in this revision

Viewing changes to buildtools/wafadmin/Tools/libtool.py

  • Committer: Package Import Robot
  • Author(s): Andrew Bartlett
  • Date: 2013-02-12 20:43:55 UTC
  • mfrom: (1.4.6)
  • mto: (1.4.7) (3.3.7 experimental)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: package-import@ubuntu.com-20130212204355-6q6jvxshtoie7ex5
ImportĀ upstreamĀ versionĀ 1.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# encoding: utf-8
 
3
# Matthias Jahn, 2008, jahn matthias ath freenet punto de
 
4
# Thomas Nagy, 2008 (ita)
 
5
 
 
6
import sys, re, os, optparse
 
7
 
 
8
import TaskGen, Task, Utils, preproc
 
9
from Logs import error, debug, warn
 
10
from TaskGen import taskgen, after, before, feature
 
11
 
 
12
REVISION="0.1.3"
 
13
 
 
14
"""
 
15
if you want to use the code here, you must use something like this:
 
16
obj = obj.create(...)
 
17
obj.features.append("libtool")
 
18
obj.vnum = "1.2.3" # optional, but versioned libraries are common
 
19
"""
 
20
 
 
21
# fake libtool files
 
22
fakelibtool_vardeps = ['CXX', 'PREFIX']
 
23
def fakelibtool_build(task):
 
24
        # Writes a .la file, used by libtool
 
25
        env = task.env
 
26
        dest  = open(task.outputs[0].abspath(env), 'w')
 
27
        sname = task.inputs[0].name
 
28
        fu = dest.write
 
29
        fu("# Generated by ltmain.sh - GNU libtool 1.5.18 - (pwn3d by BKsys II code name WAF)\n")
 
30
        if env['vnum']:
 
31
                nums = env['vnum'].split('.')
 
32
                libname = task.inputs[0].name
 
33
                name3 = libname+'.'+env['vnum']
 
34
                name2 = libname+'.'+nums[0]
 
35
                name1 = libname
 
36
                fu("dlname='%s'\n" % name2)
 
37
                strn = " ".join([name3, name2, name1])
 
38
                fu("library_names='%s'\n" % (strn) )
 
39
        else:
 
40
                fu("dlname='%s'\n" % sname)
 
41
                fu("library_names='%s %s %s'\n" % (sname, sname, sname) )
 
42
        fu("old_library=''\n")
 
43
        vars = ' '.join(env['libtoolvars']+env['LINKFLAGS'])
 
44
        fu("dependency_libs='%s'\n" % vars)
 
45
        fu("current=0\n")
 
46
        fu("age=0\nrevision=0\ninstalled=yes\nshouldnotlink=no\n")
 
47
        fu("dlopen=''\ndlpreopen=''\n")
 
48
        fu("libdir='%s/lib'\n" % env['PREFIX'])
 
49
        dest.close()
 
50
        return 0
 
51
 
 
52
def read_la_file(path):
 
53
        sp = re.compile(r'^([^=]+)=\'(.*)\'$')
 
54
        dc={}
 
55
        file = open(path, "r")
 
56
        for line in file.readlines():
 
57
                try:
 
58
                        #print sp.split(line.strip())
 
59
                        _, left, right, _ = sp.split(line.strip())
 
60
                        dc[left]=right
 
61
                except ValueError:
 
62
                        pass
 
63
        file.close()
 
64
        return dc
 
65
 
 
66
@feature("libtool")
 
67
@after('apply_link')
 
68
def apply_link_libtool(self):
 
69
        if self.type != 'program':
 
70
                linktask = self.link_task
 
71
                self.latask = self.create_task('fakelibtool', linktask.outputs, linktask.outputs[0].change_ext('.la'))
 
72
 
 
73
        if self.bld.is_install:
 
74
                self.bld.install_files('${PREFIX}/lib', linktask.outputs[0], self.env)
 
75
 
 
76
@feature("libtool")
 
77
@before('apply_core')
 
78
def apply_libtool(self):
 
79
        self.env['vnum']=self.vnum
 
80
 
 
81
        paths=[]
 
82
        libs=[]
 
83
        libtool_files=[]
 
84
        libtool_vars=[]
 
85
 
 
86
        for l in self.env['LINKFLAGS']:
 
87
                if l[:2]=='-L':
 
88
                        paths.append(l[2:])
 
89
                elif l[:2]=='-l':
 
90
                        libs.append(l[2:])
 
91
 
 
92
        for l in libs:
 
93
                for p in paths:
 
94
                        dict = read_la_file(p+'/lib'+l+'.la')
 
95
                        linkflags2 = dict.get('dependency_libs', '')
 
96
                        for v in linkflags2.split():
 
97
                                if v.endswith('.la'):
 
98
                                        libtool_files.append(v)
 
99
                                        libtool_vars.append(v)
 
100
                                        continue
 
101
                                self.env.append_unique('LINKFLAGS', v)
 
102
                                break
 
103
 
 
104
        self.env['libtoolvars']=libtool_vars
 
105
 
 
106
        while libtool_files:
 
107
                file = libtool_files.pop()
 
108
                dict = read_la_file(file)
 
109
                for v in dict['dependency_libs'].split():
 
110
                        if v[-3:] == '.la':
 
111
                                libtool_files.append(v)
 
112
                                continue
 
113
                        self.env.append_unique('LINKFLAGS', v)
 
114
 
 
115
Task.task_type_from_func('fakelibtool', vars=fakelibtool_vardeps, func=fakelibtool_build, color='BLUE', after="cc_link cxx_link static_link")
 
116
 
 
117
class libtool_la_file:
 
118
        def __init__ (self, la_filename):
 
119
                self.__la_filename = la_filename
 
120
                #remove path and .la suffix
 
121
                self.linkname = str(os.path.split(la_filename)[-1])[:-3]
 
122
                if self.linkname.startswith("lib"):
 
123
                        self.linkname = self.linkname[3:]
 
124
                # The name that we can dlopen(3).
 
125
                self.dlname = None
 
126
                # Names of this library
 
127
                self.library_names = None
 
128
                # The name of the static archive.
 
129
                self.old_library = None
 
130
                # Libraries that this one depends upon.
 
131
                self.dependency_libs = None
 
132
                # Version information for libIlmImf.
 
133
                self.current = None
 
134
                self.age = None
 
135
                self.revision = None
 
136
                # Is this an already installed library?
 
137
                self.installed = None
 
138
                # Should we warn about portability when linking against -modules?
 
139
                self.shouldnotlink = None
 
140
                # Files to dlopen/dlpreopen
 
141
                self.dlopen = None
 
142
                self.dlpreopen = None
 
143
                # Directory that this library needs to be installed in:
 
144
                self.libdir = '/usr/lib'
 
145
                if not self.__parse():
 
146
                        raise ValueError("file %s not found!!" %(la_filename))
 
147
 
 
148
        def __parse(self):
 
149
                "Retrieve the variables from a file"
 
150
                if not os.path.isfile(self.__la_filename): return 0
 
151
                la_file=open(self.__la_filename, 'r')
 
152
                for line in la_file:
 
153
                        ln = line.strip()
 
154
                        if not ln: continue
 
155
                        if ln[0]=='#': continue
 
156
                        (key, value) = str(ln).split('=', 1)
 
157
                        key = key.strip()
 
158
                        value = value.strip()
 
159
                        if value == "no": value = False
 
160
                        elif value == "yes": value = True
 
161
                        else:
 
162
                                try: value = int(value)
 
163
                                except ValueError: value = value.strip("'")
 
164
                        setattr(self, key, value)
 
165
                la_file.close()
 
166
                return 1
 
167
 
 
168
        def get_libs(self):
 
169
                """return linkflags for this lib"""
 
170
                libs = []
 
171
                if self.dependency_libs:
 
172
                        libs = str(self.dependency_libs).strip().split()
 
173
                if libs == None:
 
174
                        libs = []
 
175
                # add la lib and libdir
 
176
                libs.insert(0, "-l%s" % self.linkname.strip())
 
177
                libs.insert(0, "-L%s" % self.libdir.strip())
 
178
                return libs
 
179
 
 
180
        def __str__(self):
 
181
                return '''\
 
182
dlname = "%(dlname)s"
 
183
library_names = "%(library_names)s"
 
184
old_library = "%(old_library)s"
 
185
dependency_libs = "%(dependency_libs)s"
 
186
version = %(current)s.%(age)s.%(revision)s
 
187
installed = "%(installed)s"
 
188
shouldnotlink = "%(shouldnotlink)s"
 
189
dlopen = "%(dlopen)s"
 
190
dlpreopen = "%(dlpreopen)s"
 
191
libdir = "%(libdir)s"''' % self.__dict__
 
192
 
 
193
class libtool_config:
 
194
        def __init__ (self, la_filename):
 
195
                self.__libtool_la_file = libtool_la_file(la_filename)
 
196
                tmp = self.__libtool_la_file
 
197
                self.__version = [int(tmp.current), int(tmp.age), int(tmp.revision)]
 
198
                self.__sub_la_files = []
 
199
                self.__sub_la_files.append(la_filename)
 
200
                self.__libs = None
 
201
 
 
202
        def __cmp__(self, other):
 
203
                """make it compareable with X.Y.Z versions (Y and Z are optional)"""
 
204
                if not other:
 
205
                        return 1
 
206
                othervers = [int(s) for s in str(other).split(".")]
 
207
                selfvers = self.__version
 
208
                return cmp(selfvers, othervers)
 
209
 
 
210
        def __str__(self):
 
211
                return "\n".join([
 
212
                        str(self.__libtool_la_file),
 
213
                        ' '.join(self.__libtool_la_file.get_libs()),
 
214
                        '* New getlibs:',
 
215
                        ' '.join(self.get_libs())
 
216
                ])
 
217
 
 
218
        def __get_la_libs(self, la_filename):
 
219
                return libtool_la_file(la_filename).get_libs()
 
220
 
 
221
        def get_libs(self):
 
222
                """return the complete uniqe linkflags that do not
 
223
                contain .la files anymore"""
 
224
                libs_list = list(self.__libtool_la_file.get_libs())
 
225
                libs_map = {}
 
226
                while len(libs_list) > 0:
 
227
                        entry = libs_list.pop(0)
 
228
                        if entry:
 
229
                                if str(entry).endswith(".la"):
 
230
                                        ## prevents duplicate .la checks
 
231
                                        if entry not in self.__sub_la_files:
 
232
                                                self.__sub_la_files.append(entry)
 
233
                                                libs_list.extend(self.__get_la_libs(entry))
 
234
                                else:
 
235
                                        libs_map[entry]=1
 
236
                self.__libs = libs_map.keys()
 
237
                return self.__libs
 
238
 
 
239
        def get_libs_only_L(self):
 
240
                if not self.__libs: self.get_libs()
 
241
                libs = self.__libs
 
242
                libs = [s for s in libs if str(s).startswith('-L')]
 
243
                return libs
 
244
 
 
245
        def get_libs_only_l(self):
 
246
                if not self.__libs: self.get_libs()
 
247
                libs = self.__libs
 
248
                libs = [s for s in libs if str(s).startswith('-l')]
 
249
                return libs
 
250
 
 
251
        def get_libs_only_other(self):
 
252
                if not self.__libs: self.get_libs()
 
253
                libs = self.__libs
 
254
                libs = [s for s in libs if not(str(s).startswith('-L')or str(s).startswith('-l'))]
 
255
                return libs
 
256
 
 
257
def useCmdLine():
 
258
        """parse cmdline args and control build"""
 
259
        usage = '''Usage: %prog [options] PathToFile.la
 
260
example: %prog --atleast-version=2.0.0 /usr/lib/libIlmImf.la
 
261
nor: %prog --libs /usr/lib/libamarok.la'''
 
262
        parser = optparse.OptionParser(usage)
 
263
        a = parser.add_option
 
264
        a("--version", dest = "versionNumber",
 
265
                action = "store_true", default = False,
 
266
                help = "output version of libtool-config"
 
267
                )
 
268
        a("--debug", dest = "debug",
 
269
                action = "store_true", default = False,
 
270
                help = "enable debug"
 
271
                )
 
272
        a("--libs", dest = "libs",
 
273
                action = "store_true", default = False,
 
274
                help = "output all linker flags"
 
275
                )
 
276
        a("--libs-only-l", dest = "libs_only_l",
 
277
                action = "store_true", default = False,
 
278
                help = "output -l flags"
 
279
                )
 
280
        a("--libs-only-L", dest = "libs_only_L",
 
281
                action = "store_true", default = False,
 
282
                help = "output -L flags"
 
283
                )
 
284
        a("--libs-only-other", dest = "libs_only_other",
 
285
                action = "store_true", default = False,
 
286
                help = "output other libs (e.g. -pthread)"
 
287
                )
 
288
        a("--atleast-version", dest = "atleast_version",
 
289
                default=None,
 
290
                help = "return 0 if the module is at least version ATLEAST_VERSION"
 
291
                )
 
292
        a("--exact-version", dest = "exact_version",
 
293
                default=None,
 
294
                help = "return 0 if the module is exactly version EXACT_VERSION"
 
295
                )
 
296
        a("--max-version", dest = "max_version",
 
297
                default=None,
 
298
                help = "return 0 if the module is at no newer than version MAX_VERSION"
 
299
                )
 
300
 
 
301
        (options, args) = parser.parse_args()
 
302
        if len(args) != 1 and not options.versionNumber:
 
303
                parser.error("incorrect number of arguments")
 
304
        if options.versionNumber:
 
305
                print("libtool-config version %s" % REVISION)
 
306
                return 0
 
307
        ltf = libtool_config(args[0])
 
308
        if options.debug:
 
309
                print(ltf)
 
310
        if options.atleast_version:
 
311
                if ltf >= options.atleast_version: return 0
 
312
                sys.exit(1)
 
313
        if options.exact_version:
 
314
                if ltf == options.exact_version: return 0
 
315
                sys.exit(1)
 
316
        if options.max_version:
 
317
                if ltf <= options.max_version: return 0
 
318
                sys.exit(1)
 
319
 
 
320
        def p(x):
 
321
                print(" ".join(x))
 
322
        if options.libs: p(ltf.get_libs())
 
323
        elif options.libs_only_l: p(ltf.get_libs_only_l())
 
324
        elif options.libs_only_L: p(ltf.get_libs_only_L())
 
325
        elif options.libs_only_other: p(ltf.get_libs_only_other())
 
326
        return 0
 
327
 
 
328
if __name__ == '__main__':
 
329
        useCmdLine()
 
330