2021-05-12 14:32:11
Linux編譯相關命令
一、編譯可執行檔案
g++ –c Hello.cpp 編譯檔案,生成目標檔案Hello.o
g++ Hello.o –o a.out 連結並重新命名為可執行檔案a.out
g++ Hello.cc 編譯連結一起,生成a.out
g++ Hello.cc –o hello 生成a.out並命名為hello
二、編譯相關選項
(1)-c
生成.o檔案,對程式碼檔案進行預處理、編譯和組合,相當於windows下生成目標檔案obj
g++ -c hello.cpp
(2)-I DirPath
指定檔案查詢目錄
-include file
-i file
指定包含的檔案
g++ hello.cpp -include ../include/a.h
-I- DirPath
就是取消前一個引數的功能,所以一般在-I DirPath之後使用
(3)-L LibPath
指定連結庫的路徑
-l library
-llibrary
指定連結庫
(4) -g
在編譯的時候,產生偵錯資訊,程式執行時可以dbg偵錯
(4)-static
此選項將禁止使用動態庫。
優點:程式執行不依賴於其他庫
缺點:檔案比較大
gcc test_main.c -static -o test_main -lpthread
會發現test_main很大,它已經把各種依賴的東西都包含進來
(5) -shared (-G)
此選項將儘量使用動態庫,為預設選項
優點:生成檔案比較小
缺點:執行時需要系統提供動態庫
(6)-Wall
一般使用該選項,允許發出GCC能夠提供的所有有用的警告。也可以用-W{warning}來標記指定的警告。
三、靜態庫和動態庫的編譯命令
1、生成動態庫和靜態庫
(1)得到hello.o
g++ -c hello.cpp
(2)得到靜態庫myhello.a
ar -cr libmyhello.a hello.o
(3)使用靜態庫
g++ -o hello main.c -L. -lmyhello
-L.表示靜態庫位於當前目錄下,myhello自動加上lib組成靜態庫名稱libmyhello.a
(4)得到動態庫myhello.so
g++ -fPIC -shared hello.cpp -o libmyhello.so
(5)使用動態庫
動態庫的時候和靜態庫使用一樣,唯一值得注意的是當目錄中同時存在相同名稱的動態庫和靜態庫時,編譯的時候優先使用動態庫
2、fPIC選項
加上fPIC選項生成的動態庫時位置無關的,可以實現多個進程共用動態庫,多個進程參照同一個PIC動態庫時,可以共用記憶體。這一個庫在不同進程中的虛擬地址不同,但作業系統顯然會把它們對映到同一塊實體記憶體上。
不加fPIC,則載入so檔案時,需要對程式碼段參照的資料物件需要重定位,重定位會修改程式碼段的內容,這就造成每個使用這個.so檔案程式碼段的進程在核心裡都會生成這個.so檔案程式碼段的copy.每個copy都不一樣,取決於這個.so檔案程式碼段和資料段記憶體對映的位置。可見,這種方式更消耗記憶體。
3、如何解決執行時找不到動態庫的問題
(1)將動態庫新增到系統預設的搜尋路徑下,如/lib、/usr/lib
(2)設定臨時動態庫路徑的環境變數,這種方法設定的是臨時的,系統重新啟動之後就沒了
export LD_LIBRARY_PATH=./
取消設定
export LD_LIBRARY_PATH=
(3)/etc/ld.so.cache中快取了動態庫路徑,可以通過修改組態檔/etc/ld.so.conf中指定的動態庫搜尋路徑,然後執行ldconfig命令來改變
(4)編譯連結新增-WL,-rpath命令選項,將執行時動態庫的搜尋路徑記錄在可執行程式中
例如,有原始檔test.cpp和func.cpp
g++ -shared -fPIC func.cpp -o libfunc.so
編譯得到libfunc.so動態庫
g++ main.cpp -o a.out -L ./ -lfunc
編譯得到a.out,執行a.out,提示出錯
ldd檢視a.out依賴的動態庫,發現libfunc.so找不到
g++ main.cpp -o a.out -L ./ -lfunc -WL,-rpath ./
編譯得到a.out,執行a.out,執行成功,ldd檢視a.out依賴的動態庫,發現libfunc.so路徑正確
把a.out和libfunc.so拷貝到任何目錄下,都能執行成功
相關文章