Makefile 快速入門指南

Makefile 快速入門指南

什么是Makefile?

Makefile 是一個自動化構建工具的配置文件,用于管理代碼編譯、測試和清理等任務。它通過定義規則(rules)來指定文件之間的依賴關系,當源文件改變時,只重新編譯受影響的部分,大大提高了開發效率。

比如你寫了個main.c,手動編譯要敲gcc main.c -o app,但項目大了文件多了,手動敲命令太麻煩 ——Makefile 能幫你一鍵搞定所有編譯步驟。

最簡單的Makefile

hello:echo "Hello, World!"

運行 make 會輸出 “Hello, World!”(注意:命令前必須是Tab,不是空格)

核心概念

1. 規則結構

每條規則包含三部分:

目標: 依賴文件命令
  • 目標:要生成的文件或任務名稱
  • 依賴:生成目標所需的文件
  • 命令:生成目標的Shell命令(必須用Tab縮進)

2. 基礎示例

# 編譯C程序
app: main.o utils.ogcc main.o utils.o -o appmain.o: main.cgcc -c main.cutils.o: utils.cgcc -c utils.cclean:rm -f *.o app

3. 使用變量

定義和使用變量讓Makefile更易維護,比如把編譯器和編譯選項等定義成變量:

CC = gcc
CFLAGS = -Wall -O2
TARGET = app
OBJS = main.o utils.o$(TARGET): $(OBJS)$(CC) $(CFLAGS) $^ -o $@%.o: %.c$(CC) $(CFLAGS) -c $< -o $@

常用變量類型(簡單理解版):
(1)VAR = 值:后續修改其他變量會影響它(遞歸展開)
例:A = 123,B = $(A),之后A = 456,則B會變成 456。
(2)VAR := 值:定義時就固定,后續修改不影響(直接展開)
例:A = 123,B := $(A),之后A = 456,B還是 123。
(3)VAR ?= 默認值:如果沒給 VAR 賦值,就用默認值(方便別人修改)

4. 常用自動化變量

這些特殊變量在命令中使用:

變量含義示例
$@當前目標文件名app
$<第一個依賴文件名main.c
$^所有依賴文件main.c utils.c
$?比目標新的依賴文件修改過的文件

5. 偽目標

聲明不生成文件的目標(如clean):

.PHONY: clean runclean:rm -f *.o $(TARGET)run:./$(TARGET)

為什么要聲明.PHONY?
防止目錄下有個叫clean的文件 —— 如果有,make clean會誤以為 “文件已存在,不用執行”,加了.PHONY就會強制執行命令。

常用場景模板

1. 基礎C項目

CC = gcc
CFLAGS = -Wall -g
TARGET = myapp
SRCS = main.c utils.c
OBJS = $(SRCS:.c=.o)$(TARGET): $(OBJS)$(CC) $(CFLAGS) $^ -o $@%.o: %.c$(CC) $(CFLAGS) -c $< -o $@clean:rm -f $(OBJS) $(TARGET).PHONY: clean

2. 多目錄項目

