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

推荐订阅源

Martin Fowler
Martin Fowler
博客园 - 【当耐特】
GbyAI
GbyAI
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
腾讯CDC
F
Fortinet All Blogs
IT之家
IT之家
WordPress大学
WordPress大学
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
DataBreaches.Net
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Help Net Security
V
Visual Studio Blog
小众软件
小众软件
Y
Y Combinator Blog

ABB00717

SecList Knock Pivoting and Tunneling Broken Authentication File Inclusion Login Brute Forcing Reverse Shell Web Fuzzing 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 解決「桌面背景被當成一個視窗不斷重新彈出並覆蓋其他視窗」的問題
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