SCons链接到subdir库

时间:2014-07-14 10:49:54

标签: c++ linker scons

我有一个带有几个子目标的SCons项目,如下所示:

project-root
 - SConstruct
 - Sconscript
 + supportlib
    - SConscript (returning library target)
    + src
       - ...
 + Program
    - SConsctipt (importing library target)
    + src
       - ...

注意: supportlib是一个共享库。

在Program子目录中,我链接到supportlib目标,如下所示:

Import( [supportlib] ) # returned from supportlib/Sconscript
env.Append( LIBS=[supportlib] )

这有效,supportlib和程序编译和链接。但是,supportlib链接到程序的方式是直接引用共享对象而不是-lsupportlib。

伪链接器命令示例:

SCons喜欢这样:

g++ -o Program/program src/sourcefile1.o src/sourcefile2.o ../supportlib/libsupportlib.so

我想要这个:

g++ -o Program/program src/sourcefile1.o src/sourcefile2.o -L ../supportlib -lsupportlib

为什么呢?因为使用SCons链接方式,我得到以下共享库依赖:

$ ldd program/program
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f867ca03000)
supportlib/libsupportlib.so

我希望依赖关系像这样“无路径”:

$ ldd program/program
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f867ca03000)
libsupportlib.so

我能否在不破坏构建依赖关系的情况下以SCons的方式实现这一目标?我知道我可以在我的环境中使用LINKFLAGS手动完成它,但这不是一个很好的方法,也不是跨平台,当没有将完整的目标传递给LIBS时,我猜测SCons将失去有关构建依赖性的知识在supportlib和program之间。

祝你好运 雅各布西蒙 - 加尔德

3 个答案:

答案 0 :(得分:2)

supportlib / SConscript返回的目标具有到库的完整项目相对路径。这是SCons目标的工作方式。

要实现您的要求,您可以在Program / SConscript中执行以下操作,SCons仍将保持对库的依赖:

env.Append(LIBS='supportlib')
env.Append(LIBPATH='#supportlib')
env.Program(source='main_src_files', target='main') # will link with supportlib

请注意'#' SCons中的字符表示相对于项目根目录(SConstruct构建脚本所在的位置)

通过在SConstruct中创建的env上设置库名称并将该env传递给子目录SConscript构建脚本,可以使它更好一些,如下所示:

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'])

程序/ SConscript:

Import('env')
...
clonedEnv = env.clone()
clonedEnv.Append(LIBS=env['supportlib_name'])
env.Append(LIBPATH='#supportlib')
clonedEnv.Program(source='main_src_files', target='main')

根据您的具体情况,您可能希望克隆设置libs和库路径的env,这样就不会污染项目其余部分的env。

答案 1 :(得分:0)

根据我的经验,以下内容适用于您的示例:

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)

这将导致-Lsupportlib -lsupportlib告诉链接器在" supportlib"中查找libsupportlib.so。相对路径(除了任何标准搜索路径)。这应该导致只嵌入库soname。

然而,我发现这不适用于非标准库名称(非soname),这是我试图解决的问题。

答案 2 :(得分:0)

@brady没错。

有一种稍微简单的方法可以做到这一点,这也消除了克隆你的环境的需要()(这也是我建议这样做的方式,除非你用相同的LIBPATH链接一大堆程序和/或LIBS)

env.Program(source='main_src_files', target='main',LIBS='supportlib',LIBPATH='#supportlib') # will link with supportlib