Reputation: 725
I have a SCons project with several subdir targets like this:
project-root
- SConstruct
- Sconscript
+ supportlib
- SConscript (returning library target)
+ src
- ...
+ Program
- SConsctipt (importing library target)
+ src
- ...
Note: supportlib is a shared library.
In the Program subdir I link to the supportlib target like this:
Import( [supportlib] ) # returned from supportlib/Sconscript
env.Append( LIBS=[supportlib] )
This works, the supportlib and program compiles and links. But the way the supportlib is linked into the program is by direct reference to the shared object instead of -lsupportlib.
pseudo linker command examples:
SCons does like this:
g++ -o Program/program src/sourcefile1.o src/sourcefile2.o ../supportlib/libsupportlib.so
I want this:
g++ -o Program/program src/sourcefile1.o src/sourcefile2.o -L ../supportlib -lsupportlib
Why? Because with SCons way of linking I get the following shared library dependency:
$ ldd program/program
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f867ca03000)
supportlib/libsupportlib.so
I want the dependency to be "path-less" like this:
$ ldd program/program
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f867ca03000)
libsupportlib.so
Can I achieve this goal a pretty way with SCons without breaking build dependencies? I know that I can do it manually using LINKFLAGS in my environment, but this is not a pretty way to do it nor cross-platform and when not passing the full target to LIBS i am guessing that SCons will loose knowledge about the build-dependency between supportlib and program.
Best regards Jakob Simon-Gaarde
Upvotes: 2
Views: 1176
Reputation: 3509
@brady Has it right.
There's a slightly less verbose way to do this, which also removes any need to clone your Environment() (This is also the way I'd recommend doing this, unless you were linking a whole bunch of programs with the same LIBPATH and/or LIBS )
env.Program(source='main_src_files', target='main',LIBS='supportlib',LIBPATH='#supportlib') # will link with supportlib
Upvotes: 0
Reputation: 194
In my experience, the following would work for your example:
env.Append(LIBPATH='supportlib') # assuming this is a subdirectory from top
env.Append(LIBS=[os.path.basename(str(supportlib))]) # to only pick lib soname. (You may need to do [0] there too)
This will result in -Lsupportlib -lsupportlib
telling linker to look for libsupportlib.so in "supportlib" relative path (in addition to any standard search paths). That should result in only the library soname embedded.
I found, however, that this does not work with non-standard library names (non-soname), which is the problem I am trying to resolve.
Upvotes: 0
Reputation: 10357
The target being returned by the supportlib/SConscript has the complete project-relative path to the library. that's the way targets work in SCons.
To achieve what you're asking, you could do the following in Program/SConscript, and SCons will still maintain the dependencies on the library:
env.Append(LIBS='supportlib')
env.Append(LIBPATH='#supportlib')
env.Program(source='main_src_files', target='main') # will link with supportlib
Notice that the '#' character in SCons means relative to the project root directory (which is where the SConstruct build script is located)
You could make it a little nicer, by setting the library name on the env created in the SConstruct and pass that env to the subdir SConscript build scripts, as follows:
SConstruct:
env = Environment()
...
SConscript('supportlib/SConscript', exports=['env'])
SConscript('Program/SConscript', exports=['env'])
supportlib/SConscript:
Import('env')
...
env['supportlib_name'] = 'supportlib'
env.SharedLibrary(source='source_files', target=env['supportlib_name'])
Program/SConscript:
Import('env')
...
clonedEnv = env.clone()
clonedEnv.Append(LIBS=env['supportlib_name'])
env.Append(LIBPATH='#supportlib')
clonedEnv.Program(source='main_src_files', target='main')
Depending on your situation, you may want to clone the env where you set the libs and library paths so you dont pollute the env for the rest of the project.
Upvotes: 2