我有一个基于SCons的分层构建系统。我有一个根SConstruct,它调用一个SConscript来构建一个共享库,然后调用另一个SConscript来构建一个依赖于共享库的可执行文件。
所以这是我的问题:我对linux上共享库的理解是,当您想为将使用共享库的可执行文件做最后的ld
链接时,共享库必须作为源文件包含在可执行文件的ld
命令行中引用它(除非它在标准位置,在这种情况下-l
选项可用)。
所以这是我的SCons文件的样子:
=== rootdir / SConstruct
env=DefaultEnvironment()
shared_lib = SConscript('foolib/SConscript')
env.Append( LIBS=[shared_lib] )
executable = SConscript('barexec/SConscript')
=== rootdir / foolib / SConscript
env=DefaultEnvironment()
env.Append(CPPPATH=Glob('inc'))
penv = env.Clone()
penv.Append(CPPPATH=Glob('internal/inc'))
lib = penv.SharedLibrary( 'foo', source=['foo.c', 'morefoo.c']
Return("lib")
=== rootdir / barexec / SConscript
env=DefaultEnvironment()
exe = env.Program( 'bar', source=['main.c', 'bar.c', 'rod.c'] )
Return("exe")
所以这里的障碍是这一行:
env.Append( LIBS=[shared_lib] )
这是将生成的库添加到命令行中的任何其他需要它们的库的好方法,除了因为SCons在SConscripts中进行两次遍历(首先生成它的依赖树,然后进行工作)之外, ,即使所有
rootdir/foolib/libfoo.so
本身,libfoo.so
也会在所有产品的命令行上显示:gcc -g -Wall -Werror -o libfoo.so foo.o morefoo.o libfoo.so
那么如何使用SCons做到最好呢?目前,我已经采取了这种方法:
=== rootdir / SConstruct
env=DefaultEnvironment()
shared_lib = SConscript('foolib/SConscript')
env['shared_lib'] = shared_lib
executable = SConscript('barexec/SConscript')
...
=== rootdir / barexec / SConscript
env=DefaultEnvironment()
exe = env.Program( 'bar', source=['main.c', 'bar.c', 'rod.c'] + env['shared_lib'] )
Return("exe")
还有更多的SCons-y方法吗?
最佳答案
您应允许共享库在构建中找到。
在LIBPATH
文档中查找RPATH
和SCons
变量;这些是设置搜索路径的“Scons-y”方法,以便任何生成的-l
选项都能正确找到库。
上面已经提到了,这是您应该根据SCons的设置看到gcc
所做的事情(如果没有,则可能必须手动进行)。-l
选项始终会找到共享库,前提是您还为编译器提供了库的位置。这有两次需要:在编译时(-L
选项)和运行时(-rpath
生成的链接器选项)。LIBPATH
SCons设置应为编译时搜索路径生成类似于-L/some/directory/path
的内容。RPATH
SCons设置应生成一个链接器选项以嵌入搜索路径;例如-Wl,-rpath -Wl,\$ORIGIN/../lib
将嵌入一个搜索路径,该路径相对于可执行文件进行搜索,以便放置在bin
中的可执行文件在安装的并行lib
目录中进行搜索。