1. 程式人生 > 其它 >Linux下gcc編譯命令複習筆記

Linux下gcc編譯命令複習筆記

GCC

  • 安裝 sudo apt install gcc g++
  • 檢視版本 gcc/g++ -v/--version
  • gcc常用引數選項
gcc編譯選項 說明
-E 預處理指定的原始檔,不進行編譯
-S 編譯指定的原始檔,但是不進行彙編
-c 編譯、彙編指定的原始檔,但是不進行連結
-o [file1] [file2] / [file2] -o [file1] 將檔案 file2 編譯成可執行檔案 file1
-I directory 指定 include 包含檔案的搜尋目錄
-g 在編譯的時候,生成除錯資訊,該程式可以被偵錯程式除錯
-D 在程式編譯的時候,指定一個巨集
-w 不生成任何警告資訊
-Wall 生成所有警告資訊
-On n的取值範圍:0~3。編譯器的優化選項的4個級別,-O0表示沒有優化,-O1為預設值,-O3優化級別最高
-l 在程式編譯的時候,指定使用的庫
-L 指定編譯的時候,搜尋的庫的路徑。
-fPIC/fpic 生成與位置無關的程式碼
-shared 生成共享目標檔案,通常用在建立共享庫時
-std 指定C方言,如:-std=c99,gcc預設的方言是GNU C

庫的製作

靜態庫

  • 命名規則
    • Linux下檔名為libxxx.a ,lib為固定字首,.a為固定字尾,xxx為自定義庫名。
  • 製作
    • gcc獲得.o檔案
    • 將.o檔案打包,使用ar工具
      ar rcs libxxx.a xxx.o xxx.o
      r - 將檔案插入備存檔案中
      c - 建立備存檔案
      s - 索引
  • 使用
    使用gcc中的-l和-L指定使用製作好的靜態庫。(注意標頭檔案預編譯要用-I)
    示例編譯命令:
    gcc main.c -o main -I ./include -l calc -L ./lib
    注意上面使用的靜態庫檔名為libcalc.a

動態庫

  • 命名規則
    • Linux下檔名為libxxx.so ,lib為固定字首,.a為固定字尾,xxx為自定義庫名。在Linux下位可執行檔案。
  • 製作
    • gcc得到.o檔案,得到和位置無關的程式碼
      gcc -c -fpic/-FPIC file1.c file2.c
    • gcc得到動態庫
      gcc -shared file1.o file2.o -o libcalc.so
  • 使用
    如果使用和靜態庫檔案一樣的編譯命令:
    gcc main.c -o main -I ./include -l calc -L ./lib
    然後執行生成的main程式時會發現報錯:
    ./main: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory
    
    這是因為系統找不到我們製作的動態庫的位置,只需要將動態庫加入到可以被ld-linux.so能搜尋的地方即可。它先後搜尋elf檔案的DT_RPATH段 ——> 環境變數LD_LIBRARY_PATH ——> /etc/ld.so.cache檔案列表 ——> /lib//usr/lib目錄找到庫檔案後將其載入記憶體。
    解決:
    1. 新增環境變數
      直接在命令列輸入export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<lib路徑>
      之後可以通過echo $LD_LIBRARY_PATH檢視環境變數是否修改成功,然後ldd main檢視能否找到庫檔案位置。
      但是這種方法在關閉終端再重新開啟後會失效,因為這是臨時改變環境變數。
    • 使用者修改.bashrc
      修改使用者目錄下的.bashrc檔案。在該檔案最後一行加入剛才新增環境變數時的命令,儲存退出後通過. ~/.bashrcsource ~/.bashrc使其生效。
    • 系統修改profile
      sudo修改/etc/profile檔案,在最後一行新增同樣的命令後再儲存退出後source。
    • 有時可能需要重新開啟終端使修改檔案生效。
    1. 修改/etc/ld.so.cache檔案
      這個檔案是二進位制檔案,需要通過修改/etc/ld.so.conf檔案間接配置。直接在檔案內新增lib地址後儲存退出然後執行sudo ldconfig命令即可生效。
    2. 把庫檔案新增到庫目錄/lib/,/usr/lib下
      不推薦,避免出現檔名衝突問題。