[Scons-users] Question about paths and shared libraries with SCons
Ted Middleton
tmiddleton at teradici.com
Tue Aug 21 04:50:21 EDT 2012
> ------------------------------
>
> Message: 2
> Date: Mon, 23 Jul 2012 13:39:28 -0500
> From: Chris BeHanna <chris at behanna.org>
> Subject: Re: [Scons-users] Question about paths and shared libraries
> with SCons
> To: SCons users mailing list <scons-users at scons.org>
> Message-ID: <C16096DD-8BE9-4500-9FC7-7C60B85CE13A at behanna.org>
> Content-Type: text/plain; charset=us-ascii
>
> On Jul 23, 2012, at 13:06 , Ted Middleton wrote:
>
>> I'm using scons to build an executable and several dlls (.so's) that it depends on. In my root SConsctruct file I have roughly this:
>>
>> dylibs = []
>> dylibs += SConscript( dirs='foodir', exports=['env'] )
>> dylibs += SConscript( dirs='bardir', exports=['env'] )
>> exe = SConscript( dirs='exedir', exports= { 'env' : env, 'dyibs' : dylibs } )
>>
>> and then in exedir/SConscript I have
>>
>> Import('env', 'dylibs')
>> prog = env.Program( 'program', source=['main.cpp', dylibs] )
>> Return('prog')
>>
>> Scons ends up building them like this:
>>
>> gcc -o exedir/program foodir/libfoo.so bardir/libbar.so
>>
>> It seems that whenever scons wants to coerce a scons Node object to a string to build a command line, it likes everything to be relative to that root SConstruct file (which makes sense). If the SConstruct file had been in exedir, I would imagine that the command line that scons would build would look something like this:
>>
>> gcc -o program ../foodir/libfoo.so ../bardir/libbar.so -Wl,rpath=/opt/mycompany/lib
>>
>> How is this a problem? ld will embed whatever .so filename you put on the path that gcc gets invoked with. So in the first example, the actual reference embedded in exedir/program is foodir/libfoo.so and bardir/libbar.so, rather than just libfoo.so and libbar.so. In the second case ../foodir/libfoo.so and ../bardir/libbar.so get embedded in exedir/program.
>>
>> Any ideas on what the most elegant way of dealing with this would be?
>
> env['LIBPATH'] = ['#/foodir', '#/bardir']
>
> myprog = env.Program('program', 'main.c', LIBS=['foo', 'bar'])
>
> In this case, only the basenames of libfoo and libbar will be embedded in program's NEEDED record, and Program() will scan your LIBPATH to find them. The generated link line looks like:
>
> gcc -o program -Lpath/to/foodir -L/path/to/bardir -lfoo -lbar
>
> This is, generally, the "right" way to do it--you don't want to pass pathnames to libraries.
>
> FURTHERMORE, if libfoo and libbar are built with whatever DT_SONAME you specify from the command line (via the -h option at link-time), then THAT name will be embedded in program's NEEDED section, rather than the paths to those libraries. You can embed whatever name you want, though the convention is to use the library's name and a major version number; e.g.,
>
> libfoo.so.1
> libbar.so.2
>
> This will cause the link to fail if someone makes a non-backward-compatible change and revs the major version number of the library to give a warning of that change.
>
> --
> Chris BeHanna
> chris at behanna.org
>
I'm wondering - when I do this, that is I add the dylib name directly to the construction environment's LIBS variable like this:
Import( 'env' )
env.Append( CPPPATH=[Dir('.')] )
env.SharedLibrary( 'foo', 'foo.cpp' )
env.Append( LIBPATH=[Dir('.')] )
env.Append( LIBS=['foo'] )
then when I try to build foo, scons puts together a command line like this one:
g++ -o foodir/libfoo.so foodir/foo.cpp -Lfoodir -lfoo
which of course is never going to work. It's easy enough to understand why scons would do this, but is there no magic in the builder to prevent this? Is the recommended solution to just do something like the following?
Import( 'env' )
env.Append( CPPPATH=[Dir('.')] )
env.Clone().SharedLibrary( 'foo', 'foo.cpp' )
env.Append( LIBPATH=[Dir('.')] )
env.Append( LIBS=['foo'] )
More information about the Scons-users
mailing list