我是用的OpenMP並行程序的系統交叉編譯,但是當我在目標上運行,我得到的錯誤:運行時庫本質上是動態庫嗎?
無法加載庫「libgomp.so.1」
細算在附近,我看到它是一個OpenMP運行時庫。是否有任何靜態鏈接它在編譯器主機上的庫,還是需要在目標機器上存在?如果它可以靜態鏈接,那麼運行時庫與動態庫有什麼不同呢?只要環境正確,是否可以靜態或動態鏈接任何庫?
我是用的OpenMP並行程序的系統交叉編譯,但是當我在目標上運行,我得到的錯誤:運行時庫本質上是動態庫嗎?
無法加載庫「libgomp.so.1」
細算在附近,我看到它是一個OpenMP運行時庫。是否有任何靜態鏈接它在編譯器主機上的庫,還是需要在目標機器上存在?如果它可以靜態鏈接,那麼運行時庫與動態庫有什麼不同呢?只要環境正確,是否可以靜態或動態鏈接任何庫?
您可以通過提供某些鏈接器選項來選擇性地靜態鏈接某些庫。對於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
,鏈接錯誤的結果放置。
您的使用靜態只爲gomp的示例不適用於我。我收到很多錯誤,比如'未定義的引用dlerror'。 GCC 5.2.1,Ubuntu 15.10 64位。在Linux上混合動態庫和靜態庫對我來說是一場噩夢。 –
等一下,我剛剛開始工作。我不得不添加'-dl'。 –
'gcc -o foo foo.o -Wl,-static -lgomp -Wl,-Bdynamic -lpthread -ldl'適用於我 –
術語「運行時庫」通常用於運行程序所需的標準庫和環境。在C程序的情況下,它是C標準庫,也可能是其他某些針對編譯器的庫,還有一些目標文件鏈接到您的程序以設置標準C環境。
「運行時庫」可以是是一個動態庫,或者甚至是多個動態庫的集合。但它也可以是一個或多個靜態庫。
因此,如果給定的運行時庫作爲主機上的API的一部分提供,我應該能夠在交叉編譯時靜態鏈接它,並且運行輸出可執行文件而不需要目標機器上的庫,更正? – Spence123
動態庫是很方便的方式提供運行庫庫,因爲許多程序可能希望鏈接到這樣的庫。這就是爲什麼動態鏈接和動態庫在那裏 - 第一個需要特定動態庫的進程會導致它被加載到內存中。之後,動態庫的這個實例可以被許多進程重用。
想象一下,如果你有幾十個進程在運行,並且每個進程都會靜態鏈接到說C runtime
庫。與其中每個進程都將鏈接到單個DLL的情況相比,我認爲內存消耗會顯着增長。
在我看來,如果庫將被許多不同的進程使用(例如DirectX可能是這樣的庫),將它作爲動態庫提供可能更有效。否則,靜態鏈接是最好的。
建設時,嘗試添加'-static'標誌。但要注意,所有*庫可能會靜態鏈接。 –
當我嘗試這樣做時,出現了一個關於嘗試靜態鏈接動態對象的錯誤,我的其他庫之一。不過謝謝你的想法。 – Spence123