Afraid of Makefiles? Don't be!

Matthias Endler

害怕 Makefile?别怕!

衣服和 Makefile 有什么关系?读完这篇文章你就知道了!
衣服和 Makefile 有什么关系?读完这篇文章你就知道了!
来源:插图:Anindyanfitri(阿宁迪扬菲特里)- Freepik.com

过去几年里,我有幸和许多才华横溢的软件工程师共事。有一件事让我印象深刻:他们中的许多人并不了解 Makefiles,也不知道它们为什么有用。

当需要自动化构建流程时,他们往往会自己编写 shell 脚本。项目目录中常见的脚本包括 build.shrun.shdoall.sh

他们一次又一次地实现着相同的基本功能:

  • 解析输入参数和环境变量。
  • 手动管理构建步骤之间的依赖关系。
  • 错误处理(……也许吧)。

在此过程中,他们也不断犯着相同的基本错误:

Makefile 正是为了解决这些问题而发明的。

Makefile 很可怕!

如果你觉得 make 很可怕,你大概会想到为大型软件项目准备的复杂构建机制。但它不必如此。让我们听听 make 的作者 Stuart Feldman(斯图尔特·费尔德曼) 本人是怎么说的:

它起初是一个复杂的依赖分析器构想,后来被简化成了某种简单得多的东西,并在那个周末变成了 Make。使用当时还未经充分验证的工具,是那种文化的一部分。Makefile 是文本文件,而不是经过神秘编码的二进制文件,因为这就是 Unix 的精神:内容可打印、可调试、可理解。

——The Art of Unix Programming(《Unix 编程艺术》)(2003)

Make 只用了一个周末就构建完成,用一种简单的方式解决了一个反复出现的问题。

Makefile 很简单!

出门前,我需要先穿好衣服。每次我都按同样简单的流程来:内裤、裤子、衬衫、套头衫、袜子、鞋子、夹克。你很可能也有自己的流程,尽管它可能和我的不同。

其中一些步骤相互依赖。
Make 很适合处理依赖关系。
让我们试着把我的流程表达成一个 Makefile

dress: trousers shoes jacket
	@echo "All done. Let's go outside!"

jacket: pullover
	@echo "Putting on jacket."

pullover: shirt
	@echo "Putting on pullover."

shirt:
	@echo "Putting on shirt."

trousers: underpants
	@echo "Putting on trousers."

underpants:
	@echo "Putting on underpants."

shoes: socks
	@echo "Putting on shoes."

socks: pullover
	@echo "Putting on socks."

如果我们执行这个 Makefile,会得到以下输出:

$ make dress
Putting on underpants.
Putting on trousers.
Putting on shirt.
Putting on pullover.
Putting on socks.
Putting on shoes.
Putting on jacket.
All done. Let's go outside!

刚才发生了什么?

注意到这些步骤的顺序是正确的吗?只要清楚地写下步骤之间的依赖关系,make 就能帮助我们正确地执行它们。

每个构建步骤都具有以下结构:

target: [dependencies]
	<shell command to execute>
	<shell command to execute>
	...
  • 调用 make 时,Makefile 中的第一个目标会默认执行。

  • 目标的顺序并不重要。

  • Shell 命令必须使用制表符缩进。

  • 添加 @ 符号可以抑制所执行命令本身的输出。

  • 如果 target 不是你想要构建的文件,请在构建步骤末尾添加 .PHONY <target>。常见的伪目标包括:clean、install、run……否则,如果有人创建了一个 install 目录,make 就会静默失败,因为构建目标已经存在。

    .PHONY: install
    install:
    	npm install

恭喜!你已经学会了使用 make 所需知识的 90%。

下一步

真正的 Makefile 能做的事情多得多!它们会只构建发生过变化的文件,而不是每次都进行完整重建;还会尽可能并行执行。不过,请尽量让它们保持简单。

原文由 Matthias Endler 发布

本文章由 openai/gpt-5.6-luna 进行翻译