原因一:避免Makefile檢查時間戳
前置知識:makefile在依賴文件沒有改變時不會執行編譯命令
#第一次執行,OK
[root@VM-16-14-centos ~]# make
g++ -E main.cc -o main.i
g++ -S main.i -o main.s
g++ -c main.s -o main.o
g++ main.o -o main#第二次執行,源文件沒有被修改,為了效率make不會執行編譯
[root@VM-16-14-centos ~]# make
make: `main' is up to date.
當目錄中存在名為clean
的文件時,若未聲明.PHONY
,make clean
會檢查該文件的時間戳。由于clean
目標通常沒有依賴文件,Make會認為該目標已是最新狀態,從而跳過命令執行。
# 未聲明.PHONY時,若存在clean文件:
$ touch clean
$ make clean
make: 'clean' is up to date. # 命令未執行
.PHONY
聲明后,無論文件是否存在,make clean
都會執行其命令。例如:
.PHONY: clean
clean:rm -f *.o main
即使存在clean
文件,也會強制刪除目標文件。
情況 | 未聲明.PHONY | 聲明.PHONY 后 |
---|---|---|
目錄中存在clean 文件 | 命令被跳過 | 命令強制執行 |
無clean 文件 | 命令正常執行 | 命令正常執行 |
原因二:優化性能(次要)
在Makefile中,.PHONY
目標通過跳過隱含規則搜索來提升性能,其原理和優化效果可分為以下四個層面:
場景 | 未聲明.PHONY | 聲明.PHONY 后 |
---|---|---|
目標文件已存在 | 檢查時間戳(約0.5ms) | 直接執行命令(0ms) |
多級依賴鏈 | 遞歸檢查所有依賴 | 僅執行命令不檢查依賴 |
并行編譯(make -j ) | 可能因規則搜索阻塞線程 | 減少線程競爭 |
- 必須聲明為
.PHONY
的目標:clean
、install
等不生成文件的操作- 入口目標如
all
(避免與all
文件沖突)
- 不應聲明的情況:
- 實際需要生成文件的目標(如
main.o
),否則會重復編譯,降低效率
- 實際需要生成文件的目標(如