我有一个基于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文档中查找RPATHSCons变量;这些是设置搜索路径的“Scons-y”方法,以便任何生成的-l选项都能正确找到库。

上面已经提到了,这是您应该根据SCons的设置看到gcc所做的事情(如果没有,则可能必须手动进行)。
-l选项始终会找到共享库,前提是您还为编译器提供了库的位置。这有两次需要:在编译时(-L选项)和运行时(-rpath生成的链接器选项)。
LIBPATH SCons设置应为编译时搜索路径生成类似于-L/some/directory/path的内容。
RPATH SCons设置应生成一个链接器选项以嵌入搜索路径;例如-Wl,-rpath -Wl,\$ORIGIN/../lib将嵌入一个搜索路径,该路径相对于可执行文件进行搜索,以便放置在bin中的可执行文件在安装的并行lib目录中进行搜索。

08-16 20:51