我有一小段代码依赖于许多静态库(a_1-a_n)。我想将该代码打包在静态库中并使其可供其他人使用。

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

我创建了一个简单的示例程序,它使用 X 中的函数,但是当我尝试将其链接到 X 时,我收到许多关于缺少库 a_1 - a_n 中的符号的错误。

有没有一种方法可以创建一个新的静态库 Y,其中包含 X 和 X 所需的所有功能(从 a_1 - a_n 中选择的位),以便我可以只分发 Y 供人们链接他们的程序?


更新:

我看过把所有东西都扔掉 阿尔 然而,制作一个大型库最终会包含许多不需要的符号(所有 .o 文件约为 700 MB,但是静态链接的可执行文件为 7 MB)。有没有一种好方法只包含实际需要的内容?


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

有帮助吗?

解决方案

静态库不与其它静态库链接。要做到这一点的唯一方法是使用你的图书管理员/归档工具(例如 AR 在Linux上)通过连接多个库创建一个新的静态库。

编辑:在回答您的更新,只有这样,我知道只选择所需是从包含它们的.o文件的子集手动创建库的符号。这是困难,耗时且容易出错。我不知道任何工具帮忙做这个(并不是说他们不存在),但它会使一个很有趣的项目,以农产品之一。

其他提示

如果您正在使用Visual Studio,然后是的,你可以做到这一点。

随Visual Studio允许你加入库一起在命令行上的库构建工具。我不知道任何方式在可视化编辑器,虽然做到这一点。

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,你可以做一个“瘦档案”:

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脚本肯定是不使用安全和行之有效的。需要您自担风险使用!

我写了一个bash脚本来完成这项任务。假设你的库LIB1和一个你需要包含一些符号是从LIB2。脚本现在运行在一个循环中,在那里它从未定义LIB1符号它首先检查可在LIB2找到。然后,它从LIB2提取对应的目标文件与ar,重命名他们一点,并把它们变成lib1内。现在,可能会有更多的缺少的符号,因为你从LIB2包括东西需要从LIB2其他的东西,这是我们还没有包括在内,因此该循环需要重新运行。如果循环的一些传球后没有变化了,即从加入LIB1 LIB2没有对象文件,循环可以停止。

请注意,通过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

其中libwhatever是要在其中包括来自符号。但是,我认为这是最安全的一切先复制到一个单独的目录。我不相信我的剧本这么多(但是,它为我工作,我可以包括libgsl.a到我NUMERICS库与和省去了-lgsl编译器开关)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top