項目集成過程中的makefile記錄
文章目錄
- 項目集成過程中的makefile記錄
- 1.基礎概念
- 注釋
- 打印
- 賦值方式
- 常用變量
- @
- $
- 偽目標
- 函數
- wildcard
- 多目錄、文件操作
- 2.思路梳理
- **需求分析**
- 目錄結構
- 3.可行示例
持續更新中
1.基礎概念
注釋
#
示例:
# 項目名稱
打印
@echo "Hello, world! #僅打印信息echo "Hello, world! #打印命令和信息
賦值方式
=
使用 = 進行賦值時,變量的值是延遲展開的,即在使用變量時才進行展開計算。這意味著變量的值可以依賴于其他變量,也可能受后續賦值操作的影響。例如:SOURCES = $(wildcard src/*.c)
OBJS = $(SOURCES:.c=.o)
:=
:= 是 Makefile 中用于靜態變量賦值的一種方式,它具有立即展開和避免遞歸展開的特點,適合用于定義不依賴于其他變量的靜態值。
?=
使用 ?= 進行賦值時,如果變量之前未被賦過值(即為空),則進行賦值;如果變量已經有值,則不重新賦值。這種方式通常用于設置默認值,讓用戶可以在命令行或其他地方覆蓋默認值。例如:CC ?= gcc
+=
使用 += 可以向變量追加新的值,而不是覆蓋原有的值。這在需要動態追加值的情況下非常有用。例如:CFLAGS += -Wall -O2
常用變量
@
作用:
@ 符號通常用于控制命令的輸出
示例和講解:
print_message:@echo "Hello, world!
執行 make print_message 將只輸出 Hello, world!,而不會額外顯示命令本身。如果不帶 @ 符號,Make 工具將會輸出命令本身以及命令執行結果。print_message:echo "Hello, world!"
執行 make print_message 將輸出 echo "Hello, world!" 以及 Hello, world!。總之,@ 符號可以控制命令的輸出,讓你可以選擇是顯示命令本身還是只顯示命令執行結果。
$
1.變量引用:$ 后面跟著變量名可以引用該變量的值。
例如:$(CC)、$(CFLAGS)
例如:$(CC) -o output $(OBJS) 將會使用 CC 和 OBJS 的值來構建編譯命令。
2.命令替換:$() 或 ${} 用于執行命令替換,將命令的輸出結果賦給變量。例如:$(shell date '+%Y-%m-%d') 將會獲取當前日期并賦給變量。
3.特殊內建變量:$@ 表示規則中的目標文件名。
$^ 表示所有的依賴文件列表。
$< 表示規則中的第一個依賴文件名。
例如:$(CC) -o $@ $^ 表示將所有的依賴文件編譯鏈接生成目標文件。
偽目標
網上的一些介紹,可以增加理解:避免與同名文件沖突:有時候,當前目錄中可能會存在與 Makefile 中定義的目標同名的文件,如果這些目標不是偽目標,那么 Make 命令會誤以為這是一個文件依賴關系,從而導致錯誤。通過使用偽目標,可以避免這種沖突。明確指示任務:通過使用偽目標,你可以在 Makefile 中明確地定義一些任務,比如默認編譯任務、清理任務等,使得其他人閱讀代碼時更容易理解 Makefile 的意圖。確保每次執行:由于偽目標并不對應真實文件,因此無論是否存在同名文件,Make 命令都會執行偽目標定義的任務,這樣可以確保每次執行都能按照預期執行相應的命令。但記住下面這個就可以了:
當執行 make 命令時,Make 工具會按照規則執行 all 或 clean 相應的命令,而不會考慮是否存在同名文件
示例:
# 默認目標
all: $(TARGET)# 清理規則
clean:rm -rf $(BUILD_DIR) $(BIN_DIR).PHONY: all clean
函數
wildcard
原型:
$(wildcard pattern)pattern 是一個文件名模式,可以包含通配符 * 和 ?。wildcard 函數會將滿足模式的文件列表返回給調用者。
作用:
用于匹配文件名模式并返回匹配的文件列表
示例:
假設當前目錄下有以下文件:
src/main.c
src/util.c
include/header.h
我們可以使用 wildcard 函數來匹配以 .c 結尾的所有源文件:
SRC_FILES := $(wildcard src/*.c)
這將返回 src/main.c 和 src/util.c,并將其賦給 SRC_FILES 變量。wildcard 函數在 Makefile 中常用于收集源文件列表、頭文件列表等,以便在后續的編譯或構建過程中使用。
多目錄、文件操作
不同makefile文件相互調用
# 主Makefile文件sub_mk := ./src//ctrl/sub_ctrl.mk# 默認目標
all: @echo "building ..."@$(MAKE) -f $(sub_mk)
# 子Makefile文件.PHONY: SUB_CTRLSUB_CTRL:@echo "SUB_CTRL makefile test !!"
現象:
building ...
make[1]: 進入目錄“/home/psd/code_space/my_project_space/user_space/test/camera_usb/test”
SUB_CTRL makefile test !!
make[1]: 離開目錄“/home/psd/code_space/my_project_space/user_space/test/camera_usb/test”
2.思路梳理
需求分析
項目初期: 建立測試目錄進行模塊化的基礎功能使能那對于makefile的需求:1.對涉及到的.c源文件進行編譯;2.將編譯生成的中間文件以及目標文件存放到相應的目錄里面3.頂層目錄下執行make即可實現整個項目的編譯作用4.make clean 可以清除中間文件和已生成的目標文件其他拓展需求:1.
目錄結構
后續測試模塊內容寫完直接使用tree命令補充:# 源文件目錄
SRC_DIR := src# 頭文件目錄
INC_DIR := include# 目標文件目錄
BUILD_DIR := build# 可執行文件輸出目錄
BIN_DIR := bin# 源文件
SRCS := $(wildcard $(SRC_DIR)/**/*.c)# 目標文件
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)# 可執行文件
TARGET := $(BIN_DIR)/$(PROJECT_NAME)
3.可行示例
# 項目名稱
PROJECT_NAME := USB_CAMERA# 編譯器
CC := gcc# 編譯選項
CFLAGS := -Wall -Wextra -g# 源文件目錄
SRC_DIR := src# 頭文件目錄
INC_DIR := include# 目標文件目錄
BUILD_DIR := build# 可執行文件輸出目錄
BIN_DIR := bin# 源文件
SRCS := $(wildcard $(SRC_DIR)/**/*.c)# 目標文件
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)# 可執行文件
TARGET := $(BIN_DIR)/$(PROJECT_NAME)# 默認目標
all: $(TARGET)# 編譯目標
$(TARGET): $(OBJS) | $(BIN_DIR)$(CC) $(CFLAGS) $^ -o $@# 編譯規則
# 生成目標文件的規則
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
#創建目錄(如果不存在)@mkdir -p $(dir $@)$(CC) $(CFLAGS) -c $< -o $@# 創建目錄
$(BUILD_DIR):mkdir -p $@$(BIN_DIR):mkdir -p $@# 清理規則
clean:rm -rf $(BUILD_DIR) $(BIN_DIR).PHONY: all clean