電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 82|回復(fù): 0
收起左側(cè)

不懂 Makefile 的程序員還敢寫代碼嗎?

[復(fù)制鏈接]

317

主題

317

帖子

3149

積分

四級(jí)會(huì)員

Rank: 4

積分
3149
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-12-6 10:34:00 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
前言:編譯命令敲累了?是時(shí)候?qū)W點(diǎn)自動(dòng)化了!每次編譯項(xiàng)目是不是手動(dòng)敲gcc 命令? 當(dāng)項(xiàng)目文件一多,命令就像繞口令一樣——又長(zhǎng)又復(fù)雜,還特別容易出錯(cuò)。
別怕,今天我就帶你認(rèn)識(shí)一個(gè)“懶人神器”——Makefile。
用 Makefile 的好處很簡(jiǎn)單:
  • 代碼編譯自動(dòng)化,輕松又高效;
  • 不用手動(dòng)敲命令,少掉坑;
  • 項(xiàng)目多大都不怕,它全能搞定。只要學(xué)會(huì)寫 Makefile,編譯這種枯燥的事情,再也不用你操心!讓我們從零開始,一步步帶你搞清楚它是啥、怎么寫,看完就能用!
    1、什么是 Makefile?Makefile 就是一個(gè)編譯指揮官,你把編譯規(guī)則寫在里面,之后用一條簡(jiǎn)單的命令make,它就會(huì)按照規(guī)則自動(dòng)完成所有的編譯任務(wù)。
    打個(gè)比方,你是項(xiàng)目經(jīng)理,Makefile 就是你的筆記本,記錄著項(xiàng)目的“施工計(jì)劃”:
  • 每個(gè)目標(biāo)(比如可執(zhí)行文件main)的來源(哪些源文件);
  • 這些目標(biāo)要用什么命令生成;
  • 有哪些需要重復(fù)利用的部分(比如中間文件*.o)。一句話:Makefile 幫你自動(dòng)化處理那些又多又煩的編譯流程!
    2、為什么用 Makefile?假設(shè)你有兩個(gè)源文件:main.c 和utils.c,手動(dòng)編譯步驟大概是這樣:
  • 先把main.c 和utils.c 分別編譯成目標(biāo)文件:[/ol]gcc -c main.c -o main.o
    gcc -c utils.c -o utils.o 2. 再把目標(biāo)文件鏈接成可執(zhí)行文件:gcc main.o utils.o -o main
    看著簡(jiǎn)單,但代碼一多,命令就會(huì)變成這樣:
    gcc -c file1.c -o file1.o
    gcc -c file2.c -o file2.o
    gcc -c file3.c -o file3.o
    ...
    gcc file1.o file2.o file3.o -o my_program
    多打一條命令,多一個(gè)機(jī)會(huì)掉坑;一改代碼,又得全編譯一遍,時(shí)間都浪費(fèi)了。
    用 Makefile,只需要:
    make
    一條命令,全搞定!而且它還會(huì)只編譯改動(dòng)的文件,效率直接起飛。
    簡(jiǎn)單理解:
  • 沒有 Makefile:自己手敲命令,累。
  • 有了 Makefile:只用一句make,剩下的事全自動(dòng)完成,爽。3、Makefile 的基本結(jié)構(gòu) (一分鐘搞懂)Makefile 是由一組規(guī)則(rule)組成的,每個(gè)規(guī)則都包含三部分:
  • 目標(biāo)(target):你想要生成的文件,比如main。
  • 依賴(dependencies):目標(biāo)文件需要哪些源文件或頭文件。
  • 命令(commands):生成目標(biāo)需要運(yùn)行的命令。[/ol]舉個(gè)例子:
    main: main.o utils.o
    gcc main.o utils.o -o main
      
    main.o: main.c
        gcc -c main.c
    utils.o: utils.c
        gcc -c utils.c
    什么意思呢?
    上面總共 3 條規(guī)則,來說說第一條規(guī)則:
  • 目標(biāo)是main,表示我們要生成一個(gè)叫main 的可執(zhí)行文件。
  • 依賴是main.o 和utils.o,也就是說生成main 需要這兩個(gè)依賴文件先生成,而這兩個(gè)依賴是利用規(guī)則 2 和 規(guī)則 3 生成的。
  • 命令是gcc main.o utils.o -o main,它負(fù)責(zé)把.o 文件編譯成最終的可執(zhí)行文件。[/ol]后兩條規(guī)則類似,告訴make 怎么生成main.o 和utils.o。
    簡(jiǎn)單嗎?這就相當(dāng)于告訴 Makefile:“你要先準(zhǔn)備好main.o 和utils.o,然后用 gcc 鏈接它們!
    4、Makefile 基礎(chǔ)功能:讓編譯自動(dòng)化從這里開始4.1 自動(dòng)生成目標(biāo)文件如果你每次都向上面一樣手寫main.o、utils.o 的生成規(guī)則,那 Makefile 就會(huì)變得非常繁瑣和重復(fù)。好消息是,Makefile 支持通配符,可以自動(dòng)生成規(guī)則!
    %.o: %.c
    gcc -c $ -o $@
    這段代碼怎么用?假設(shè)你有main.c 和utils.c,Makefile 會(huì)自動(dòng)生成對(duì)應(yīng)的規(guī)則:
  • main.o:由main.c 生成,命令是gcc -c main.c -o main.o;
  • utils.o:由utils.c 生成,命令是gcc -c utils.c -o utils.o。解釋一下符號(hào):
  • %.o 和%.c:% 是通配符,表示文件名匹配,比如main.o 和main.c。
  • $:依賴文件,比如main.c。
  • $@:目標(biāo)文件,比如main.o。用這個(gè)規(guī)則,Makefile 直接幫你生成所有目標(biāo)文件,舒服吧?
    而當(dāng)項(xiàng)目文件越多,使用 Makefile 的優(yōu)勢(shì)就越大。
    4.2 增量編譯:只編譯改動(dòng)的文件Makefile 有個(gè)超棒的功能:只編譯需要更新的文件
    它會(huì)檢查每個(gè)目標(biāo)的依賴文件,如果依賴文件沒有變化,就跳過編譯。
    比如你改了main.c,Makefile 只會(huì)重新生成main.o,而utils.o 完全不動(dòng)。
    這個(gè)功能在項(xiàng)目文件很多的時(shí)候,能節(jié)省一大堆時(shí)間。
    4.3 清理臨時(shí)文件編譯后,會(huì)留下很多.o 文件和中間文件。Makefile 可以加一個(gè)clean 規(guī)則,幫你一鍵清理:
    clean:
    rm -f *.o main
    直接運(yùn)行make clean,干凈清爽!
    5、Makefile 的進(jìn)階玩法了解了基本用法后,咱們來看一些能提升開發(fā)效率的進(jìn)階功能。
    5.1 基礎(chǔ)玩法 - 提高可讀性和可維護(hù)性1. 使用變量:讓 Makefile 更加簡(jiǎn)潔變量怎么使用?比如CC = gcc。變量可以讓 Makefile 更加靈活和易維護(hù)。
    變量的基本用法:
    # 定義變量
    CC = gcc
    CFLAGS = -Wall -g
    TARGET = main
    SRCS = main.c utils.c
    OBJS = $(SRCS:.c=.o)
    # $(SRCS:.c=.o) 是 Makefile 中的一種變量替換,它的作用是把變量 SRCS 中的每個(gè) .c 文件名換成對(duì)應(yīng)的 .o 文件名。
    # 替換之后 OBJS = main.o utils.o
    在命令中使用變量時(shí),需要用$() 的形式引用:
    $(TARGET): $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $(TARGET)
       
    # 使用$()替換變量之后的規(guī)則如下:   
    main: main.o utils.o
    gcc -Wall -g main.o utils.o -o main
    這樣,如果你要修改編譯器或優(yōu)化選項(xiàng),只需要改動(dòng)變量部分,而不需要手動(dòng)修改每條規(guī)則。
    2、偽目標(biāo):讓 Makefile 更靈活在 Makefile 中,有些目標(biāo)(比如clean)不會(huì)生成文件,而是用來執(zhí)行特定的命令,比如清理臨時(shí)文件。這種目標(biāo)我們稱為 偽目標(biāo)。
    問題來了:如果目錄中剛好有個(gè)文件名就叫clean,運(yùn)行make clean 時(shí),Makefile 會(huì)誤以為這個(gè)文件已經(jīng)存在,導(dǎo)致規(guī)則不執(zhí)行。
    怎么解決?
    用.PHONY 聲明偽目標(biāo),告訴make 這個(gè)目標(biāo)不是文件,應(yīng)該直接執(zhí)行命令。
    示例:聲明偽目標(biāo)
    .PHONY: clean
    clean:
    rm -f $(OBJS) $(TARGET)
    這樣,即使目錄中有個(gè)名為clean 的文件,make clean 仍然會(huì)按規(guī)則執(zhí)行,刪除目標(biāo)文件和中間文件。
    記。悍彩遣簧晌募哪繕(biāo),都建議用.PHONY 聲明!
    5.2  進(jìn)階玩法 - 構(gòu)建更強(qiáng)大的 Makefile1、模式規(guī)則:適配更多文件類型有時(shí)候我們的項(xiàng)目里,不只有.c 文件,還有.cpp 文件。如果要分別寫規(guī)則,那就太麻煩了!這時(shí)候,模式規(guī)則 就能幫上大忙。
    什么是模式規(guī)則?
    模式規(guī)則就是一種通用規(guī)則,用來告訴 Makefile:
    “遇到這種類型的文件,該怎么處理!
    比如,告訴 Makefile:
  • .c 文件用gcc 編譯;
  • .cpp 文件用g++ 編譯。這樣,Makefile 會(huì)根據(jù)文件后綴自動(dòng)選擇正確的規(guī)則,不用你手動(dòng)一個(gè)一個(gè)寫。
    怎么用?支持 C++ 文件
    假設(shè)項(xiàng)目里有.cpp 文件,我們可以加一個(gè)模式規(guī)則:
    %.o: %.cpp
    g++ -c $ -o $@
    這樣,Makefile 會(huì)自動(dòng)把所有.cpp 文件編譯成.o 文件,完全不用你操心。
    如何同時(shí)支持 C 和 C++ 文件?
    如果項(xiàng)目里既有.c 文件,也有.cpp 文件,那我們可以寫兩條規(guī)則:
    %.o: %.c
    $(CC) $(CFLAGS) -c $ -o $@
    %.o: %.cpp
    g++ -c $ -o $@
    這兩條規(guī)則的作用:
  • 第一條:告訴 Makefile,.c 文件用gcc 編譯。
  • 第二條:告訴 Makefile,.cpp 文件用g++ 編譯。[/ol]這樣,不管你的文件是.c 還是.cpp,Makefile 都會(huì)自動(dòng)搞定。
    總結(jié)一下:
  • 它會(huì)根據(jù)文件類型,自動(dòng)選擇合適的編譯方式;
  • 你只需要寫一條規(guī)則,Makefile 就能幫你搞定一大堆文件;
  • 再也不用重復(fù)寫規(guī)則了,省事又高效!記。何募缶Y不同?用模式規(guī)則全搞定!
    2、條件語(yǔ)句:讓 Makefile 更聰明條件語(yǔ)句可以讓 Makefile 根據(jù)實(shí)際情況調(diào)整規(guī)則,比如不同的操作系統(tǒng)、不同的編譯模式,用起來既靈活又省心。
    1、適配不同平臺(tái)
    不同操作系統(tǒng)的命令可能不一樣,比如刪除文件,Linux 用rm,Windows 用del。通過條件語(yǔ)句,Makefile 可以自動(dòng)選擇正確的命令:
    OS = $(shell uname)
    ifeq ($(OS), Linux)
    CLEAN_CMD = rm -f
    else
    CLEAN_CMD = del
    endif
    clean:
    $(CLEAN_CMD) *.o $(TARGET)
  • 在 Linux 上運(yùn)行make clean:執(zhí)行rm -f;
  • 在 Windows 上運(yùn)行make clean:執(zhí)行del。這樣,無論在哪個(gè)平臺(tái)都不用手動(dòng)改命令了,省事!
    2、切換編譯模式
    開發(fā)過程中經(jīng)常需要在調(diào)試模式(debug)和發(fā)布模式(release)之間切換:
  • 調(diào)試模式:包含調(diào)試信息(方便排查問題)。
  • 發(fā)布模式:優(yōu)化性能(適合生產(chǎn)環(huán)境)。用條件語(yǔ)句很容易實(shí)現(xiàn):
    ifeq ($(MODE), debug)
    CFLAGS = -g -O0
    else
    CFLAGS = -O2
    endif
    all:
    $(CC) $(CFLAGS) -o $(TARGET) $(SRCS)
  • 運(yùn)行調(diào)試模式:make MODE=debug
    用-g 和-O0 編譯,生成帶調(diào)試信息的程序。
  • 運(yùn)行發(fā)布模式:make
    或:
    make MODE=release
    用-O2 編譯,生成優(yōu)化后的高性能程序。
    小結(jié)一下
  • 適配不同平臺(tái): 條件語(yǔ)句讓 Makefile 在 Linux 和 Windows 上都能用。
  • 切換編譯模式: 方便開發(fā)階段調(diào)試和生產(chǎn)環(huán)境優(yōu)化。3、自動(dòng)化依賴管理: 讓 Makefile 更聰明!在寫代碼時(shí),.c 文件往往會(huì)用到頭文件.h。比如,你的main.c 里可能有一句:
    #include "utils.h"
    如果有一天你修改了utils.h,Makefile 怎么知道它需要重新編譯main.c 呢?
    靠你手動(dòng)寫依賴規(guī)則?別開玩笑了,項(xiàng)目文件一多,光靠手動(dòng)寫依賴會(huì)把人累趴。
    這時(shí)候,自動(dòng)化依賴管理就派上用場(chǎng)了。
    什么是自動(dòng)化依賴管理?
  • 自動(dòng)化依賴管理的核心是用gcc -M 命令,它能幫你自動(dòng)生成.c 文件和.h 文件的依賴關(guān)系。每次你修改頭文件時(shí),Makefile 會(huì)自動(dòng)觸發(fā)相關(guān)的.c 文件重新編譯。代碼怎么寫?
    看下面這個(gè) Makefile 示例:
    # 定義依賴文件列表
    DEPS = $(SRCS:.c=.d)
    # 生成 .d 文件,寫入依賴規(guī)則
    %.d: %.c
    $(CC) -M $ > $@
    # 包含依賴文件
    include $(DEPS)
    它到底做了什么?
  • 定義依賴文件[/ol]DEPS = $(SRCS:.c=.d)
    把源文件列表SRCS 中的每個(gè).c 文件,替換成對(duì)應(yīng)的.d 文件,比如:
  • main.c →main.d
  • utils.c →utils.d這些.d 文件就是用來記錄.c 和.h 之間的關(guān)系。
    2. 自動(dòng)生成依賴規(guī)則
    %.d: %.c
    $(CC) -M $ > $@
    這條規(guī)則會(huì)用gcc -M 為每個(gè).c 文件生成一個(gè).d 文件,里面記錄了它依賴哪些頭文件。
    比如,如果你的main.c 包含了utils.h,生成的main.d 文件可能是這樣的:
    main.o: main.c utils.h3. 包含依賴規(guī)則include $(DEPS)
    這句話告訴 Makefile,把所有.d 文件里的內(nèi)容加載進(jìn)來。每次運(yùn)行 Makefile 時(shí),它都會(huì)檢查.d 文件里的規(guī)則,看哪些文件需要重新編譯。
    效果如何?
    假設(shè)你有以下文件:
  • main.c 依賴utils.h;
  • utils.c 不依賴任何頭文件。如果你修改了utils.h,Makefile 會(huì)自動(dòng)發(fā)現(xiàn)這個(gè)改動(dòng),然后只重新編譯main.c,而不會(huì)動(dòng)utils.c。
    自動(dòng)化依賴管理的好處:
  • 再也不用手動(dòng)寫依賴規(guī)則,讓 Makefile 更智能;
  • 每次頭文件更新時(shí),Makefile 自動(dòng)判斷哪些文件需要重新編譯;
  • 即使項(xiàng)目文件多到爆,也能輕松應(yīng)對(duì)。[/ol]簡(jiǎn)單記住:“有.h 文件,就用gcc -M 自動(dòng)生成依賴!”
    4、多目標(biāo)支持:用 Makefile 管理多個(gè)模塊當(dāng)你的項(xiàng)目文件越來越多,甚至分成了多個(gè)模塊,比如lib 是核心功能模塊,app 是主程序模塊,光靠一個(gè) Makefile 已經(jīng)很難搞定了。
    這時(shí)候,聰明的做法是:
  • 每個(gè)模塊有自己的 Makefile,單獨(dú)管理自己的規(guī)則;
  • 用一個(gè)主 Makefile 調(diào)度所有模塊,讓項(xiàng)目更清晰、更高效!分模塊的做法:
    1. 給每個(gè)模塊單獨(dú)寫一個(gè) Makefile
    比如,在lib 模塊的目錄下,我們寫一個(gè)lib/Makefile:
    # lib/Makefile
    lib.a: lib.o               # 定義目標(biāo) lib.a
    ar rcs lib.a lib.o       # 把 lib.o 打包成靜態(tài)庫(kù) lib.a
    lib.o: lib.c               # 編譯規(guī)則:生成 lib.o
    gcc -c lib.c -o lib.o
  • lib.a 是靜態(tài)庫(kù),ar rcs 是打包命令。
  • 這個(gè) Makefile 只關(guān)心lib 模塊自己的文件,不影響其他模塊。2. 用主 Makefile 調(diào)度所有模塊
    主 Makefile 位于項(xiàng)目根目錄,負(fù)責(zé)把所有模塊串起來。它并不關(guān)心每個(gè)模塊的具體規(guī)則,而是遞歸調(diào)用每個(gè)模塊自己的 Makefile:
    # 主 Makefile
    SUBDIRS = lib app          # 定義模塊目錄
    all: $(SUBDIRS)            # 主目標(biāo):編譯所有模塊
    $(SUBDIRS):                # 遞歸調(diào)用每個(gè)模塊的 Makefile
    $(MAKE) -C $@
    clean:                     # 清理所有模塊
    for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done
    代碼解釋:
    1. SUBDIR 是模塊列表:這里定義了項(xiàng)目中的模塊,比如lib 和app。每個(gè)模塊目錄都有自己的 Makefile。
    2. $(MAKE) -C $@  是關(guān)鍵:這條命令的意思是切換到指定目錄(-C),然后運(yùn)行這個(gè)目錄里的 Makefile。比如,$(MAKE) -C lib 就是到lib 目錄運(yùn)行它的 Makefile。
    [/ol]3. 遞歸清理 :  clean 目標(biāo)會(huì)循環(huán)進(jìn)入每個(gè)模塊目錄,調(diào)用它們的clean 規(guī)則。注意$$dir 中的雙$,是為了讓 Makefile 能正確解析。
    整體效果:
  • 你可以在主目錄運(yùn)行make,它會(huì)自動(dòng)編譯所有模塊;
  • 運(yùn)行make clean 時(shí),它會(huì)遞歸清理所有模塊的臨時(shí)文件;
  • 每個(gè)模塊的規(guī)則獨(dú)立,清晰又方便維護(hù)。用主 Makefile 調(diào)度多個(gè)模塊的好處:
  • 結(jié)構(gòu)清晰:每個(gè)模塊的規(guī)則獨(dú)立管理,主 Makefile 只負(fù)責(zé)調(diào)度。
  • 易于維護(hù):修改或新增模塊時(shí),只需在SUBDIRS 添加對(duì)應(yīng)模塊目錄即可。
  • 高效遞歸:通過$(MAKE) -C 調(diào)用子目錄的 Makefile,模塊間互不干擾。[/ol]簡(jiǎn)單來說:分模塊管理,用主 Makefile 調(diào)度,一切井井有條!
    5.3 高階玩法 - 優(yōu)化效率與靈活性1. 并行編譯:提高效率Makefile 的make 命令支持并行執(zhí)行多個(gè)規(guī)則,用-j 參數(shù)指定并行任務(wù)數(shù)。
    示例:并行編譯
    make -j4
    這會(huì)同時(shí)運(yùn)行最多 4 個(gè)任務(wù),充分利用多核 CPU,顯著提升大項(xiàng)目的編譯速度。
    2. 自定義函數(shù):復(fù)用邏輯在寫 Makefile 時(shí),如果規(guī)則中有重復(fù)的編譯邏輯,比如把.c 文件編譯成.o 文件,一直重復(fù)寫$(CC) $(CFLAGS) 就很麻煩。這時(shí)候,我們可以用自定義函數(shù)來統(tǒng)一管理這些重復(fù)操作,既方便又省事!
    定義函數(shù):
    用define 和endef 定義一個(gè)編譯函數(shù):
    define compile
    $(CC) $(CFLAGS) -c $ -o $@
    endef
  • compile 是函數(shù)名,表示編譯的邏輯;
  • $ 是依賴文件(比如main.c),$@ 是目標(biāo)文件(比如main.o)。使用函數(shù):
    調(diào)用自定義函數(shù)時(shí),用$(call 函數(shù)名):
    %.o: %.c
    $(call compile)
    這條規(guī)則會(huì)自動(dòng)把.c 文件編譯成對(duì)應(yīng)的.o 文件。
    小結(jié)一下:
  • 自定義函數(shù)減少了重復(fù)代碼;
  • 修改邏輯時(shí),只需改函數(shù)定義,其他地方不用動(dòng);
  • 讓 Makefile 簡(jiǎn)潔易讀,清晰高效。[/ol]一句話:把重復(fù)的邏輯封裝成函數(shù),Makefile 也能優(yōu)雅起來!
    3. 靜態(tài)模式規(guī)則:批量生成目標(biāo)文件當(dāng)多個(gè)文件需要用相似的規(guī)則編譯時(shí),一個(gè)個(gè)寫太麻煩,用靜態(tài)模式規(guī)則 就能一次性搞定!
    先來看個(gè)簡(jiǎn)單示例: 假設(shè)我們要把多個(gè).c 文件編譯成.o 文件:
    OBJS = main.o utils.o io.o
    $(OBJS): %.o: %.c
    $(CC) $(CFLAGS) -c $ -o $@
    這是什么意思?
  • $(OBJS) 是目標(biāo)文件列表,比如main.o、utils.o;
  • %.o: %.c 說明每個(gè).o 文件由對(duì)應(yīng)的.c 文件生成;
  • $ 是源文件(如main.c),$@ 是目標(biāo)文件(如main.o)。優(yōu)點(diǎn):
  • 減少重復(fù):一條規(guī)則批量處理,省時(shí)省力;
  • 自動(dòng)匹配:文件名自動(dòng)對(duì)應(yīng),無需手動(dòng)寫每條規(guī)則。[/ol]這里順便提下 通配模式規(guī)則,這兩種模式用法很相似。
    對(duì)于更簡(jiǎn)單的項(xiàng)目,你可以用通配模式規(guī)則來實(shí)現(xiàn)類似效果:
    %.o: %.c
    $(CC) $(CFLAGS) -c $ -o $@
    解釋一下:
  • 每個(gè).o 文件由對(duì)應(yīng)的.c 文件生成;
  • 通配符% 會(huì)匹配任意文件名,比如main.c 自動(dòng)對(duì)應(yīng)main.o。靜態(tài)模式規(guī)則 vs. 通配模式規(guī)則
    特性靜態(tài)模式規(guī)則通配模式規(guī)則匹配范圍針對(duì)特定目標(biāo)列表(如$(OBJS)
    )自動(dòng)匹配所有符合%
    的文件靈活性控制更精確,只處理指定的目標(biāo)文件簡(jiǎn)單統(tǒng)一,適合全局規(guī)則適用場(chǎng)景文件多、規(guī)則復(fù)雜,特定文件需要特殊處理文件少、規(guī)則統(tǒng)一,簡(jiǎn)單項(xiàng)目總結(jié):
  • 通配模式規(guī)則適合簡(jiǎn)單項(xiàng)目,一條規(guī)則處理所有文件;
  • 靜態(tài)模式規(guī)則適合復(fù)雜項(xiàng)目,可以精確控制哪些文件應(yīng)用規(guī)則。記。汉(jiǎn)單全局用通配,精準(zhǔn)處理選靜態(tài)!
    4. 跨平臺(tái)構(gòu)建:用 CMake 生成 Makefile如果項(xiàng)目需要在多個(gè)平臺(tái)(如 Windows、Linux、macOS)上編譯,直接寫 Makefile 會(huì)很麻煩。這時(shí),可以用 CMake 自動(dòng)生成適配不同平臺(tái)的 Makefile。
    使用方法:
    1. 創(chuàng)建 CMake 配置文件
    在項(xiàng)目目錄下新建CMakeLists.txt,內(nèi)容如下:
  • # 聲明最低版本要求cmake_minimum_required(VERSION 3.10)
    # 定義項(xiàng)目名稱project(MyProject)
    # 指定可執(zhí)行文件add_executable(main main.c utils.c)2. 生成 Makefile
    在終端運(yùn)行:
    cmake .
    3. 編譯項(xiàng)目
    使用生成的 Makefile:
    make
    優(yōu)點(diǎn):
  • 跨平臺(tái):適配 Windows、Linux、macOS 等操作系統(tǒng);
  • 簡(jiǎn)化管理:無需手寫復(fù)雜的 Makefile。一句話總結(jié):用 CMake 自動(dòng)生成 Makefile,跨平臺(tái)編譯就是這么簡(jiǎn)單!
    五、完整示例結(jié)合前面學(xué)到的內(nèi)容,來看看一個(gè)完整的 Makefile:
    # 定義變量
    CC = gcc                     # 編譯器
    CFLAGS = -Wall -g            # 編譯參數(shù):開啟所有警告和調(diào)試信息
    SRCS =  $(wildcard *.c)      # 獲取當(dāng)前目錄下所有的 .c 文件,并賦值給 SRCS 變量,例如:SRCS = main.c utils.c
    OBJS = $(SRCS:.c=.o)         # 把 .c 文件替換成 .o 文件,替換之后,OBJS = main.o utils.o
    TARGET = main                # 最終生成的可執(zhí)行文件
    # 編譯規(guī)則
    $(TARGET): $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $(TARGET)
    # 生成 .o 文件規(guī)則
    %.o: %.c
    $(CC) $(CFLAGS) -c $ -o $@
    # 加上 .PHONY 聲明偽目標(biāo)
    .PHONY: clean
    clean:
    rm -f $(OBJS) $(TARGET)
    使用:
  • make:生成 可執(zhí)行文件main;
  • make clean:會(huì)刪除所有.o 文件和可執(zhí)行文件main,保持項(xiàng)目目錄干凈。看了這篇文章,相信你看上面的 Makefile 代碼 應(yīng)該很輕松!六、寫在最后:從 Makefile 開始,走向編譯自動(dòng)化!Makefile 就是編譯中的“懶人神器”,一旦用上,你會(huì)發(fā)現(xiàn):
  • 不再手動(dòng)敲命令,編譯變得更簡(jiǎn)單;
  • 即使項(xiàng)目越來越大,管理起來也毫不費(fèi)力;
  • 提高效率,節(jié)省時(shí)間,輕松搞定復(fù)雜編譯!如果你還在手動(dòng)敲命令,趕緊試試寫個(gè) Makefile,體驗(yàn)一下自動(dòng)化的快樂吧~
    下篇文章我們將帶你進(jìn)入 CMake 的世界,了解如何跨平臺(tái)管理項(xiàng)目,敬請(qǐng)期待!
    end

    一口Linux

    關(guān)注,回復(fù)【1024】海量Linux資料贈(zèng)送
    精彩文章合集
    文章推薦
    ?【專輯】ARM?【專輯】粉絲問答?【專輯】所有原創(chuàng)?【專輯】linux入門?【專輯】計(jì)算機(jī)網(wǎng)絡(luò)?【專輯】Linux驅(qū)動(dòng)?【干貨】嵌入式驅(qū)動(dòng)工程師學(xué)習(xí)路線?【干貨】Linux嵌入式所有知識(shí)點(diǎn)-思維導(dǎo)圖
  • 發(fā)表回復(fù)

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表