編譯鏈結和庫

2021-07-25 14:37:13 字數 4142 閱讀 6161

簡單c程式

c code

#include 

int main(int argc, char **argv)

過程

預處理

gcc -e -o main.i main.c

1. 展開所有巨集定義

2. 處理條件預編譯指令

3. 插入#include執行的標頭檔案**

4. 新增行號和檔案標識, 以便編譯錯誤和警告的提示.

5. 刪除所有注釋

6. 新增其他資訊

編譯

gcc -s -o main.s main.i

對預處理完的檔案test.i進行詞法分析, 語法分析, 語義分析以及優化後生成相應的彙編**.

彙編

gcc -c -o main.o main.s

將彙編**轉變成二進位制機器指令(根據彙編指令和機器指令對照表逐條翻譯), 最後產生目標檔案main.o.

鏈結

gcc -o main main.ogdb

編譯時使用gcc -g選項才能使用gdb除錯

自動化編譯鏈結檔案

makefile語句

目標檔案: 依賴檔案…

命令…makefile變數

宣告: var_name = var…

使用: $(var_name)

makefile特殊變數

$@: 目標檔案

$^: 被依賴的所有檔案

$<: 被依賴的第乙個檔案

約定俗成的目標命令

all: 編譯所有目標

clean: 刪除make建立的檔案

install: 安裝已編譯好的程式

print: 列出改變過的原始檔

tar: 打包備份

dist: 建立乙個壓縮檔案

tags: 更新所有目標

防止和檔名衝突可以使用偽命令.phony

簡單makefile編寫

makefile code

cc = gcc

src = main.c

bin = main

$(bin):

$(src)

$(cc) -o $@

$^.phony

: clean

clean:

rm $(

bin)

靜態鏈結

優點: **裝載速度快, 執行速度比動態鏈結庫略快, 不需要外部函式庫支援

缺點: 檔案體積大, **冗餘造成記憶體浪費, 靜態函式庫發生改變時程式必須重新編譯.

動態鏈結

優點: 檔案體積小, 節省記憶體空間, 公升級方便, 提高軟體可維護性和可擴充套件性.

缺點: 程式變成多個部分, 更容易出錯.

要製作成庫的函式編寫

fun.c

c code

int fun(int a, int b)

main.c

c code

#include 

#include

int main(int argc, char **argv)

靜態庫

製作靜態庫

ar -crs libfun.a fun.o

makefile code

cc = gcc

ar = ar

src_fun = fun.c

obj_fun = fun.o

lib_fun = libfun.a

src = main.c

bin = main

all:

$(obj_fun) $(

lib_fun) $(

bin)

$(obj_fun):

$(src_fun)

$(cc) -c -o $@

$^$(

lib_fun):

$(obj_fun)

$(ar) -crs $@

$^$(

bin):

$(src)

$(cc) -o $@

$^ -l. -lfun

.phony

: clean

clean:

rm $(

bin)

rm $(

obj_fun)

rm $(

lib_fun)

動態庫

製作動態庫

gcc -c -fpic -o fun.o fun.c

gcc -shared -o libfun.so fun.o

makefile code

cc = gcc

src_fun = fun.c

obj_fun = fun.o

lib_fun = libfun.so

src = main.c

bin = main

all:

$(obj_fun) $(

lib_fun) $(

bin)

$(obj_fun):

$(src_fun)

$(cc) -c -fpic -o $@

$^$(

lib_fun):

$(obj_fun)

$(cc) -shared -o $@

$^$(

bin):

$(src)

$(cc) -o $@

$^ -l. -lfun -wl,-rpath=.

.phony

: clean

clean:

rm $(

bin)

rm $(

obj_fun)

rm $(

lib_fun)

動態庫的鏈結方式還可以使用庫環境變數, 或者直接把庫放在系統的庫目錄中.

c語言執行時動態載入動態庫

需要鏈結dl庫

gcc -o main main.c -ldl

執行main程式

./main 3 4 ./libfun.so

c code

#include 

#include

#include

int main(int argc, char **argv)

fn = dlsym(lib_handle, "fun");

err = dlerror();

if (err)

int a = atoi(argv[1]);

int b = atoi(argv[2]);

int ans = fn(a, b);

printf("%d\n", ans);

dlclose(lib_handle);

return

0;}

使用ldd命令檢視二進位制程式所依賴的動態鏈結庫

鏈結 裝載與庫 2 編譯和鏈結

1 預處理 主要的處理規則如下 gcc e hello.c o hello.i e表示只進行預編譯2 編譯 將預處理完的檔案進行一系列的詞法分析 語法分析 語義分析和 優化。gcc s hello.c o hello.s 3 彙編 將彙編 轉換成機器碼 gcc c hello.s o hello.o...

鏈結 裝載與庫(2) 編譯和鏈結2 1

2.1 被隱藏了的過程 通常整合開發環境 ide 會將編譯和鏈結的過程一步完成,稱為構建 build 即時使用命令列來編譯乙個源 檔案,簡單地一句 gcc hello.c 命令實際上也包含了非常複雜的過程。乙個gcc過程可以分解為4個步驟,分別是預處理 prepressing 編譯 compilat...

編譯和鏈結

一般來說,無論是c c 首先要把原始檔編譯成中間 檔案,在windows下也就是 obj 檔案,unix下是 o 檔案,即 object file,這個動作叫做編譯 compile 然後再把大量的object file合成執行檔案,這個動作叫作鏈結 link 編譯時,編譯器需要的是語法的正確,函式與...