C++ 将静态库链接到其他静态库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2157629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Linking static libraries to other static libraries
提问by Jason Sundram
I have a small piece of code that depends on many static libraries (a_1-a_n). I'd like to package up that code in a static library and make it available to other people.
我有一小段代码依赖于许多静态库(a_1-a_n)。我想将该代码打包到一个静态库中并使其可供其他人使用。
My static library, lets call it X, compiles fine.
我的静态库,我们称之为 X,编译得很好。
I've created a simple sample program that uses a function from X, but when I try to link it to X, I get many errors about missing symbols from libraries a_1 - a_n.
我创建了一个简单的示例程序,它使用 X 中的一个函数,但是当我尝试将它链接到 X 时,我收到了很多关于库 a_1 - a_n 中缺少符号的错误。
Is there a way that I can create a new static library, Y that contains X and all the functionality needed by X (selected bits from a_1 - a_n), so that I can distribute just Y for people to link their programs to?
有没有一种方法可以创建一个新的静态库,Y 包含 X 和 X 所需的所有功能(从 a_1 - a_n 中选择的位),以便我可以只分发 Y 供人们将他们的程序链接到?
UPDATE:
更新:
I've looked at just dumping everything with arand making one mega-lib, however, that ends up including a lot of symbols that are not needed (all the .o files are about 700 MB, however, a statically linked executable is 7 MB). Is there a nice way to include only what is actually needed?
我看过只是用ar转储所有内容并制作一个大型库,但是,最终包含了很多不需要的符号(所有 .o 文件大约 700 MB,但是,静态链接的可执行文件是 7 MB)。有没有一种很好的方法来只包含实际需要的内容?
This looks closely related to How to combine several C/C++ libraries into one?.
这看起来与如何将多个 C/C++ 库合二为一?.
采纳答案by Jason Sundram
Static libraries do not link with other static libraries. The only way to do this is to use your librarian/archiver tool (for example aron Linux) to create a single new static library by concatenating the multiple libraries.
静态库不与其他静态库链接。唯一的方法是使用您的图书管理员/归档工具(例如Linux 上的ar)通过连接多个库来创建一个新的静态库。
Edit:In response to your update, the only way I know to select only the symbols that are required is to manually create the library from the subset of the .o files that contain them. This is difficult, time consuming and error prone. I'm not aware of any tools to help do this (not to say they don't exist), but it would make quite an interesting project to produce one.
编辑:为了响应您的更新,我知道仅选择所需符号的唯一方法是从包含它们的 .o 文件的子集中手动创建库。这是困难的、耗时的并且容易出错。我不知道有任何工具可以帮助做到这一点(并不是说它们不存在),但是制作一个会是一个非常有趣的项目。
回答by John Knoeller
If you are using Visual Studio then yes, you can do this.
如果您使用的是 Visual Studio,那么是的,您可以这样做。
The library builder tool that comes with Visual Studio allows you to join libraries together on the command line. I don't know of any way to do this in the visual editor though.
Visual Studio 附带的库生成器工具允许您在命令行上将库连接在一起。不过,我不知道有什么方法可以在可视化编辑器中执行此操作。
lib.exe /OUT:compositelib.lib lib1.lib lib2.lib
回答by Star Brilliant
On Linux or MingW, with GNU toolchain:
在 Linux 或 MingW 上,使用 GNU 工具链:
ar -M <<EOM
CREATE libab.a
ADDLIB liba.a
ADDLIB libb.a
SAVE
END
EOM
ranlib libab.a
Of if you do not delete liba.a
and libb.a
, you can make a "thin archive":
如果你不删除liba.a
and libb.a
,你可以制作一个“瘦存档”:
ar crsT libab.a liba.a libb.a
On Windows, with MSVC toolchain:
在 Windows 上,使用 MSVC 工具链:
lib.exe /OUT:libab.lib liba.lib libb.lib
回答by Nikolai Fetissov
A static library is just an archive of .o
object files. Extract them with ar
(assuming Unix) and pack them back into one big library.
静态库只是.o
目标文件的存档。使用ar
(假设为 Unix)提取它们并将它们打包回一个大库。
回答by evpo
Alternatively to Link Library Dependencies
in project properties there is another way to link libraries in Visual Studio.
另外,以Link Library Dependencies
在项目属性还有另一种方式在Visual Studio链接库。
- Open the project of the library (X) that you want to be combined with other libraries.
- Add the other libraries you want combined with X (Right Click,
Add Existing Item...
). - Go to their properties and make sure
Item Type
isLibrary
- 打开要与其他库合并的库 (X) 的项目。
- 添加您想要与 X 组合的其他库(右键单击,
Add Existing Item...
)。 - 去他们的属性并确保
Item Type
是Library
This will include the other libraries in X as if you ran
这将包括 X 中的其他库,就像您运行一样
lib /out:X.lib X.lib other1.lib other2.lib
回答by Elmar Zander
Note before you read the rest: The shell script shown here is certainly not safe to use and well tested. Use at your own risk!
在阅读其余部分之前请注意:此处显示的 shell 脚本肯定无法安全使用且经过良好测试。使用风险自负!
I wrote a bash script to accomplish that task. Suppose your library is lib1 and the one you need to include some symbols from is lib2. The script now runs in a loop, where it first checks which undefined symbols from lib1 can be found in lib2. It then extracts the corresponding object files from lib2 with ar
, renames them a bit, and puts them into lib1. Now there may be more missing symbols, because the stuff you included from lib2 needs other stuff from lib2, which we haven't included yet, so the loop needs to run again. If after some passes of the loop there are no changes anymore, i.e. no object files from lib2 added to lib1, the loop can stop.
我编写了一个 bash 脚本来完成该任务。假设您的库是 lib1,而您需要包含一些符号的库是 lib2。该脚本现在在循环中运行,它首先检查可以在 lib2 中找到来自 lib1 的哪些未定义符号。然后它从 lib2 中提取相应的目标文件,稍微ar
重命名它们,然后将它们放入 lib1。现在可能缺少更多符号,因为您从 lib2 中包含的内容需要来自 lib2 的其他内容,而我们尚未包含这些内容,因此需要再次运行循环。如果在循环的某些遍之后不再有任何更改,即没有来自 lib2 的目标文件添加到 lib1,则循环可以停止。
Note, that the included symbols are still reported as undefined by nm
, so I'm keeping track of the object files, that were added to lib1, themselves, in order to determine whether the loop can be stopped.
请注意,包含的符号仍被报告为 undefined by nm
,因此我正在跟踪添加到 lib1 的目标文件本身,以确定循环是否可以停止。
#! /bin/bash
lib1=""
lib2=""
if [ ! -e $lib1.backup ]; then
echo backing up
cp $lib1 $lib1.backup
fi
remove_later=""
new_tmp_file() {
file=$(mktemp)
remove_later="$remove_later $file"
eval =$file
}
remove_tmp_files() {
rm $remove_later
}
trap remove_tmp_files EXIT
find_symbols() {
nm | cut -c20- | sort | uniq
}
new_tmp_file lib2symbols
new_tmp_file currsymbols
nm $lib2 -s --defined-only > $lib2symbols
prefix="xyz_import_"
pass=0
while true; do
((pass++))
echo "Starting pass #$pass"
curr=$lib1
find_symbols $curr "--undefined-only" > $currsymbols
changed=0
for sym in $(cat $currsymbols); do
for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
echo " Found $sym in $obj."
if [ -e "$prefix$obj" ]; then continue; fi
echo " -> Adding $obj to $lib1"
ar x $lib2 $obj
mv $obj "$prefix$obj"
ar -r -s $lib1 "$prefix$obj"
remove_later="$remove_later $prefix$obj"
((changed=changed+1))
done
done
echo "Found $changed changes in pass #$pass"
if [[ $changed == 0 ]]; then break; fi
done
I named that script libcomp
, so you can call it then e.g. with
我命名了那个脚本libcomp
,所以你可以调用它,例如
./libcomp libmylib.a libwhatever.a
where libwhatever is where you want to include symbols from. However, I think it's safest to copy everything into a separate directory first. I wouldn't trust my script so much (however, it worked for me; I could include libgsl.a into my numerics library with that and leave out that -lgsl compiler switch).
libwhatever 是您想要包含符号的位置。但是,我认为首先将所有内容复制到单独的目录中是最安全的。我不太相信我的脚本(但是,它对我有用;我可以将 libgsl.a 包含在我的数字库中,而忽略 -lgsl 编译器开关)。