CC = gcc
CFLAGS = -Wall -Iinclude
TARGET = app
SRC_DIR = src
OBJ_DIR = objSRCS = $(wildcard $(SRC_DIR)/*.c)
OBJS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS))$(TARGET): $(OBJS)$(CC) $(CFLAGS) $^ -o $@$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)$(CC) $(CFLAGS) -c $< -o $@$(OBJ_DIR):mkdir -p $@clean:rm -rf $(OBJ_DIR) $(TARGET).PHONY: clean

3. 帶測試的任務

TARGET = app
TEST_TARGET = testbuild: $(TARGET)test: $(TEST_TARGET)./$(TEST_TARGET)$(TARGET): main.cgcc main.c -o $@$(TEST_TARGET): test.cgcc test.c -o $@clean:rm -f $(TARGET) $(TEST_TARGET).PHONY: build test clean

初學者技巧

  1. Tab是關鍵:命令前必須使用Tab縮進,空格會導致錯誤

    # 正確
    target:
    <Tab>command# 錯誤
    target:command  # 這里用了空格
    
  2. 使用變量:把編譯器、選項等定義為變量

    CC = gcc
    CFLAGS = -Wall -O2
    
  3. 通配符規則:使用%簡化相似規則

    %.o: %.c$(CC) $(CFLAGS) -c $< -o $@
    
  4. 偽目標聲明:為不生成文件的目標添加.PHONY

    .PHONY: clean all install
    
  5. 調試Makefile

    • make -n:顯示但不執行命令
    • make --debug:顯示詳細調試信息

常見錯誤解決

  1. “missing separator” 錯誤
    原因:命令前使用了空格而不是Tab
    解決:確保命令前是Tab字符

  2. “No rule to make target” 錯誤
    原因:依賴文件不存在
    解決:檢查文件名拼寫,或添加生成該文件的規則

  3. 命令不執行
    原因:存在同名文件且比依賴文件新
    解決:使用.PHONY聲明偽目標或make -B強制重建

  4. 頭文件修改不觸發重編譯
    解決:添加頭文件依賴

    main.o: main.c utils.h
    

完整示例

# ===========================================
# 簡單C項目Makefile示例(帶詳細注釋)
# ===========================================# 1. 編譯器配置
# --------------------------------
# 定義使用的C編譯器(默認為gcc)
CC = gcc# 編譯選項:
#   -Wall: 啟用所有警告
#   -g: 添加調試信息
CFLAGS = -Wall -g# 最終生成的可執行文件名
TARGET = calculator# 2. 源文件配置
# --------------------------------
# 列出所有源文件(.c文件)
SRCS = main.c math.c# 將源文件列表轉換為目標文件列表(.c替換為.o)
OBJS = $(SRCS:.c=.o)# 項目中的頭文件列表(用于依賴關系)
HEADERS = math.h# 3. 構建規則
# --------------------------------
# 主目標:生成可執行文件
# 依賴所有目標文件(OBJS)
$(TARGET): $(OBJS)# 鏈接所有目標文件生成可執行文件# $^ 表示所有依賴文件(這里是所有.o文件)# $@ 表示目標文件名(這里是$(TARGET))$(CC) $(CFLAGS) $^ -o $@# 通用規則:從.c文件生成.o文件
# % 是通配符,匹配任意文件名
# 依賴對應的.c文件和所有頭文件(HEADERS)
%.o: %.c $(HEADERS)# 編譯單個源文件生成目標文件# $< 表示第一個依賴文件(這里是.c文件)# $@ 表示目標文件名(這里是.o文件)$(CC) $(CFLAGS) -c $< -o $@# 4. 實用目標
# --------------------------------
# 清理生成的文件
clean:# 刪除所有目標文件和可執行文件rm -f $(OBJS) $(TARGET)# 運行程序(先構建再運行)
run: $(TARGET)# 運行生成的可執行文件./$(TARGET)# 5. 偽目標聲明
# --------------------------------
# 聲明不生成實際文件的目標
# 這確保即使有同名文件存在,這些目標也會執行
.PHONY: clean run# ===========================================
# 使用說明:
#   1. 保存為 "Makefile"(無擴展名)
#   2. 在終端執行:
#       make      # 編譯程序
#       make run  # 運行程序
#       make clean # 清理生成的文件
# ===========================================

使用步驟:

  1. 保存為 Makefile(無擴展名)
  2. 終端運行:
    make     # 編譯程序
    make run # 運行程序
    make clean # 清理文件
    

學習資源

  1. GNU Make手冊
  2. Makefile教程(中文):https://seisman.github.io/how-to-write-makefile/
  3. 交互式學習:https://makefiletutorial.com/

初學者建議:從簡單項目開始,先掌握基本規則和變量使用,再逐步學習高級特性。實踐是最好的學習方式!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91084.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91084.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91084.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux學習--C語言(指針4、結構體)

1.二維數組的傳參int a[2][3] {1, 2, 3, 4, 5, 6};fun(a,2); int fun(int (*p)[3], int len);2.指針數組的傳參char *pastr[5] {NULL};int fun(char **pstr,int len);例子&#xff1a;#include <stdio.h> #include <string.h>int InputArray(char (*p)[32], int …

【STM32】FreeRTOS 消息隊列(五)

在 FreeRTOS 中&#xff0c;任務消息隊列&#xff08;Message Queue&#xff09; 是一種非常關鍵的通信機制&#xff0c;用于在任務之間 傳遞數據、同步事件。 它是實現任務 解耦、異步通信 的核心工具之一&#xff0c;FreeRTOS 的消息隊列是任務之間通信的橋梁。 簡單點說&am…

【筆記】加速 uv 安裝:系統環境變量配置國內鏡像源

使用 Conda 工具鏈創建 UV 本地虛擬環境全記錄——基于《Python 多版本與開發環境治理架構設計》-CSDN博客 命令行創建 UV 環境及本地化實戰演示—— 基于《Python 多版本與開發環境治理架構設計》的最佳實踐-CSDN博客 加速 uv 包安裝&#xff1a;Windows 系統環境變量配置國內…

Three.js 渲染優化處理

基于項目經驗和最佳實踐&#xff0c;以下是渲染優化的具體處理方法&#xff1a; 1. 幾何體與材質優化 使用 BufferGeometry // 推薦&#xff1a;使用 BufferGeometry 替代 Geometry const geometry new THREE.BufferGeometry();合并幾何體 // 將多個幾何體合并為一個以減少繪制…

Kafka——Kafka控制器

引言在Kafka集群中&#xff0c;有一個組件堪稱"隱形的指揮官"——它默默協調著Broker的加入與退出&#xff0c;管理著主題的創建與刪除&#xff0c;掌控著分區領導者的選舉&#xff0c;它就是控制器&#xff08;Controller&#xff09;。想象一個擁有100臺Broker的大…

編程與數學 03-002 計算機網絡 11_域名系統(DNS)

編程與數學 03-002 計算機網絡 11_域名系統&#xff08;DNS&#xff09;一、DNS的作用與功能&#xff08;一&#xff09;域名與IP地址的映射關系&#xff08;二&#xff09;DNS的層次結構二、DNS查詢過程&#xff08;一&#xff09;遞歸查詢與迭代查詢&#xff08;二&#xff0…

影翎Antigravity將發布全球首款全景無人機,8月開啟公測招募

7月28日&#xff0c;消費級無人機品牌「影翎Antigravity」及品牌標識官宣亮相&#xff0c;計劃推出全新品類——全球首款「全景無人機」。這一消息引發行業震動&#xff0c;消費級航拍無人機市場或將迎來顛覆性飛行體驗。影翎Antigravity官方介紹&#xff0c;引力不僅是束縛雙腳…

SpringBoot集成Quzrtz實現定時任務

一 定時任務介紹 自律是很多人都想擁有的一種能力&#xff0c;或者說素質&#xff0c;但是理想往往很美好&#xff0c;現實卻是無比殘酷的。在現實生活中&#xff0c;我們很難做到自律&#xff0c;或者說做到持續自律。例如&#xff0c;我們經常會做各種學習計劃、儲蓄計劃或減…

Java中的異常判斷以及文件中的常用方法及功能

目錄 異常 作用 異常的處理方式 JVM&#xff08;虛擬機&#xff09;默認的處理方式 自己處理&#xff08;捕獲異常&#xff09; 拋出異常&#xff08;也就是交給調用者處理&#xff09; 自定義異常 file File中常見成員方法 判斷和獲取 創建和刪除 獲取并遍歷 異常…

【C++算法】74.優先級隊列_最后一塊石頭的重量

文章目錄題目鏈接&#xff1a;題目描述&#xff1a;解法C 算法代碼&#xff1a;題目鏈接&#xff1a; 1046. 最后一塊石頭的重量 題目描述&#xff1a; 解法 每次取出最重的兩塊石頭進行碰撞&#xff0c;將剩余的石頭重新放入堆中。 C 算法代碼&#xff1a; class Solution …

中興云電腦W101D2-晶晨S905L3A-2G+8G-安卓9-線刷固件包

中興云電腦W101D2-晶晨S905L3A-2G8G-WIFI-藍牙5.0-3個USB2.0-線刷包線刷方法&#xff1a;1、準備好一根雙公頭USB線刷刷機線&#xff0c;長度30-50CM長度最佳&#xff0c;同時準備一臺電腦&#xff1b;2、電腦上安裝好刷機工具Amlogic USB Burning Tool 軟件 →打開軟件 →文件…

Android OkHttp 底層原理和實戰完全教程(責任鏈模式詳解)

目錄 1. OkHttp 入門:從一個請求開始 1.1 基本 GET 請求:三步走 1.2 同步 vs 異步:選擇你的風格 1.3 為什么選 OkHttp? 2. 配置 OkHttpClient:打造你的專屬網絡引擎 2.1 超時設置:別讓請求卡死 2.2 添加攔截器:窺探請求全過程 2.3 緩存:讓請求更快更省流量 3. …

【RK3588部署yolo】算法篇

簡歷描述收集并制作軍事偽裝目標數據集&#xff0c;包含真實與偽裝各種類型軍事目標共計60余類。其中&#xff0c;包含最新戰場充氣偽裝軍事裝備30余類&#xff0c;并為每一張圖片制作了詳細的標注。針對軍事偽裝目標的特點&#xff0c;在YOLOv8的Backbone與Neck部分分別加…

【Spring Boot 快速入門】一、入門

目錄Spring Boot 簡介Web 入門Spring Boot 快速入門HTTP 協議概述請求協議響應協議解析協議TomcatSpring Boot 簡介 Spring Boot 是由 Pivotal 團隊&#xff08;后被 VMware 收購&#xff09;開發的基于 Spring 框架的開源項目&#xff0c;于 2014 年首次發布。其核心目標是簡…

如何調整服務器的內核參數?-哈爾濱云前沿

調整服務器內核參數是一項較為專業的操作&#xff0c;不同的操作系統調整方式略有不同&#xff0c;以下以常見的 Linux 系統為例&#xff0c;介紹一些調整服務器內核參數的一般步驟和常用參數&#xff1a;一般步驟 備份當前配置&#xff1a;在修改內核參數之前&#xff0c;先備…

C++基礎:模擬實現queue和stack。底層:適配器

引言模擬實現queue和stack&#xff0c;理解適配器&#xff0c;實現起來非常簡單。一、適配器 適配器是一種能讓原本不兼容的接口協同工作的設計模式或者組件。它的主要作用是對一個類的接口進行轉換&#xff0c;使其符合另一個類的期望接口&#xff0c;進而實現適配和復用。&am…

OI 雜題

OI 雜題字符串括號匹配例 1&#xff1a;與之前的類似&#xff0c;就是講一點技巧&#xff0c;但是比較亂&#xff0c;湊合著看吧。 字符串 括號匹配 幾何意義&#xff1a;考慮令 ( 為 111 變換&#xff0c;令 ) 為 ?1-1?1 變換&#xff0c;然后對這個 1/?11/-11/?1 構成…

【論文閱讀】Safety Alignment Should Be Made More Than Just a Few Tokens Deep

Safety Alignment Should Be Made More Than Just a Few Tokens Deep原文摘要問題提出現狀與漏洞&#xff1a;當前LLMs的安全對齊機制容易被攻破&#xff0c;即使是簡單的攻擊&#xff08;如對抗性后綴攻擊&#xff09;或良性的微調也可能導致模型越獄。核心論點&#xff1a; 作…

Generative AI in Game Development

如有侵權或其他問題&#xff0c;歡迎留言聯系更正或刪除。 出處&#xff1a;CHI 20241. 一段話總結本研究通過對來自 Reddit 和 Facebook 群組的 3,091 條獨立游戲開發者的在線帖子和評論進行定性分析&#xff0c;探討了他們對生成式 AI在游戲開發中多方面作用的認知與設想。研…

【C++算法】72.隊列+寬搜_二叉樹的最大寬度

文章目錄題目鏈接&#xff1a;題目描述&#xff1a;解法C 算法代碼&#xff1a;題目鏈接&#xff1a; 662. 二叉樹最大寬度 題目描述&#xff1a; 解法 這里的寬度指的是一層的最右邊的非空節點到一層的最左邊的非空節點&#xff0c;一共的節點數。 解法一&#xff1a;硬來&am…