我有一个只在静态范围内与应用程序交互的库。这需要我将库与--whole-archive
选项链接起来,以避免链接器“优化”库(这样做是因为链接器实际上从未看到我的库被使用)。
问题是我还没有找到为scons中的特定库添加此链接器选项的方法。
env.Append(LIBS=['mylib']) #I don't have the linker option
env.Append(LINKFLAGS=['-Wl,--whole-archive','-lmylib']) #I don't add myself to the scons dependency tree, I also get added to the link line before the LIBPATH variable.
如何在scons中优雅地支持链接器标志?
答案 0 :(得分:2)
如何使用scons将静态库链接到带有-sole-archive链接标志的共享库,同时保持依赖关系。
我正在重述你的问题只是为了确保我们都清楚地了解你想要完成的事情。如果我没有正确捕捉你的问题的意图,请发表评论。
您无法在LIBS
中包含该库,因为您希望使用--whole-archive
标记来包围库。如果您将此条目放在LINKFLAGS
中,它可以正常工作,但您将失去依赖关系跟踪。
当您将库从LIBS
中的条目移动到LINKFLAGS
中的条目时,您将失去隐式依赖项,但这很好,只需设置显式与Depends
的依赖关系。
.
├── A.cpp
├── A.h
├── B.cpp
├── B.h
├── main.cpp
└── SConstruct
A.cpp
#include "A.h"
int foo2(void) {
return 2;
}
A.H
#ifndef __A__
#define __A__
int foo2(void);
#endif
B.cpp
#include "B.h"
#include "A.h"
int bar(void) {
return 2 * foo2();
}
B.h
#ifndef __B__
#define __B__
int bar(void);
#endif
的main.cpp
#include <iostream>
#include "B.h"
using namespace std;
int main() {
cout << "Sum of foo and bar = " << bar() << endl;
return 0;
}
SConstruct
import os
# Top level Build Environment
env = Environment()
# Library A
envA = env.Clone()
libA = envA.StaticLibrary('A.cpp')
# Library B
envB = env.Clone()
envB.Append(LINKFLAGS=['-Wl,--whole-archive,./libA.a,--no-whole-archive'])
libB = envB.SharedLibrary('B.cpp')
Depends(libB, libA)
# Test Program
envE = env.Clone()
envE.Append(LIBS=['B'],
LIBPATH=['.'],
RPATH=[os.path.abspath(os.curdir)])
envE.Program('example', 'main.cpp')
将所有文件复制到同一目录,并在该目录中键入scons
。如果你构建并要求依赖树,这是你应该在linux上看到的输出。 (我正在使用Fedora 21)
>> scons --version
SCons by Steven Knight et al.:
script: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001 - 2014 The SCons Foundation
>> scons --tree=prune
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o A.o -c A.cpp
g++ -o B.os -c -fPIC B.cpp
g++ -o main.o -c main.cpp
ar rc libA.a A.o
ranlib libA.a
g++ -o libB.so -Wl,--whole-archive,./libA.a,--no-whole-archive -shared B.os
g++ -o example -Wl,-rpath=/full/path/to/build/directory main.o -L. -lB
+-.
+-A.cpp
+-A.h
+-A.o
| +-A.cpp
| +-A.h
| +-/bin/g++
+-B.cpp
+-B.h
+-B.os
| +-B.cpp
| +-A.h
| +-B.h
| +-/bin/g++
+-SConstruct
+-example
| +-main.o
| | +-main.cpp
| | +-B.h
| | +-/bin/g++
| +-/bin/g++
| +-libB.so
| +-[B.os]
| +-libA.a
| +-[A.o]
| +-/bin/ar
| +-/bin/ranlib
+-[libA.a]
+-[libB.so]
+-main.cpp
+-[main.o]
scons: done building targets.
>> ./example
Sum of foo and bar = 4
--whole-archive
链接标志构建动态库B. 您可以从上面的依赖关系图中看到,库A被正确列为库B的依赖关系。
享受!
答案 1 :(得分:1)
Scons 仍然不支持-Wl,--whole-archive
等链接标记。使用Kenneth E. Bellock提供的解决方案多年来一直运作良好。缺点是这容易出错。您必须小心管理手动依赖列表。
还有一种替代解决方法。将以下内容添加到SConstruct文件中:
whole_archive = env.Command('-Wl,--whole-archive', [], '')
no_whole_archive = env.Command('-Wl,--no-whole-archive', [], '')
现在,您可以使用整个归档/非整个归档以任意组合包装必要的库。例如:
so_libs = env.SharedLibrary('myso', whole_archive+['libfoo1.a']+no_whole_archive+['libbar.a']+whole_archive+['libfoo2.a']+no_whole_archive)
答案 2 :(得分:0)
您可以将LIBS和LINKFLAGS添加到链接器语句中。
env.SharedLibrary('target',sources,LIBS=['mylib'],LINKFLAGS=env['LINKFLAGS']+['-Wl,--whole-archive','-lmylib'])
例如。