C++ 将静态库链接到其他静态库
我有一小段代码,它依赖于许多静态库(a_1-a_n)。我想把这些代码打包到一个静态库中,让其他人可以使用 我的静态库,我们称之为X,编译得很好 我创建了一个使用X函数的简单示例程序,但是当我尝试将它链接到X时,我得到了许多关于库a_1-a_n中缺少符号的错误 有没有一种方法可以让我创建一个新的静态库Y,其中包含X和X所需的所有功能(从a_1-a_n中选择的位),这样我就可以只分发Y供人们链接他们的程序C++ 将静态库链接到其他静态库,c++,linker,unix-ar,.a,C++,Linker,Unix Ar,.a,我有一小段代码,它依赖于许多静态库(a_1-a_n)。我想把这些代码打包到一个静态库中,让其他人可以使用 我的静态库,我们称之为X,编译得很好 我创建了一个使用X函数的简单示例程序,但是当我尝试将它链接到X时,我得到了许多关于库a_1-a_n中缺少符号的错误 有没有一种方法可以让我创建一个新的静态库Y,其中包含X和X所需的所有功能(从a_1-a_n中选择的位),这样我就可以只分发Y供人们链接他们的程序 更新: 我已经研究过如何使用ar转储所有内容,并制作一个大型库,但最终会包含许多不需要的符号
更新: 我已经研究过如何使用ar转储所有内容,并制作一个大型库,但最终会包含许多不需要的符号(所有的.o文件约为700 MB,但是静态链接的可执行文件为7 MB)。是否有一个好的方法只包含实际需要的内容
这看起来与静态库密切相关。静态库不与其他静态库链接。唯一的方法是使用library/archiver工具(例如Linux上的ar)通过连接多个库来创建一个新的静态库
编辑:响应您的更新,我所知道的仅选择所需符号的唯一方法是从包含符号的.o文件子集手动创建库。这是困难、耗时且容易出错的。我不知道有什么工具可以帮助实现这一点(并不是说它们不存在),但制作一个静态库将是一个非常有趣的项目。静态库只是
.o
对象文件的存档。使用ar
(假设使用Unix)提取它们,并将它们打包回一个大型库。如果您使用的是Visual Studio,则可以执行此操作
VisualStudio附带的库生成器工具允许您在命令行上将库连接在一起。不过,我不知道在可视化编辑器中有什么方法可以做到这一点
lib.exe /OUT:compositelib.lib lib1.lib lib2.lib
除了在项目属性中链接库依赖项之外,还有另一种在Visual Studio中链接库的方法
添加现有项…
)项目类型
为库
lib /out:X.lib X.lib other1.lib other2.lib
在Linux或MingW上,使用GNU工具链:
ar -M <<EOM
CREATE libab.a
ADDLIB liba.a
ADDLIB libb.a
SAVE
END
EOM
ranlib libab.a
lib.exe /OUT:libab.lib liba.lib libb.lib
在Windows上,使用MSVC工具链:
ar -M <<EOM
CREATE libab.a
ADDLIB liba.a
ADDLIB libb.a
SAVE
END
EOM
ranlib libab.a
lib.exe /OUT:libab.lib liba.lib libb.lib
在阅读其余部分之前请注意:这里显示的shell脚本使用起来肯定不安全,而且经过了良好的测试。使用风险自负 我编写了一个bash脚本来完成这项任务。假设您的库是lib1,需要从中包含一些符号的库是lib2。脚本现在在循环中运行,首先检查lib1中哪些未定义的符号可以在lib2中找到。然后,它用
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
其中libanywhere是您希望包含符号的位置。然而,我认为首先将所有内容复制到单独的目录中是最安全的。我不太相信我的脚本(不过,它对我来说很有效;我可以将libgsl.a包含到我的数字库中,而不使用-lgsl编译器开关)。嗨,尼尔,我已经更新了这个问题——你知道有什么方法只包含必要的.o文件吗?更新——如果你发现自己想这样做,请后退一步,并追求其他东西(除非,正如约翰·克诺勒所指出的,您正在使用VisualStudio)。我花了很多时间在这种方法上,没有得到任何有用的东西。GNU ld工具提供了一个选项
-r
,可以将输出用作ld的输入。如果你链接一次,你应该得到一个可重新定位的链接,那么它就可以替代你的库。在VS2008中,在Library/General下compositelib的项目属性中,如果您选中[x]链接库依赖项,那么如果lib1和lib2是compositelib的依赖项,它将为您执行此操作。这似乎有点问题,我会在每个构建配置中分别设置复选框,而不是在“所有配置”中设置一次。VS2015 IDE-您不使用“其他依赖项”吗在图书管理员/将军的领导下,让更多的图书馆直接链接到你的项目正在建设的图书馆?@davidbak我在过去几天里试图解决这个问题,显然这个选项已经过时了,没有任何作用?很高兴知道,但并没有真正解决OP的问题,由于您将libb.a中的所有内容都包含在联合库中,如果您只需要libb中的几个模块,联合库可能会变得非常大。@ElmarZander但是您可以使用ar crsT
,它可以执行类似“符号链接”的操作,而不是复制,然后,您只需提供一份数据副本。精简归档主要用于Linux内核v4.19:您好,我使用的是Intel IPP,我构建了自己的函数,我希望所有函数都打包到一个(静态)库中。然而,当我创建lib,然后将项目发送到另一台计算机时,我希望它能够仅使用我创建的lib编译项目,我得到了一个错误,即