#include int main()
為了編譯生成對應的可執行檔案,你可能會使用下面的命令:
$ cc -o hello hello.c
$ ./hello
hello, world!
但是,如果使用make
(前提是你的作業系統已經安裝了gcc
和gnu 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 clean
和make
的結果如下所示:
$ 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.o
和function.o
鏈結生成可執行檔案block
。同時bolck.o
和function.o
就是根據需要從bolck.c
和function.c
編譯生成,因為make
有如下內建規則:***.o
由同名的c原始檔
生成,因此不必寫多餘的bolck.o:bolck.c
和function.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
而且cflags
、cppflags
、ldflags
、target_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 ...