1. 背景
这篇文章的主要目的是记录一些可以在Makefile中使用的技巧,以便可以为Makefile本身中的每个目标添加文档,并且可以将其作为make目标查看(例如make help)。
在项目中拥有可靠的文档是一件很了不起的事情,而且如果它们不会过时,那就更好了。通常在顶级Readme.md或类似文件中记录每个Make目标。尽管这是迈出的重要第一步,但更新Makefile而不是更新文档是很常见的,因此使它们变得毫无用处。
2. 目标
最终目标是能够根据Makefile中的注释运行以下内容。
1 2 3 4 5 6 7 8 9 10 11
| # make
Usage: make
Targets: help Display this help deps Check dependencies clean Cleanup the project folders build Build the project watch Watch file changes and build
|
对于具有很多目标的复杂Makefile,我们也可以将它们组合在一起。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| > make
Usage: make
Dependencies deps Check dependencies
Cleanup clean Cleanup the project folders
Building build Build the project watch Watch file changes and build
Helpers help Display this help
|
让我们继续看看它是如何实现的
要求:
make
和awk
是唯一的要求。在macOS(BSD)和Linux(GNU)版本上均能工作。
实现:
如上面的示例所示,我们可以针对两种不同的情况实现它们。
- 简单的makefile
对于目标文件很少的Makefile,我们可以列出所有目标文件而没有任何分组。
首先,添加一个帮助目标。
1 2
| help: ## Display this help @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-10s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
|
然后,使用上述帮助目标中指定的语法添加注释。在此示例中,我们将使用##作为可打印注释的标签。
1 2 3 4 5 6 7 8 9 10 11
| deps: ## Check dependencies $(info Checking and getting dependencies)
clean: ## Cleanup the project folders $(info Cleaning up things)
build: clean deps ## Build the project $(info Building the project)
watch: clean deps ## Watch file changes and build $(info Watching and building the project)
|
(可选)将默认目标添加为help,最好在Makefile的顶部
(可选)调整目标和通过make help输出的注释之间的宽度。
在上述帮助目标中,将数字10替换为您喜欢的字符宽度。
完整的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| .DEFAULT_GOAL:=help SHELL:=/bin/bash
.PHONY: help deps clean build watch
help: ## Display this help @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-10s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
deps: ## Check dependencies $(info Checking and getting dependencies)
clean: ## Cleanup the project folders $(info Cleaning up things)
build: clean deps ## Build the project $(info Building the project)
watch: clean deps ## Watch file changes and build $(info Watching and building the project)
|
添加分组与上面的分组非常相似。我们再添加一种注释格式,以区分分组注释和目标注释,并稍微调整帮助目标以适应更改。
添加帮助目标(确保正确复制/转换制表符)
1 2
| help: ## Display this help @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
|
使用上述帮助目标中指定的语法添加注释。在此示例中,我们将使用##作为可打印注释的标记,并使用## @作为分组注释 的标记
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ##@ Dependencies
deps: ## Check dependencies $(info Checking and getting dependencies)
##@ Cleanup
clean: ## Cleanup the project folders $(info Cleaning up things)
##@ Building
build: clean deps ## Build the project $(info Building the project)
watch: clean deps ## Watch file changes and build $(info Watching and building the project)
|
(可选)提供默认目标,并调整目标和打印输出的注释之间的字符宽度,如上面“简单Makefile”部分中所述
完整的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| .DEFAULT_GOAL:=help SHELL:=/bin/bash
##@ Dependencies
.PHONY: deps
deps: ## Check dependencies $(info Checking and getting dependencies)
##@ Cleanup
.PHONY: clean
clean: ## Cleanup the project folders $(info Cleaning up things)
##@ Building
.PHONY: build watch
build: clean deps ## Build the project $(info Building the project)
watch: clean deps ## Watch file changes and build $(info Watching and building the project)
##@ Helpers
.PHONY: help
help: ## Display this help @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
|
参考:
make help - Well documented Makefiles
Gist by prwhite
Client9 - Self documenting makefiles
Marmelab - Self documented makefiles