Makefile
直接看原文
- Aniket Bhattacharyea. (2021). Makefile Tutorials and Examples to Build From
- Aniket Bhattacharyea. (2021). Creating a Python Makefile
一个 Makefile 由若干条 rules 组成. 每条 rule 语法如下. 注意 recipes 前面要用 tab 而不是空格.
target1 [target2 ...]: [pre-req1 pre-req2 pre-req3 ...]
[recipes
...]
注意
- 默认用 sh 而不是 bash, 可以通过
SHELL = /bin/bash
设置. 关于:=
和=
的区别, 参考 这个回答 和 这个例子. - 默认 recipes 中每行都会开新的 sub-shell, 见 这里. 可以通过
.ONESHELL:
设置, 参考 这里 (为什么默认不是 oneshell). - recipes 中 command expansion 要加上
shell
(待确认其他做法), 比如$(shell ls)
, 见 这里. - shell 中的
$
需要转义, 见 这里 和 这里. 记得在 for 循环的时候用$$
.
其他语法略.
下面的例子来自 pandas (.PHONY 和不关心的项略了). 现在 pandas 已删除该文件, 可通过 查找 git 历史, 发现 这个更新 10 月 5 日删除了 Makefile.
all: develop
develop: build
python -m pip install --no-build-isolation -e .
build: clean_pyc
python setup.py build_ext
clean_pyc:
-find . -name '*.py[co]' -exec rm {} \;
clean:
-python setup.py clean
lint-diff:
git diff upstream/main --name-only -- "*.py" | xargs flake8
black:
black .
test-scripts:
pytest scripts
其中 recipes 中开头的 -
means ignore the exit status of the command that is executed (normally, a non-zero exit status would stop that part of the build). 参考 makefile - What do @, - and + do as prefixes to recipe lines in Make? - Stack Overflow
clean_pyc 中
-exec command {} ;
{} is a symbolic representation of the current pathname, and the semicolon is a required delimiter indicating the end of the command.
-exec rm '{}' ';'
另外可参考 find . -name -exec rm {} \;
- 16bit
此外还有有趣的用法比如 streamlit 中
.PHONY: help
help:
@# Magic line used to create self-documenting makefiles.
@# See https://stackoverflow.com/a/35730928
@awk '/^#/{c=substr($$0,3);next}c&&/^[[:alpha:]][[:alnum:]_-]+:/{print substr($$1,1,index($$1,":")),c}1{c=0}' Makefile | column -s: -t
.PHONY: all
# Get dependencies, build frontend, install Streamlit into Python environment.
all: init frontend install
它的 Makefile 很长, 可以参考一些写法.
其他自动化组件
TODO