C C 從零開始的Make教程

2021-08-01 17:31:41 字數 4183 閱讀 2771

#include int main()

為了編譯生成對應的可執行檔案,你可能會使用下面的命令:

$ cc -o hello hello.c

$ ./hello

hello, world!

但是,如果使用make(前提是你的作業系統已經安裝了gccgnu make),會顯得更清爽一些。

$ make hello

cc hello.c -o hello

$ ./hello

hello, world!

什麼?你連make hello都懶得寫?看完這部分,你的「妄念」應該就能實現了,到時候你只需要慢悠悠地打出4個字母——make,然後按下回車鍵,比圖形介面ide還要方便(至少你不用到處去找那個該死的執行按鈕在哪。

這時候你只要在hello.c的同乙個目錄下新建乙個檔案makefile作為make命令的配置檔案即可。它的內容很簡單:

hello:
什麼?你不想使用預設的cc,而想使用gcc來編譯程式?那還不簡單,只用在makefile檔案中把cc變數的值賦為gcc就可以了。

cc := gcc

hello:

如果你這時候想執行make試下效果,請注意:make根本就不會重新編譯生成hello。為什麼啊?因為make很「懶」,因為它檢測到hello.c和上一次編譯時一模一樣,再重新編譯生成的可執行檔案肯定也一樣啊,那就沒有執行的必要了,直接返回結果了。這時候可以用上些「小手段」,反正make很好騙。輸入下面的命令,更新下hello.c的最近修改日期。

$ touch hello.c
或者乾脆直接把hello檔案刪掉。但是刪檔案的方式也有高招和低招之分,如果你使用的是下面的命令:

$ rm -f hello
那麼這就是低招了,因為這很可能誤刪了其他很重要的原始檔,造成十分嚴重的後果。那麼高招是什麼呢?那就是在makefile中新增下面的內容:

clean:

$(rm) hello

執行方式也很簡單,執行make clean命令即可。

如果你想為gcc增加-g -wall -wextra選項,那麼只要設定變數cflags的值即可。

cc := gcc

cflags := -g -wall -wextra

hello:

clean:

$(rm) hello

這時候,執行make cleanmake的結果如下所示:

$ make clean

rm -f hello

$ make

gcc -g -wall -wextra hello.c -o hello

如果程式不再只有乙個原始檔,那麼結合make的內建編譯規則,也可以很簡潔地編寫makefile檔案完成編譯任務。下面是乙個簡單的例子:

ldlibs := -lncurses

block: block.o function.o

block.o function.o: function.h

clean:

$(rm) *.o

$(rm) block

其中程式需要用到ncurses,它是乙個字元終端下螢幕控制的基本庫,因此在編譯時需要在最後增加-lncurses選項。這時候,可能你已經發現了,其實編寫makefile主要內容就是編寫依賴關係,block: block.o function.o就是表示由block.ofunction.o鏈結生成可執行檔案block。同時bolck.ofunction.o就是根據需要從bolck.cfunction.c編譯生成,因為make有如下內建規則:***.o由同名的c原始檔生成,因此不必寫多餘的bolck.o:bolck.cfunction.o:function.c。執行結果如下

$ make

cc -c -o block.o block.c

cc -c -o function.o function.c

cc block.o function.o -lncurses -o block

輸入make -p命令,可以檢視所有的make的內建規則,比如上面提到的***.o由同名的c原始檔生成,在make -p的輸出結果中顯示如下:

%.o: %.c

# recipe to execute (內建):

$(compile.c) $(output_option) $<

其中,%為萬用字元,$(compile.c)是取compile.c這個變數的值,如果你好奇這個值到底是什麼,可以再繼續查詢,發現下面的語句

# 預設

compile.c = $(compile.cc)

在進一步找,得到:

# 預設

compile.cc = $(cxx) $(cxxflags) $(cppflags) $(target_arch) -c

上面的變數可以像之前的例項那樣重新賦值(預設為空),從而自定義編譯方式。

除了像$(compile.c)$(compile.cc)這樣形式的變數,make中還存在一類很常用、無比重要的變數——自動變數。

下面列出最常用的自動變數:

比如下面這條規則:

%: %.c

# commands to execute (built-in):

$(link.c) $^ $(loadlibes) $(ldlibs) -o $@

link.c的定義如下:

link.c = $(cc) $(cflags) $(cppflags) $(ldflags) $(target_arch)
cc的定義如下:

cc = cc
而且cflagscppflagsldflagstarget_arch預設都為空。

最後原來的規則等同於:

%: %.c

cc $^ -o $@

hello:
就可得到最終的編譯命令:

cc hello.c   -o hello
所以,參考make -p命令輸出的make內建規則,編寫自己程式的makefile是個不錯的程式設計習慣和學習如何熟練使用make的途徑。

C C 從零開始的cmake教程

通過編寫cmakelists.txt,然後執行cmake命令可以自動生成對應makefile,從而控制make的編譯過程。因此在學習cmake之前,建議先對make有個大致的了解。歡迎閱讀本人編寫的另一篇部落格 c c 從零開始的make教程 如果你的專案只有乙個原始檔main.cpp,那麼只需要在...

C C 從零開始的cmake教程

本文 通過編寫cmakelists.txt,然後執行cmake命令可以自動生成對應makefile,從而控制make的編譯過程。因此在學習cmake之前,建議先對make有個大致的了解。歡迎閱讀本人編寫的另一篇部落格 c c 從零開始的make教程 1.單個原始檔的編譯 如果你的專案只有乙個原始檔m...

從零開始學習OpenWrt完美教程

1.2.切記不要改動軟體源,同時按住ctrl alt t,調出終端 3.逐條輸入下列命令 及時驗證是否安裝成功 4.sudo apt get install g sudo apt get install libncurses5 dev sudo apt get install zlib1g dev ...