2015-11-03 51 views
1

我是用的OpenMP並行程序的系統交叉編譯,但是當我在目標上運行,我得到的錯誤:運行時庫本質上是動態庫嗎?

無法加載庫「libgomp.so.1」

細算在附近,我看到它是一個OpenMP運行時庫。是否有任何靜態鏈接它在編譯器主機上的庫,還是需要在目標機器上存在?如果它可以靜態鏈接,那麼運行時庫與動態庫有什麼不同呢?只要環境正確,是否可以靜態或動態鏈接任何庫?

+0

建設時,嘗試添加'-static'標誌。但要注意,所有*庫可能會靜態鏈接。 –

+0

當我嘗試這樣做時,出現了一個關於嘗試靜態鏈接動態對象的錯誤,我的其他庫之一。不過謝謝你的想法。 – Spence123

回答

1

您可以通過提供某些鏈接器選項來選擇性地靜態鏈接某些庫。對於libgomp它會是這樣的:

gcc -o executable foo.o bar.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread -lother -llibs 

-Wl,-static-Wl,-Bdynamic之間列出的所有庫將靜態鏈接。 -fopenmp不應出現在鏈接命令中,因爲它擴展爲在用戶提供的選項後附加的鏈接器標誌,因此應該明確列出libpthread。這也意味着即使是簡單的OpenMP程序也必須通過兩個獨立的步驟進行編譯和鏈接,才能實現靜態鏈接。

實施例:

// foo.c 
#include <stdio.h> 
#include <omp.h> 

int main(void) 
{ 
    #pragma omp parallel 
    printf("Hello world from thread %d\n", omp_get_thread_num()); 
    return 0; 
} 

傳統彙編:

$ gcc -fopenmp -o foo foo.c 
$ ldd foo 
    linux-vdso.so.1 => (0x00007ffff5661000) 
    libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x0000003bcfa00000) 
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003bc2600000) 
    libc.so.6 => /lib64/libc.so.6 (0x0000003bc1e00000) 
    librt.so.1 => /lib64/librt.so.1 (0x0000003bc3200000) 
    /lib64/ld-linux-x86-64.so.2 (0x0000003bc1a00000) 

該方案是針對libgomp的DSO版本鏈接。

完全靜態鏈接:

$ gcc -fopenmp -static -o foo foo.c 
$ ldd foo 
    not a dynamic executable 

隨着-static所有庫靜態連接到可執行文件。

鏈接僅libgomp靜態:

$ gcc -fopenmp -c foo.c 
$ gcc -o foo foo.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread 
$ ldd foo 
    linux-vdso.so.1 => (0x00007ffdaaf61000) 
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003bc2600000) 
    libc.so.6 => /lib64/libc.so.6 (0x0000003bc1e00000) 
    /lib64/ld-linux-x86-64.so.2 (0x0000003bc1a00000) 

它是保持在這種情況下,靜態鏈接對象的正確順序很重要。

$ gcc -o foo -Wl,-static -lgomp -Wl,-Bdynamic foo.o -lpthread 
foo.o: In function `main': 
foo.c:(.text+0x14): undefined reference to `GOMP_parallel_start' 
foo.c:(.text+0x23): undefined reference to `GOMP_parallel_end' 
foo.o: In function `main.omp_fn.0': 
foo.c:(.text+0x3b): undefined reference to `omp_get_thread_num' 
collect2: ld returned 1 exit status 

從包含OpenMP結構應-lgomp之前被放置源代碼產生的任何對象文件:如果foo.o之後-lgomp,鏈接錯誤的結果放置。

+0

您的使用靜態只爲gomp的示例不適用於我。我收到很多錯誤,比如'未定義的引用dlerror'。 GCC 5.2.1,Ubuntu 15.10 64位。在Linux上混合動態庫和靜態庫對我來說是一場噩夢。 –

+0

等一下,我剛剛開始工作。我不得不添加'-dl'。 –

+0

'gcc -o foo foo.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread -ldl'適用於我 –

1

術語「運行時庫」通常用於運行程序所需的標準庫和環境。在C程序的情況下,它是C標準庫,也可能是其他某些針對編譯器的庫,還有一些目標文件鏈接到您的程序以設置標準C環境。

「運行時庫」可以是是一個動態庫,或者甚至是多個動態庫的集合。但它也可以是一個或多個靜態庫。

+0

因此,如果給定的運行時庫作爲主機上的API的一部分提供,我應該能夠在交叉編譯時靜態鏈接它,並且運行輸出可執行文件而不需要目標機器上的庫,更正? – Spence123

1

動態庫是很方便的方式提供運行庫庫,因爲許多程序可能希望鏈接到這樣的庫。這就是爲什麼動態鏈接和動態庫在那裏 - 第一個需要特定動態庫的進程會導致它被加載到內存中。之後,動態庫的這個實例可以被許多進程重用。

想象一下,如果你有幾十個進程在運行,並且每個進程都會靜態鏈接到說C runtime庫。與其中每個進程都將鏈接到單個DLL的情況相比,我認爲內存消耗會顯着增長。

在我看來,如果庫將被許多不同的進程使用(例如DirectX可能是這樣的庫),將它作爲動態庫提供可能更有效。否則,靜態鏈接是最好的。

相關問題