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

我有一小段代码,它依赖于许多静态库(a _ 1-a _ n)。我想把这些代码打包在一个静态库中,让其他人可以使用。

我的静态库,我们称之为 X,编译得很好。

我已经创建了一个简单的示例程序,它使用来自 X 的函数,但是当我试图将它链接到 X 时,我发现库 a _ 1-a _ n 中缺少符号的错误很多。

有没有一种方法,我可以创建一个新的静态库,Y 包含 X 和 X 所需要的所有功能(从 _ 1-a _ n 中选择的位) ,这样我就可以只分发 Y,让人们链接他们的程序?


更新:

我已经考虑过用 转储所有东西,然后制作一个 Mega-lib,但是,它最终包含了很多不需要的符号(所有。O 文件大约是700MB,但是,静态链接的可执行文件是7MB)。有没有一种很好的方法只包含实际需要的内容?


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

131874 次浏览

静态库不与其他静态库链接。唯一的方法是使用库管理员/归档工具(例如 Linux 上的 )通过连接多个库来创建一个新的静态库。

编辑: 为了响应您的更新,我所知道的仅选择所需符号的唯一方法是从。包含它们的文件。这是困难的,耗费时间和容易出错。我不知道有什么工具可以帮助做到这一点(并不是说它们不存在) ,但是制作一个这样的工具会是一个非常有趣的项目。

静态库只是 .o对象文件的归档文件。用 ar(假设是 Unix)提取它们,并将它们打包回一个大库中。

如果您正在使用 VisualStudio,那么是的,您可以这样做。

VisualStudio 附带的库生成器工具允许您在命令行上将库联接在一起。但是我不知道在可视化编辑器中有什么方法可以做到这一点。

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

除了在项目属性中使用 Link Library Dependencies之外,还有另一种在 VisualStudio 中链接库的方法。

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

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

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

如果你不删除 liba.alibb.a,你可以创建一个“瘦存档”:

ar crsT libab.a liba.a libb.a

在 Windows 上,使用 MSVC 工具链:

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,因此您可以调用 then

./libcomp libmylib.a libwhatever.a

其中 libwhatever 是您希望包含符号的位置。但是,我认为最安全的做法是首先将所有内容复制到一个单独的目录中。我不太相信我的脚本(但是,它对我很有用; 我可以将 libgsl.a 包含到我的数字库中,并且省略-lgsl 编译器开关)。