将静态库链接到其他静态库

我有一小段代码依赖于许多静态库(a_1-a_n)。 我想将这些代码打包在一个静态库中,并将其提供给其他人。

我的静态库,让它叫X,编译好。

我创build了一个使用X函数的简单示例程序,但是当我尝试将它链接到X时,出现了许多有关从库a_1 – a_n中丢失符号的错误。

有没有一种方法可以创build一个新的静态库,Y包含X和X所需的所有function(从a_1 – a_n中select的位),这样我就可以分发Y,让人们将它们的程序链接到?


更新:

我已经看过只是倾销所有与AR和一个超级图书馆,但是,最终包括了很多不需要的符号(所有.o文件大约700 MB,但是,一个静态链接的可执行文件是7 MB)。 有没有一种很好的方法来只包含实际需要的东西?


这看起来与如何将几个C / C ++库合并为一个密切相关? 。

静态库不与其他静态库链接。 要做到这一点的唯一方法是使用图书pipe理员/存档工具(例如Linux上的ar )通过连接多个库来创build一个新的静态库。

编辑:为了响应您的更新,我知道只select所需符号的唯一方法是从包含它们的.o文件的子集手动创build库。 这很困难,耗时且容易出错。 我没有意识到有任何工具可以帮助做到这一点(并不是说它们不存在),但是生成一个非常有趣的项目是非常有趣的。

如果你使用的是Visual Studio,那么是的,你可以做到这一点。

Visual Studio附带的库构build器工具允许您在命令行上将库连接在一起。 我不知道有什么办法可以在视觉编辑器中做到这一点。

 lib.exe /OUT:compositelib.lib lib1.lib lib2.lib 

在Linux或MingW上,使用GNU工具链:

 ar -M <<EOM CREATE libab.a ADDLIB liba.a ADDLIB libb.a SAVE END EOM ranlib libab.a 

如果你不删除liba.alibb.a ,你可以创build一个“精简档案”:

 ar crsT libab.a liba.a libb.a 

在Windows上,使用MSVC工具链:

 lib.exe /OUT:libab.lib liba.lib libb.lib 

静态库只是.o目标文件的存档。 用ar (假设Unix)解压缩它们并将它们打包回一个大型库。

另外,在项目属性中Link Library Dependencies还有另一种方法来链接Visual Studio中的库。

  1. 打开要与其他库合并的库(X)的项目。
  2. 添加你想结合X的其他库(右键单击, Add Existing Item... )。
  3. 去他们的属性,并确保Item TypeLibrary

这将包括X中的其他库,就像运行一样

 lib /out:X.lib X.lib other1.lib other2.lib 

在阅读其他内容之前,请注意:这里显示的shell脚本当然不是安全的,并且经过很好的testing。 使用风险自负!

我写了一个bash脚本来完成这个任务。 假设你的库是lib1,你需要包含一些符号的是lib2。 脚本现在运行在一个循环中,它首先检查lib1中哪些未定义的符号可以在lib2中find。 然后用ar从lib2中提取相应的目标文件,重命名它们,并把它们放到lib1中。 现在可能会有更多的缺失符号,因为你从lib2中包含的东西需要lib2中的其他东西,我们还没有包含这些东西,所以循环需要重新运行。 如果在循环的一些循环之后没有变化,也就是说lib2没有添加到lib1的目标文件,循环可以停止。

请注意,包含的符号仍被报告为nm未定义,所以我跟踪了自己添加到lib1的对象文件,以确定是否可以停止循环。

 #! /bin/bash lib1="$1" lib2="$2" 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 $1=$file } remove_tmp_files() { rm $remove_later } trap remove_tmp_files EXIT find_symbols() { nm $1 $2 | 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 

我把这个脚本命名为libcomp ,所以你可以用它来调用它

 ./libcomp libmylib.a libwhatever.a 

libw是什么地方你想包括符号。 不过,我认为将所有内容先复制到一个单独的目录是最安全的。 我不太相信我的脚本(不过,它对我有用;我可以将libgsl.a包含到我的数字库中,并省略-lgsl编译器开关)。