c++ - 將靜態庫鏈接到其他靜態庫




linker ar .a (6)

在閱讀其他內容之前請注意:這裡顯示的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

libw是什麼是你想要包含符號的地方。 不過,我認為將所有內容先複製到單獨的目錄是最安全的。 我不會那麼信任我的腳本(但是,它對我有用;我可以將libgsl.a包含到我的數字庫中,並省略-lgsl編譯器開關)。

我有一小段代碼依賴於許多靜態庫(a_1-a_n)。 我想將這些代碼打包到一個靜態庫中,並將其提供給其他人。

我的靜態庫,讓它叫X,編譯好。

我創建了一個簡單的示例程序,它使用了X中的一個函數,但是當我嘗試將它鏈接到X時,出現了許多有關從庫a_1 - a_n中丟失符號的錯誤。

有沒有一種方法可以創建一個新的靜態庫,Y包含X和X所需的所有功能(從a_1 - a_n中選擇位),這樣我就可以將Y分發給人們將它們的程序鏈接到?

更新:

我已經看過只是用ar來拋棄所有東西,然後製作一個超級lib,但最終會包含很多不需要的符號(所有的.o文件都是大約700 MB,但是靜態鏈接的可執行文件是7 MB)。 有沒有一種很好的方法來僅包含實際需要的內容?

這看起來與如何將幾個C / C ++庫合併為一個密切相關


靜態庫只是.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

如果你使用的是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

術語“STL”或“標準模板庫”不會出現在ISO 14882 C ++標準的任何地方。 所以將C ++標準庫稱為STL是錯誤的。 術語“C ++標準庫”或“標準庫”是ISO 14882正式使用的術語:

ISO 14882 C ++標準:

17 - 圖書館介紹[lib.library]:

  1. 本章節描述了C ++標準庫的內容,一個結構良好的C ++程序如何使用該庫以及一致性實現如何提供庫中的實體。

...

STL是最初由Alexander Stepanov設計的獨立於C ++標準的庫。 但是,C ++標準庫的一些組件包括STL組件,如vectorlistcopyswap等算法。

但是,當然C ++標准在STL之外包含了更多的東西,所以術語“C ++標準庫”更加正確(標准文檔實際使用的是這個術語)。





c++ linker ar .a