惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
Blog — PlanetScale
Blog — PlanetScale
H
Help Net Security
The GitHub Blog
The GitHub Blog
博客园 - Franky
酷 壳 – CoolShell
酷 壳 – CoolShell
Recent Announcements
Recent Announcements
量子位
aimingoo的专栏
aimingoo的专栏
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
Microsoft Azure Blog
Microsoft Azure Blog
Martin Fowler
Martin Fowler
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
A
About on SuperTechFans
T
Tailwind CSS Blog
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
SegmentFault 最新的问题
G
Google Developers Blog
M
MIT News - Artificial intelligence

ABB00717

HTB - SpeedNet PHP Filter to RCE Redis HTB - Pollution HTB - Pollution 工具 常見服務 HTB - BroScience HTB - BroScience 如何把爛爛的 shell 升級成好用的 TTY 滲透筆記 HTB - Imagery HTB - Imagery HTB - Reset HTB - Reset HTB - Trick HTB - Trick HTB - Editorial HTB - Editorial 150. Evaluate Reverse Polish Notation droopescan 安裝找不到 module imp 解決「桌面背景被當成一個視窗不斷重新彈出並覆蓋其他視窗」的問題 桌面不斷彈出覆蓋其他視窗 medusa 找不到 ssh module 中文文案排版指北 BugBounty Playbook 小知識 透過 Ubuntu 26 設定 Windows 11 雙系統並使用 Image Recovery 之踩坑全紀錄 透過 Ubuntu 26 設定 Windows 11 雙系統並使用 Image Recovery 之踩坑全紀錄 清除 git history 中的機敏資料
Makefile
2026-03-29 · via ABB00717

你就想像你在寫 BashPython 這種腳本語言,只不過 make 更針對編譯這個情境設計。

既然是腳本語言,那肯定以下幾個是不能少的:

  • 指令
  • 變數
  • 函式
  • 條件判斷

四大要件

指令

就是你在命令列(Command Line)會打的那些命令。但請注意,指令前面必須要是以 <Tab> 縮排,不能用空白鍵!

變數

在 Makefile 習慣變數名稱用大寫,要取變數值必須用 $(VAR)${VAR}

變數賦值

  • := (立即賦值 / Simple Assignment):定義的當下就會把值並確定下來,最常用且最推薦。
  • = (延遲賦值 / Recursive Assignment):用到該變數時,才會去尋找並展開它當下的值。這可能導致無窮迴圈或非預期結果。
  • ?= (條件賦值 / Conditional Assignment):如果這個變數前面還沒有被定義過,才會賦予它這個值;如果已經有值了,這行就會被忽略。
  • += (附加賦值 / Append):將後面的字串接在原本變數內容的後面(會自動用一個空白字元隔開)。

自動化變數

  • $@ 工作目標檔名
  • $* 工作目標的主檔名
  • $< 第一個必要條件的檔名
  • $^ 所有必要條件的檔名,並以空格隔開這些檔名
  • $? 所有比工作目標還要新的必要條件檔名

其他符號修飾

  • % 代表所有字串,像是 Regex 的 *
  • @ 不要顯示當前執行的命令
  • - 就算當前命令出錯,也不要中斷後續的執行

函式

在 Makefile 中叫做目標(Target),和函式一樣可以被呼叫和依賴:

all:
    # Compile Commands
clean:
    # Clean Commands

我們可以像呼叫函式那樣呼叫任意區塊,那當然也可能會有參數(依賴條件):

target: <obj1> <obj2>
    # Commands

Makefile 如果在呼叫 make 不接任何參數,就會執行第一個區塊。而 make 會先確認參數裡的每個區塊都準備完畢,才會執行該區塊:

FILE = main.l
NAME = $(basename $(FILE))

run: $(NAME)
    ./$(NAME)

$(NAME): lex.yy.c
    cc -o $(NAME) -O lex.yy.c -ll

lex.yy.c: $(FILE)
    lex $(FILE)

這就是 run $(NAME) lex.yy.c $(FILE),也就是只要有 FILE,其實就可以執行 run 了。因此要運行上述腳本,只須 make FILE=test.l 即可!

真實的內建函式

除了把 Target 當作函式,Makefile 也有提供真正的字串與檔案處理函式,語法通常是 $(function_name arguments)

  • $(wildcard *.c):抓取當前目錄下所有 .c 結尾的檔案。
  • $(patsubst %.c,%.o,$(SRCS)):字串替換,把 $(SRCS) 裡所有 .c 結尾的字串換成 .o
  • $(shell ls -la):執行外部的 Shell 指令並捕捉其輸出結果。

條件判斷

Makefile 也支援條件判斷(ifeq, ifneq, ifdef, ifndef),最常用來判斷不同的作業系統或編譯環境:

OS := $(shell uname)

ifeq ($(OS), Darwin)
    CC = clang
    CFLAGS += -D MAC_OS
else ifeq ($(OS), Linux)
    CC = gcc
    CFLAGS += -D LINUX_OS
else
    CC = cc
endif

build:
    $(CC) $(CFLAGS) main.c -o main