【问题标题】:SCons link to subdir librarySCons 链接到子目录库
【发布时间】:2014-07-14 10:49:54
【问题描述】:

我有一个 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 和程序之间。

最好的问候 雅各布·西蒙-加德

【问题讨论】:

    标签: c++ linker scons


    【解决方案1】:

    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 构建脚本来使它更好一点,如下所示:

    S构造:

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

    根据您的情况,您可能希望克隆设置库和库路径的环境,以免污染项目其余部分的环境。

    【讨论】:

      【解决方案2】:

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

      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。

      但是,我发现这不适用于非标准库名称(non-soname),这是我要解决的问题。

      【讨论】:

        【解决方案3】:

        @brady 说得对。

        有一种稍微不那么冗长的方法来执行此操作,这也消除了克隆您的 Environment() 的任何需要(这也是我建议这样做的方式,除非您使用相同的 LIBPATH 链接一大堆程序和/或 LIBS )

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

        【讨论】:

          猜你喜欢
          • 2015-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-19
          相关资源
          最近更新 更多