Jas*_*ram 125 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转储所有内容并制作一个mega-lib,然而,最终包含了许多不需要的符号(所有.o文件大约为700 MB,但是,静态链接的可执行文件是7 MB).有没有一种很好的方法只包括实际需要的东西?
这看起来与如何将多个C/C++库合并为一个密切相关?.
小智 66
静态库不与其他静态库链接.唯一的方法是使用librarian/archiver工具(例如Linux上的ar)通过连接多个库来创建一个新的静态库.
编辑:为了响应您的更新,我知道只选择所需符号的唯一方法是从包含它们的.o文件的子集手动创建库.这很困难,耗时且容易出错.我不知道有任何工具可以帮助做到这一点(并不是说它们不存在),但它会产生一个非常有趣的项目来制作一个.
Joh*_*ler 44
如果您使用的是Visual Studio,则可以执行此操作.
Visual Studio附带的库构建器工具允许您在命令行上将库连接在一起.我不知道在可视化编辑器中有什么方法可以做到这一点.
lib.exe /OUT:compositelib.lib lib1.lib lib2.lib
Run Code Online (Sandbox Code Playgroud)
Sta*_*ant 18
在Linux或MingW上,使用GNU工具链:
ar -M <<EOM
CREATE libab.a
ADDLIB liba.a
ADDLIB libb.a
SAVE
END
EOM
ranlib libab.a
Run Code Online (Sandbox Code Playgroud)
如果你不删除liba.a和libb.a,你可以做一个"瘦档案":
ar crsT libab.a liba.a libb.a
Run Code Online (Sandbox Code Playgroud)
在Windows上,使用MSVC工具链:
lib.exe /OUT:libab.lib liba.lib libb.lib
Run Code Online (Sandbox Code Playgroud)
在阅读其余部分之前请注意:此处显示的 shell 脚本肯定无法安全使用且经过良好测试。使用风险自负!
我编写了一个 bash 脚本来完成该任务。假设您的库是 lib1,而您需要包含一些符号的库是 lib2。该脚本现在在循环中运行,它首先检查可以在 lib2 中找到来自 lib1 的哪些未定义符号。然后它从 lib2 中提取相应的目标文件,稍微ar重命名它们,然后将它们放入 lib1。现在可能缺少更多符号,因为您从 lib2 中包含的内容需要来自 lib2 的其他内容,而我们尚未包含这些内容,因此循环需要再次运行。如果经过一些循环后不再有任何更改,即没有来自 lib2 的目标文件添加到 lib1,则循环可以停止。
请注意,包含的符号仍被报告为 undefined by 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
Run Code Online (Sandbox Code Playgroud)
我命名了那个脚本libcomp,所以你可以调用它,例如
./libcomp libmylib.a libwhatever.a
Run Code Online (Sandbox Code Playgroud)
libwhatever 是您想要包含符号的位置。但是,我认为首先将所有内容复制到单独的目录中是最安全的。我不太相信我的脚本(但是,它对我有用;我可以将 libgsl.a 包含在我的数字库中,而忽略 -lgsl 编译器开关)。
或者Link Library Dependencies在项目属性中,还有另一种在Visual Studio中链接库的方法.
Add Existing Item...).Item Type是Library这将包括X中的其他库,就像您运行一样
lib /out:X.lib X.lib other1.lib other2.lib
Run Code Online (Sandbox Code Playgroud)