Linux學習筆記——例說makefile 單個C檔案
0.前言
從學習C語言開始就慢慢開始接觸makefile,查閱了很多的makefile的資料但總感覺沒有真正掌握makefile,如果自己動手寫一個makefile總覺得非常吃力。所以特意藉助部落格總結makefile的相關知識,通過例子說明makefile的具體用法。
例說makefile分為以下幾個部分,更多內容請參考【例說makefile索引博文】
2.含有多個C檔案
3.需要包括標頭檔案路徑
4.增加巨集定義
5.增加系統共享庫
6.增加自定義共享庫
7.一個實際的例子
【程式碼倉庫】——makefile-example
程式碼倉庫位於bitbucket,可藉助TortoiseHg(GUI工具)克隆程式碼或者在網頁中直接下載zip包。
1.複習gcc指令
一個非常簡單的C檔案——test.c
【test.c】
#include <stdio.h>
int main(void)
{
int a = 3;
int b = 2;
printf("a=%d\n",a);
printf("b=%d\n",b);
return 0;
}
【最簡單方法】
gcc test.c -o test
最終生成可執行檔案test。
【執行test】
./test
【輸出結果】
a=3
b=5
【不正確的寫法】
請注意以下寫法並不正確。
gcc -c test.c -o test
【詳細步驟分解】編譯——連結
無論gcc指令的引數如何變化,從原始檔變為可執行檔案只需要兩步,第一步原始檔編譯為目標檔案,第二步從目標檔案連結為可執行檔案。在最簡單的指令——gcc test.c -o test中使用了一處GCC的隱含規則,所有編譯和連結這兩個關鍵步驟展現的不明顯。那麼下面通過指令讓“不明顯”變得“明顯”。
【1】由c檔案編譯為目標檔案
【寫法1】
gcc -c test.c -o test.o
【寫法2】——順序可以顛倒
gcc -o test.o -c test.c
【寫法3】——適當簡寫
可以適當簡寫,充分利用GCC的預設規則,*.o檔案由同名的*.c檔案編譯得到。
gcc -c test.c
【寫法4】——有點奇怪
還可以這樣寫,雖然看起來有點奇怪,但只執行結果卻是一樣的。makefile檔案似乎更喜歡這種方式。
gcc -c -o test.o test.c
【2】把目標檔案連結為可執行檔案
【寫法1】
gcc test.o -o test
【寫法2】——順序可以顛倒
順序可以顛倒,makefile檔案似乎更喜歡這種方式。
gcc -o test test.o
2.編寫makefile檔案
【makefile】
請替換其中的[tab],並以程式碼倉庫中的makefile檔案為主。
# 可執行檔案
TARGET = test
# 依賴目標
OBJS = test.o
# 指令編譯器和選項
CC=gcc
CFLAGS=-Wall -std=gnu99
$(TARGET):$(OBJS)
# @echo TARGET:$@
# @echo OBJECTS:$^
[tab]$(CC) -o $@ $^
clean:
[tab]rm -rf $(TARGET) $(OBJS)
【具體說明】
【1】TARGET=test test為最後可執行檔案,linux中的可執行檔案就是windows中的exe檔案
【2】OBJS = test.o test.o對應test.c,利用makefile的隱含規則,test.o由test.c編譯得到。 【3】CC=gcc 指定編譯器為gcc
【4】CFLAGS=-Wall -std=gnu99 使能所有警告,指定編譯器標準為gnu99
【5】 $(CC) -o $@ $^
$@和$^為自動化變數,$@指目標檔案,此處為可執行檔案test,$^指去除重複的依賴檔案,此處為test.o
$(CC) -o $@ $^ 最終變化為 gcc -o test test.o。gcc -o test test.o和【詳細步驟】連結部分的指令完全相同。那麼makefile和gcc指令便建立了聯絡。
可以通過@echo指令在makefile執行過程中列印自動化變數,通過這種方式除錯makefile加速錯誤修正。
【編譯】
make clean && make
先執行make clean再執行make生成可執行檔案
【控制檯輸出】
gcc -Wall -std=gnu99 -c -o test.o test.c
gcc -o test test.o
【分析】
若去除-Wall -std=gnu99,那麼以上兩句簡化為
gcc -c -o test.o test.c 和編譯過程方法【4】相同
gcc -o test test.o 和執行過程方法【2】相同
那麼makefile和gcc指令便建立了關係,理解起來也方便多了。
3.再完善一些
【makefile】
請替換其中的[tab],並以程式碼倉庫中的makefile檔案為主
# 可執行檔案
TARGET=test
# C檔案
SRCS = test.c
# 目標檔案
OBJS = $(SRCS:.c=.o)
# 指令編譯器和選項
CC=gcc
CFLAGS=-Wall -std=gnu99
$(TARGET):$(OBJS)
# @echo TARGET:$@
# @echo OBJECTS:$^
[tab]$(CC) -o $@ $^
clean:
[tab]rm -rf $(TARGET) $(OBJS)
%.o:%.c
[tab]$(CC) $(CFLAGS) -o $@ -c $<
【變化說明】
【1】OBJS = $(SRCS:.c=.o) 變數替換函式,把所有的*.c檔案替換為*.o檔案。該函式和
OBJS = $(patsubst %.c,%.o,$(SRCS))具有相同效果。
【2】$<為自動化變數,指第一個目標檔案,此處為test.c
替換變數和自動化變數之後:
test.o:test.c
[tab]gcc -Wall -std=gnu99 -o test.o -c test.c
4.總結
【1】gcc指令執行順序——先編譯目標檔案,後連結成可執行檔案
【2】自動化變數
$@ 當前規則的目標檔案
$< 第一個依賴檔案
$^ 去除重複的所有依賴檔案
相關文章
- Makefile學習筆記筆記
- C++學習筆記----讀寫檔案C++筆記
- Makefile例項學習
- Linux 學習筆記--檔案打包與解壓縮Linux筆記
- 4、Linux入門學習筆記 檔案操作命令Linux筆記
- Linux下的makefile編寫 ——陳皓《跟我一起寫Makefile》學習筆記(二)Linux筆記
- 嵌入式之Makefile學習筆記筆記
- 設計模式學習筆記——單例模式設計模式筆記單例
- C++學習隨筆——簡單的單例設計模式例項C++單例設計模式
- Linux學習筆記:rm刪除檔案和資料夾Linux筆記
- Linux 學習筆記--環境變數與檔案查詢Linux筆記變數
- Linux 學習筆記--目錄結構及檔案基本操作Linux筆記
- DVWA-檔案包含學習筆記筆記
- 學習筆記:robots.txt檔案筆記
- C語言例項解析精粹學習筆記——19C語言筆記
- Linux 學習筆記--使用者及檔案許可權管理Linux筆記
- Linux 學習筆記Linux筆記
- Java設計模式學習筆記(五) 單例模式Java設計模式筆記單例
- 忽略某些檔案 —— Git 學習筆記 05Git筆記
- Python學習筆記|Python之檔案操作Python筆記
- Python學習筆記|Python之特殊檔案Python筆記
- C/C++學習路線———學習筆記C++筆記
- C#學習筆記C#筆記
- VC++學習筆記---配置檔案(一) ini檔案和propritiesC++筆記
- Linux 學習筆記--程式Linux筆記
- python學習筆記:第8天 檔案操作Python筆記
- Android學習筆記之build.gradle檔案Android筆記UIGradle
- JVM學習筆記——Class類檔案解讀JVM筆記
- C/C++學習筆記:字串C++筆記字串
- Laravel 學習筆記一: 專案框架和配置檔案Laravel筆記框架
- c++筆記_標頭檔案C++筆記
- makefile檔案案例
- 說區塊鏈-學習筆記區塊鏈筆記
- C++學習筆記——003C++筆記
- C++學習筆記——001C++筆記
- C 語言學習筆記筆記
- C語言學習筆記C語言筆記
- c#學習筆記(一)C#筆記
- OI學習筆記(C++)筆記C++