Goal: to have a more flexible LINKCOM, so that we can put options in any order. Right now, we are force to have LINKFLAGS LIBPATH LIBS. In particular, if we want to put linkflags between libs, this is not possible right now wo rewrwiting link actions.
None of below is meant as a prototype: this is just to show the basic concept.
1 import SCons
2 from SCons.Defaults import _stripixes, _concat
3
4 # This dict of func is just a (really) poor-man replacement for scons
5 # interpolation. In real life, of course, the scons scheme should be used.
6 def interpolate_lib(libs, env):
7 return _stripixes(env['LIBLINKPREFIX'], libs,
8 env['LIBLINKSUFFIX'], env['LIBPREFIXES'],
9 env['LIBSUFFIXES'], env)
10
11 def interpolate_libpath(libpaths, env):
12 return _concat(env['LIBDIRPREFIX'], libpaths, env['LIBDIRSUFFIX'], env,
13 env['RDirs'], None, None)
14
15 _INTERPOLATE = {'LIBS' : interpolate_lib,
16 'LIBPATH': interpolate_libpath,
17 'LINKFLAGS': lambda x, y: x}
18
19 class Framework:
20 _keys = {'LIBPATH': None, 'LIBS': None, 'LINKFLAGS': None}
21 def __init__(self):
22 self._data = []
23
24 def append(self, key, value):
25 # XXX: handling non valid construction variables ?
26 assert key in self._keys
27
28 # XXX: of course, this should be handled correctly too
29 assert SCons.Util.is_List(value)
30
31 self._data.append((key, value))
32
33 def subst(self, env):
34 intp = []
35 # XXX: I should see how scons interpolation works
36 for item in self._data:
37 key = item[0]
38 val = item[1]
39 intp.extend(_INTERPOLATE[key](val, env))
40
41 return ' '.join(intp)
42
43 class Bstatic:
44 def __init__(self, lib):
45 f = Framework()
46
47 # XXX: This is tool specific (e.g. gnu ld here)
48 # Maybe this could be handled at the tool level, be defining pre/post
49 # flag ? But does this catpure all way of doing it (MS platforms ?) ?
50 f.append('LINKFLAGS', ['-Wl,-Bstatic'])
51 f.append('LIBS', lib)
52 f.append('LINKFLAGS', ['-Wl,-Bshared'])
53
54 self._f = f
55
56 def subst(self, env):
57 return self._f.subst(env)
58 ~
Which would be used in :
1 from framework import interpolate_lib, interpolate_libpath, Framework, Bstatic
2
3 env = Environment()
4
5 # Simple example with libpath + lib (not useful here, but anyway)
6 f1 = Framework()
7
8 f1.append('LIBPATH', ['/opt/bar'])
9 f1.append('LIBS', ['bar'])
10
11 print f1.subst(env)
12
13 # Simple example to wrap a lib to link statically
14 f2 = Bstatic(["foo"])
15
16 print f2.subst(env)
17
18 # Simple example to add two libraries: this way, of foo in present in /opt/bar
19 # and /opt/foo, foo in /opt/foo will be picked up first
20 f3 = Framework()
21 f3.append('LIBPATH', ['/opt/foo'])
22 f3.append('LIBS', ['foo'])
23 f3.append('LIBPATH', ['/opt/bar'])
24 f3.append('LIBS', ['bar'])
25
26 print f3.subst(env)
27
28 # More complicated example
29 f4 = Framework()
30 f4.append('LIBPATH', ['/opt/foo'])
31 f4.append('LINKFLAGS', ['-Wl,--rpath-link=/opt/foo'])
32 f4.append('LIBS', ['foo'])
33 f4.append('LIBPATH', ['/opt/bar'])
34 f4.append('LINKFLAGS', ['-Wl,--rpath-link=/opt/bar'])
35 f4.append('LIBS', ['bar'])
36 f4.append('LINKFLAGS', ['-xlic_lib=foobar'])
37
38 print f4.subst(env)
Which would print:
-L/opt/bar -lbar -Wl,-Bstatic -lfoo -Wl,-Bshared -L/opt/foo -lfoo -L/opt/bar -lbar -L/opt/foo -Wl,--rpath-link=/opt/foo -lfoo -L/opt/bar -Wl,--rpath-link=/opt/bar -lbar -xlic_lib=foobar
