目錄html
轉載請註明出處,謝謝 https://www.cnblogs.com/tianknight/p/10648021.htmllinux
關於gcc這三個參數,參考了諸多文檔後,仍然理解上有誤差,仿照下面博客中的方法,本身調試了一波,總算是理解了。仍是建議你們動手實踐一下。.net
參考資料以下:3d
- https://blog.csdn.net/q1302182594/article/details/42102961
- https://blog.csdn.net/openme_openwrt/article/details/7860580
新建三個文件:test.c hello.c world.c ,其源碼依賴關係爲:test.c 依賴 hello.c;hello.c 依賴 world.c調試
test.ccode
#include <stdio.h> void world(void); void hello(void) { printf("hello "); world(); }
hello.chtm
#include<stdio.h> void hello(void); void main(void) { hello(); }
world.cblog
#include<stdio.h> void world(void) { printf("world.\n"); }
# -o 指定輸出文件 [root@localhost testc]# ls hello.c test.c world.c [root@localhost testc]# gcc -o hehe *.c [root@localhost testc]# ls hehe hello.c test.c world.c [root@localhost testc]# ./hehe hello world.
# -shared 編譯連接庫 # -fPIC 個人理解是編譯連接庫時給代碼動態分配內存 [root@localhost testc]# gcc -shared -fPIC -o libworld.so world.c [root@localhost testc]# ls hello.c libworld.so test.c world.c [root@localhost testc]# ldd libworld.so linux-vdso.so.1 => (0x00007ffd7498f000) libc.so.6 => /lib64/libc.so.6 (0x00007fcb49815000) /lib64/ld-linux-x86-64.so.2 (0x00007fcb49dea000) #上述命令和下面的等價,建議選取單條命令便可:gcc -shared -fPIC -o libworld.so world.c # -c 只激活預處理,編譯,和彙編,也就是他只把程序作成obj文件 [root@localhost testc]# gcc -c -fPIC world.c [root@localhost testc]# ls hello.c test.c world.c world.o [root@localhost testc]# gcc -shared -fPIC -o libworld.so world.o [root@localhost testc]# ls hello.c libworld.so test.c world.c world.o [root@localhost testc]# ldd libworld.so linux-vdso.so.1 => (0x00007ffd0dfa9000) libc.so.6 => /lib64/libc.so.6 (0x00007f4357dcb000) /lib64/ld-linux-x86-64.so.2 (0x00007f43583a0000)
# -lxxx 指定須要動態連接的庫文件 # -L 指定動態鏈接庫文件的位置(編譯時) # . 指當前路徑 # 下面編譯出的libhello.so文件已經顯式依賴libworld.so文件,可是沒有找到libworld.so的位置 [root@localhost testc]# gcc -shared -fPIC -o libhello.so hello.c -lworld -L. [root@localhost testc]# ls hello.c libhello.so libworld.so test.c world.c [root@localhost testc]# ldd libhello.so linux-vdso.so.1 => (0x00007ffe61b89000) libworld.so => not found libc.so.6 => /lib64/libc.so.6 (0x00007ff73cc1e000) /lib64/ld-linux-x86-64.so.2 (0x00007ff73d1f4000)
[root@localhost testc]# ls hello.c libhello.so libworld.so test.c world.c # 編譯出錯,提示找不到hello [root@localhost testc]# gcc -o haha test.c /tmp/ccQCWcSW.o: In function 'main': test.c:(.text+0x5): undefined reference to 'hello' collect2: error: ld returned 1 exit status # 添加libhello.so的連接索引,並指定庫的搜索路徑爲'.'(當前路徑) # 依然編譯失敗,提示找不到libworld.so,該庫被libhello.so依賴,並提示建議使用-rpath 或 -rpath-link解決 [root@localhost testc]# gcc -o haha test.c -lhello -L. /usr/bin/ld: warning: libworld.so, needed by ./libhello.so, not found (try using -rpath or -rpath-link) ./libhello.so: undefined reference to 'world' collect2: error: ld returned 1 exit status # 手動添加libworld.so的依賴,編譯經過,查看haha的連接庫,已經顯式指出依賴,可是沒有找到其位置 [root@localhost testc]# gcc -o haha test.c -lhello -L. -lworld [root@localhost testc]# ldd haha linux-vdso.so.1 => (0x00007fff556ea000) libhello.so => not found libworld.so => not found libc.so.6 => /lib64/libc.so.6 (0x00007f1ff0c97000) /lib64/ld-linux-x86-64.so.2 (0x00007f1ff106b000) # 執行編譯出的haha,執行報錯,提示找不到依賴庫 [root@localhost testc]# ./haha ./haha: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory #修改系統環境變量'LD_LIBRARY_PATH',增長索引庫的位置,查看依賴OK,執行haha, 結果OK, 清空'LD_LIBRARY_PATH' [root@localhost testc]# export LD_LIBRARY_PATH=/home/testc/ && echo $LD_LIBRARY_PATH /home/testc/ [root@localhost testc]# ldd haha linux-vdso.so.1 => (0x00007ffd647d2000) libhello.so => /home/testc/libhello.so (0x00007fb7aa063000) libworld.so => /home/testc/libworld.so (0x00007fb7a9e60000) libc.so.6 => /lib64/libc.so.6 (0x00007fb7a9a8e000) /lib64/ld-linux-x86-64.so.2 (0x00007fb7aa266000) [root@localhost testc]# ./haha hello world. [root@localhost testc]# export LD_LIBRARY_PATH= && echo $LD_LIBRARY_PATH # 將-lworld 替換爲 -Wl,-rpath-link=. ,編譯OK,依然找不到索引庫,添加LD_LIBRARY_PATH後,執行OK [root@localhost testc]# gcc -o haha test.c -lhello -L. -Wl,-rpath-link=. [root@localhost testc]# ldd haha linux-vdso.so.1 => (0x00007ffdf67c0000) libhello.so => not found libc.so.6 => /lib64/libc.so.6 (0x00007fbdbb94b000) /lib64/ld-linux-x86-64.so.2 (0x00007fbdbbd1f000) [root@localhost testc]# ./haha ./haha: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory [root@localhost testc]# export LD_LIBRARY_PATH=/home/testc && echo $LD_LIBRARY_PATH /home/testc [root@localhost testc]# ldd haha linux-vdso.so.1 => (0x00007fff89504000) libhello.so => /home/testc/libhello.so (0x00007fc9e75c6000) libc.so.6 => /lib64/libc.so.6 (0x00007fc9e71f3000) libworld.so => /home/testc/libworld.so (0x00007fc9e6ff1000) /lib64/ld-linux-x86-64.so.2 (0x00007fc9e77c9000) [root@localhost testc]# ./haha hello world. [root@localhost testc]# export LD_LIBRARY_PATH= && echo $LD_LIBRARY_PATH # 將-Wl,-rpath-link=. 換成 -Wl,-rpath=. 編譯OK, 查看連接庫OK,執行OK # 修改LD_LIBRARY_PATH後,連接庫的位置沒有變化 [root@localhost testc]# gcc -o haha test.c -lhello -L. -Wl,-rpath=. [root@localhost testc]# ls haha hello.c libhello.so libworld.so test.c world.c [root@localhost testc]# ldd haha linux-vdso.so.1 => (0x00007fff86195000) libhello.so => ./libhello.so (0x00007f4c11254000) libc.so.6 => /lib64/libc.so.6 (0x00007f4c10e81000) libworld.so => ./libworld.so (0x00007f4c10c7f000) /lib64/ld-linux-x86-64.so.2 (0x00007f4c11457000) [root@localhost testc]# ./haha hello world. [root@localhost testc]# export LD_LIBRARY_PATH=/home/testc/ && echo $LD_LIBRARY_PATH /home/testc/ [root@localhost testc]# ldd haha linux-vdso.so.1 => (0x00007ffc9f36c000) libhello.so => ./libhello.so (0x00007f35cf07c000) libc.so.6 => /lib64/libc.so.6 (0x00007f35ceca9000) libworld.so => ./libworld.so (0x00007f35ceaa7000) /lib64/ld-linux-x86-64.so.2 (0x00007f35cf27f000) [root@localhost testc]# export LD_LIBRARY_PATH= && echo $LD_LIBRARY_PATH
- 編譯時連接庫須要分爲兩類: 直接引用 間接引用
- 直接引用 被源碼中直接調用的庫
- 間接引用 被調用庫的依賴庫
- -lxxx 指定具體的庫名稱,編譯時須要顯式指定直接引用的庫名稱
- -L 指定連接庫的位置,編譯時須要顯式指定直接引用的庫位置
- -Wl,-rpath-link ,用於編譯時指定間接引用的庫位置
若是知道全部間接引用的庫文件名稱,而且不嫌麻煩,也能夠用-lxxx顯式指定每個庫(不推薦-lxxx)- -Wl,-rpath ,有兩個做用:
- 用於編譯時指定間接引用的庫位置,做用同-Wl,-rpath-link
- 用於運行時指定全部引用庫的位置,做用同修改環境變量(LD_LIBRARY_PATH),而且庫路徑引用優先級高於LD_LIBRARY_PATH
- 使用建議
- 編譯命令中使用-Wl,-rpath-link 指定間接引用庫位置(編譯時),使用-Wl,-rpath 指定引用庫位置(運行時)
- -Wl,-rpath-link 在 -Wl,-rpath 前