banner
raye~

Raye's Journey

且趁闲身未老,尽放我、些子疏狂。
medium
tg_channel
twitter
github
email
nintendo switch
playstation
steam_profiles

学习使用Makefile来管理项目

Group 4

一直以为 Makefile 是独属于 C++ 项目的,看到这个文件就比较头大,因为少不了需要执行一堆 make 命令来等待编译链接。

不过最近才了解到,make 命令其实并没有那么神秘,相反,它可以有效地组织开发项目中会使用到的各种命令、环境变量、shell 命令等。

除此之外,Makefile 的一大好处就是可以配置一些自动化的前置步骤,比如 python 项目的 pip install, node 项目的 npm install 等

最后,Makefile 还可以依赖本地的文件,如果文件没有更新,则与之相应的任务并不会执行,有点类似于本地的 CI 了

接下来就认识一下 Makefile 的简单编写以及实例吧

Makefile 的基础语法#

.PHONY#

因为 Makefile 的设计初衷其实是监控本地的文件是否有更新,再去触发一系列动作,所以单纯的 shell 命令执行得使用.PHONY(虚假)来实现,比如

dev:
	@echo "Hello, world!"
.PHONY: dev

依赖#

Makefile 是分步骤进行的,每一个步骤都会有其前置任务,其写法一般是:

target1 [target2 ...]: [pre-req1 pre-req2 pre-req3 ...]
    [recipes
    ...]

最简单的举例,比如我们想执行一个 next.js 项目的本地预览,其前置条件必须是已经安装了对应的 dependences,那么就可以这样写:

dev: node_modules ## 开启本地服务
	@./node_modules/.bin/next dev
.PHONY: dev

node_modules: package.json
	@yarn install

这里就构成了一个依赖的执行顺序:

  1. 执行 make dev,会检查前置条件 node_modules(注意这是一个步骤的命名)
  2. node_modules 步骤依赖于 package.json,即首先会执行一次 yarn install,后续如果 package.json 如果更新了才会执行

根据上述简单的示例就可以看到,Makefile 可以让我们清晰有序地管理一些常见的开发步骤,免去诸如修改 package.json 但是忘记执行 yarn install 的 “悲剧”

帮助文档#

可以看到在上面的示例中,有通过 ## 来编写注释

此时如果在 Makefile 中加入下面这段:

help: ## Show this help
	@echo "\nSpecify a command. The choices are:\n"
	@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "  \033[0;36m%-12s\033[m %s\n", $$1, $$2}'
	@echo ""
.PHONY: help

就可以自动生成注释了,即输入 make help 自动打印帮助文档,是不是非常神奇呢 hh

简单示例:使用 Makefile 来管理你的 hugo 博客#

hugo 管理博客有几个最简单的命令,如开启服务器,生成站点静态文件等,我们可以将其都放在一个 Makefile 中

all: help ## 默认打开帮助文档


serve: ## 启动服务器
	@echo "Starting Hugo server..."
	hugo server

build: ## 构建站点
	@echo "Building the site..."
	hugo 

clean: ## 清理生成的文件
	@echo "Cleaning up the public directory..."
	rm -rf public/

help: ## Show this help
	@echo "\nSpecify a command. The choices are:\n"
	@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "  \033[0;36m%-12s\033[m %s\n", $$1, $$2}'
	@echo ""

.PHONY: all serve build clean help

默认的命令 all 就是显示帮助文档,而帮助文档的生成只需要写清楚注释即可自动完成,现在输入 make 命令的效果如下:

$:~/develop$ make

Specify a command. The choices are:

  all          默认打开帮助文档
  serve        启动服务器
  build        构建站点
  clean        清理生成的文件
  help         Show this help

当然这里只是最简单的展示,你还可以根据需要添加对应的依赖文件,以及 new post 的操作也都是可以集成进来的。

一步步使用 Makefile 来管理 python 项目#

简单版本#

首先,假设我们的 python 项目入口为 app.py,那么我们最终执行的目标就是

run: ## 记得加注释,可以自动生成帮助文档
  python app.py
.PHONY run ## 因为并没有依赖文件,所以需要使用.PHONY

其次,python 肯定有前置依赖需要安装,一般依赖都会写在 requirements.txt,于是我们有

setup: requirements.txt
    pip install -r requirements.txt

当然,一般还会补充一个 clean 的命令,于是有

clean:
    rm -rf __pycache__

进阶版本#

由于每个人电脑上本地的 python 环境变量都不同,当然这个也可以用 docker 来解决,不过 python 本身提供了 venv 这种更轻量级的解决方案,于是可以

python3 -m venv venv

-m venv 代表使用 venv 命令,创建一个虚拟环境,位于 venv 目录

此时安装依赖就可以使用

./venv/bin/pip install -r requirements.txt

因为此时 pip 是位于 ./venv/bin/ 目录下的

所以得到 Makefile

venv/bin/activate: requirements.txt
 python3 -m venv venv
 ./venv/bin/pip install -r requirements.txt

但是每次都要写 ./venv/bin/ 比较麻烦,可以使用变量做一下简化

即声明一个变量 VENV 它的值默认为 venv 目录,但是你也可以通过命令行传递的方式来修改

引用变量的方式则是 $(VENV),可以理解为简单的字符串替换,于是 Makefile 就可以修改为:

VENV = venv
PYTHON = $(VENV)/bin/python3
PIP = $(VENV)/bin/pip

run: $(VENV)/bin/activate
 $(PYTHON) app.py
.PHONY run


$(VENV)/bin/activate: requirements.txt
 python3 -m venv $(VENV)
 $(PIP) install -r requirements.txt


clean:
 rm -rf __pycache__
 rm -rf $(VENV)
.PHONY clean

简单总结#

有了 GPT 之后,其实 Makefile 完全可以让 GPT 来代劳,对于其语法完全可以做一个简单了解,能看懂就行了,所以我也只列举出了最简单的语法以及对应的示例。

不得不说有了 AI 之后,诸如此类的工作已经完全不用开发者操心了。从另一个方面来说,以前觉得一些麻烦的,不太想了解的技术细节,其实往往有很多意想不到的作用。

具体到 Makefile,完全可以将其当做一系列命令的封装,以及一些繁琐依赖人工记录的步骤,甚至可以将其当做 README 文件来使用了。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。