gcc連接選項 連接靜態庫和動態庫

連接庫

連接指定的庫有兩種方式html

  • -llibrary
  • -l library

如連接LuaJIT庫,能夠用-lluajit-5.1,此時gcc會在庫路徑中查找libluajit-5.1.so或者libluajit-5.1.a。 也能夠用-l llibluajit-5.1.a,第二種只能用在POXIS上,推薦使用第一種方式。並且第二種方式只會在特定的目錄進行搜索,會發生找不到庫的狀況。linux

經過-llibrary連接庫時,可能既有靜態庫如libluajit-5.1.a,也有動態庫如libluajit-5.1.so,這是連接器會優先連接動態庫。c++

指定庫路徑

若是須要的庫不在系統的庫搜索路徑下,就須要經過-L指定庫的搜索路徑。 如lua解釋器安裝時會把libluajit-5.1.a,和libluajit-5.1.so等放在/usr/local/lib下,而gcc進行連接時默認不會在這個路徑下搜索庫,致使連接失敗。經過-L/usr/local/lib指定庫路徑就能夠解決這個問題。app

~$ gcc main.c -lluajit-5.1             
/usr/bin/ld: 找不到 -lluajit-5.1
collect2: error: ld returned 1 exit status

~$ gcc main.c -L/usr/local/lib -lluajit-5.1

指定運行時庫搜索路徑

有時經過-L指定庫路徑能夠正常連接,運行程序時卻由於找不到庫報錯lua

~ $ ./a.out 
./a.out: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
~ $ ldd ./a.out 
	linux-vdso.so.1 =>  (0x00007ffc1638e000)
	libluajit-5.1.so.2 => not found
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c23d48000)
	/lib64/ld-linux-x86-64.so.2 (0x000055713bf16000)

使用ldd命令能夠看到運行時找不到libluajit-5.1.so.2,沒法運行,對此能夠經過-Wl,-rpath指定運行時庫的搜索路徑3d

kenan@kenan-desktop ~ $ gcc test.c -I/usr/local/include/luajit-2.1 -Wl,-rpath=/usr/local/lib/ -lluajit-5.1
kenan@kenan-desktop ~ $ ./a.out 
Hello, Lua!
~ $ 
~ $ ldd ./a.out 
	linux-vdso.so.1 =>  (0x00007ffd6c5d7000)
	libluajit-5.1.so.2 => /usr/local/lib/libluajit-5.1.so.2 (0x00007f5ea238c000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5ea1fa5000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5ea1c9b000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5ea1a97000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5ea1881000)
	/lib64/ld-linux-x86-64.so.2 (0x0000565491551000)

再使用ldd命令查看,libluajit-5.1.so.2在/sur/local/lib下。code

使用靜態連接

對於運行時找不到動態庫的問題,除了經過-Wl,-rpath指定路徑外,還能夠經過靜態連接庫的方式來解決。實際生產環境中一般只在一臺機器上編譯二進制程序,再將二進制程序分發到線上運行環境。程序須要的庫可能實際線上環境中根本沒有,也須要將庫靜態連接。htm

靜態連接庫有下面幾種方式。文檔

只保留靜態庫

如安裝luajit後,在/usr/local/lib下既有靜態庫,也有動態庫。連接時優先連接動態庫。若是將動態庫刪除,只保留靜態庫,這時連接器就會連接靜態庫.get

經過-Wl,-Bstatic對指定的庫使用靜態連接

gcc會對-Wl,-Bstatic 後面的庫使用靜態連接。對-Wl,-Bdynamic後面跟的庫使用動態連接。 若是須要對指定的庫使用靜態連接,其餘的庫使用默認的動態連接,能夠這樣用

gcc test  -Wl,-Bstatic -lluajit-5.1 -Wl,-Bdynamic -lxxx -lxxx

這樣gcc會連接libluajit-5.1.a,而對其餘庫使用動態連接。

使用 -static 避免動態連接

gcc編譯時使用-static參數,會阻止使用動態連接的方式。與以前兩個方法不一樣,-static參數會致使gcc對全部的庫使用靜態連接,通常不推薦使用這種方式。

~ $ gcc test.c -I/usr/local/include/luajit-2.1 -Wl,-rpath=/usr/local/lib/ -L/usr/local/lib -lluajit-5.1 -ldl -lm -static
~ $ ldd ./a.out 
	不是動態可執行文件

對程序使用ldd命令提示不是動態可執行文件

沒有使用-static時ldd能夠看到程序須要的動態庫,以及庫的路徑。

~ $ gcc test.c -I/usr/local/include/luajit-2.1 -Wl,-rpath=/usr/local/lib/ -L/usr/local/lib -lluajit-5.1 -ldl -lm     
~ $ ldd ./a.out 
	linux-vdso.so.1 =>  (0x00007ffd057f1000)
	libluajit-5.1.so.2 => /usr/local/lib/libluajit-5.1.so.2 (0x00007f1e72a48000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1e7267f000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f1e72375000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1e72171000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f1e71f5b000)
	/lib64/ld-linux-x86-64.so.2 (0x000055875c7a0000)

使用 -static-libxxx對某些系統庫進行靜態連接

gcc自己提供了參數能夠只對libgcc,libstdc++等庫進行靜態連接 主要有下面這些

-static-libgcc

-static-libasan

-static-libtsan

-static-liblsan

-static-libubsan

-static-libmpx

-static-libmpxwrappers

-static-libstdc++

更詳細的介紹能夠參見官方文檔

相關文章
相關標籤/搜索