使用 Makefile(make) 实现项目工作流程自动化¶
make
0 创建之始主要用于大型软件(C/C++ 语言等)项目的构建。
因为 make
工具可以自动确定一个大型程序中哪些部分需要重新编译,并发出适当的命令重新编译它们。
可以极大的减轻维护项目编译脚本的负担。
当前还是有许多项目使用 make
和 Makefile
来完成软件的 编译 & 安装,
一个良好维护的 Makefile
的项目通常使用如下的命令来完成 编译 & 安装:
./configure
make build
make install
备注
对于现代的 C/C++ 项目,建议您使用 CMake
1 作为构建系统。
make
& Makefile
简介¶
如果需要使用 make
那么您需要创建 Makefile
告诉 make
它所需要的运行规则。
Makefile
规则¶
Makefile
是基于文件规则的引擎。
一个规则通常由 target 目标(文件), prerequisites 依赖文件(目标) 以及 recipe (一系列命令) 组成。
示例如下:
您可以使用: make build
来构建 demo
, make run
直接运行。
备注
关于 make
和 Makefile
的相关知识,可以阅读 GNU make
0 文档。
为什么使用 Makefile
?¶
Makefile
主要有以下几个优点:
基于文件的规则引擎
开箱即用 & 久经考验
几乎所有平台(除 Windows 平台)都自带了
make
, 自 1977 年 2make
在贝尔实验室开发以来,已经经受住了四十多年的考验。shell 的无缝集成
兼容任何命令行工具。 只要能在命令行中完成的,都可以在
Makefile
中完成。Makefile
可以作为项目级别的alias
工具。编写简单 & 容易理解
对于熟悉 shell 脚本的开发者而言,
Makefile
编写简单,代码也很容易理解。
在项目中使用 Makefile
¶
小型项目中使用¶
在小型项目中,Makefile
可以作为命令行快速执行工具,它具有如下优点:
可靠的重现
减轻人员的记忆负担
减小需要输入的文字数量
命令行自动补全功能
例如:
.PHONY: format
format:
go fmt path/to/go/code
cargo fmt path/to/rust/code
black path/to/python/code
npm prettier --write path/to/javascript/code
# 调用其他语言的 自动格式化 程序
.PHONY: build-prepare
build-prepare:
# 构建环境准备 构建过程共享
.PHONY: build-dev
build-dev: build-prepare
@echo "start dev build ..."
# your build command here
@echo "dev build done"
.PHONY: build-prod
build-prod: build-prepare
@echo "start prod build ..."
# your build command here
@echo "prod build done"
.PHONY: build-feature-xxx
build-feature-xxx: build-prepare
@echo "start feature xxx build ..."
# your build command here
@echo "feature xxx build done"
只需要在命令行输入 make format
即可完成整个项目代码的自动格式化。
根据不同的构建需要,使用不同的 make build-xxx
即可(无需记忆复杂的构建命令)。
备注
在需要更改编译选项、设置的时候,只需一个人更改提交到版本控制系统,其他人员直接同步即可。
大型项目中使用¶
在大型项目中,Makefile
通常需要分成多个模块(每个模块实现相应的功能):
例如:
.
├── Makefile
└── mk
├── build.mk
├── deploy.mk
├── doc.mk
├── help.mk
└── install.mk
1 directory, 6 files
主 Makefile
引入其他的模块即可,
# Makefile entry
include mk/build.mk
include mk/deploy.mk
include mk/doc.mk
include mk/help.mk
include mk/install.mk
Makefile
小技巧¶
DEFAULT_GOAL¶
设置默认目标, 例如: .DEFAULT_GOAL := help
, 直接执行 make
则相当于 make help
PHONY & FORCE¶
对于非编译的项目,通常目标都不是真实的文件(例如: make format
格式化代码),
这时候可以使用 PHONY 和 FORCE 联合来保证目标的执行。
FORCE:
.POHNY: format
format: FORCE
@echo "代码格式化命令"
自定义过程¶
对于常用的一些固定流程,我们转换成过程供我们调用,例如:
.DEFAULT_GOAL := help
FORCE:
define my_info
@echo "\033[0;32m$(1)\033[0m"
endef
define my_warn
@echo "\033[0;33m$(1)\033[0m"
endef
define my_error
@echo "\033[0;31m$(1)\033[0m"
endef
define run_cmd
@echo
$(eval @_CMD := $(1))
$(call my_info,"$$ $(@_CMD)")
@$(@_CMD)
endef
.PHONY: help
help: FORCE
$(call my_info,"提示信息")
$(call my_warn,"警告信息")
$(call my_error,"错误信息")
$(call run_cmd,ls)
$(call run_cmd,ls -a)
执行 make
结果如下:
