共计 3870 个字符,预计需要花费 10 分钟才能阅读完成。
你必须十分致力,能力看起来毫不费力!
微信搜寻公众号[漫漫 Coding 路],一起 From Zero To Hero !
前言
在 Go 语言开发中,咱们心愿可能标准代码格调,每个成员在提交时能够一键格式化,同时查看是否有语法错误;咱们心愿可能一键运行单测,生成单测报告;咱们心愿可能一键编译、打包、公布我的项目,这就须要应用到 Make。Make 有很多种,咱们罕用的就是 GUN Make,有了 Make,咱们将极大的进步我的项目开发、测试、公布的效率。
Make 最后是为 C、C++ 我的项目的编译、构建服务的,因而有很多为 C、C++ 的个性,然而这些个性在 Go 开发中应用不到。毕竟每个人的工夫无限,咱们就只学习 Go 开发中 Make 应用所必须的常识。Make 的规定都在 Makefile 文件编写上,咱们前面就一起来学习 Makefile 的编写吧!
make 命令在 Windows 下不反对运行,须要在 Linux 或 Mac 环境下运行
规定
Makefile 的规定很简略,分为三个局部:
target : prerequisites
command
...
target:指标,能够是一个文件,或者是一个标签 label
prerequisites:targets 依赖的货色,能够是文件,也能够依赖其余 target
command:shell 命令(结尾是 Tab 键)
- 如果 prerequisites 比 target 要新,就会 执行 command 命令(已存在的文件比不存在的文件新)
- 如果 prerequisites 中存在其余 target,对该 target 反复第一条
举个例子:
hello: hello.go
go build hello.go
如果 hello 文件不存在,hello.go 必定比不存在的 hello 新,执行命令 go build hello.go
如果 hello 文件存在,然而 hello.go 又有了新的批改,hello.go 也比 hello 新,执行 go build hello.go
如果 hello 文件存在,且 hello.go 没有改变,不执行任何操作
再举个例子:
hello: hello.go
go build hello.go
world: hello world.go
go build world.go
hello 是个 target,world 也是个 target,且 world 依赖 hello。
如果执行 world 这个 target,会有如下两种情景:
world 不存在,遍历 prerequisites
-
hello 是个 target,走一遍例一形容的流程
如果 hello 文件不存在,执行命令
go build hello.go
,此时生成了 hello,比 world 新如果 hello 文件存在,然而 hello.go 又有了新的批改,执行
go build hello.go
,,此时生成了 hello,比 world 新如果 hello 文件存在,且 hello.go 没有改变,持续判断 world.go
- world.go 是个一般文件,比不存在的 world 新
- world 的依赖中,存在有比 world 新的,因而执行 command
world 存在,遍历 prerequisites
-
hello 是个 target,走一遍例一形容的流程
如果 hello 文件不存在,那么就会执行命令
go build hello.go
,此时 hello 比 world 新了如果 hello 文件存在,然而 hello.go 又有了新的批改,也会执行
go build hello.go
,此时 hello 比 world 新如果 hello 文件存在,且 hello.go 没有改变,不执行任何操作
- world.go 是个一般文件,如果批改过,那么比 world 新,否则不如 world 新
- 判断 prerequisites 中的 hello 或者 world.go 是否存在比 world 新的,如果有,执行 command;没有的话不执行任何操作
多指标
有可能咱们会有多个 target 规定相似,咱们能够将它们合并起来:
.PHONY: target1 target2
target1 target2: prerequisites
command
等同于
.PHONY: target1 target2
target1: prerequisites
command
target2: prerequisites
command
伪指标
下面说过,target 不肯定是一个文件,也可能是一个 标签,因为有些操作,咱们不肯定会生成文件,比方清理一些两头文件,运行单测等,这种 target 咱们把它叫做伪指标。
hello: hello.go
go build hello.go
world: hello world.go
go build world.go
clean:
rm hello world
clean 就是一个伪指标,只是一个标签,运行这个伪指标,须要显式地指定这个指标,即 make clean
➜ make clean
rm hello world
然而有可能会有文件和咱们的伪指标名称重名,这样咱们运行 make clean 的时候就达不到咱们的目标了。
# 如果有重名文件存在,make clean 就不会运行
➜ touch clean
➜ make clean
make: `clean' is up to date.
为了避免这样的状况,咱们能够应用 “.PHONY” 显式地申明咱们的 target 是个 伪指标,这样即便有重名文件在,也不会影响 target 的运行。
hello: hello.go
go build hello.go
world: hello world.go
go build world.go
# 显式申明 clean 是个伪指标
.PHONY: clean
clean:
rm hello world
➜ make world
go build hello.go
go build world.go
➜ touch clean
➜ make clean
rm hello world
运行
下面咱们其实曾经运行过 makefile 了,这里咱们再来简略看下:
hello: hello.go
go build hello.go
world: hello world.go
go build world.go
# 显式申明 clean 是个伪指标
.PHONY: clean
clean:
rm hello world
在默认的形式下,也就是咱们只输出 make
命令。那么,
- make 会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 如果找到,它会找文件中的第一个 target,运行该 target,并打印相应的日志。
或者咱们能够输出 make + target,强制运行某个 target,比方输出 make world
。
➜ make
go build hello.go
➜ makefile_study make world
go build world.go
➜ make clean
rm hello world
援用 Makefile
在 Makefile 中应用 include
关键字能够把别的 Makefile 蕴含进来,这很像 C 语言的 #include
,被蕴含的文件会放在以后文件的蕴含地位。include
的语法是:
include filenames…
- filename 能够是绝对路径或者当前目录下的文件;如果 filename 是空,不会进行援用也不会报错。
- include 后面能够有多个空格,然而
肯定不能
是Tab
- include 和 filename 间接应用空格分隔;多个 filename 之间也应用空格分隔
- filename 中能够应用变量
举个例子,如果你以后文件夹下有三个 makefile 文件,别离叫做 a.mk、b.mk、c.mk,那么如下援用
include foo *.mk
相当于
include foo a.mk b.mk c.mk
Makefile 在解决 include 时,遇到一个 include 文件就读取该文件内容,读取完后再解决下一个 include 文件。
如果一个文件没有指定门路,会在以后门路下寻找,如果没找到,还会依照如下程序寻找:
- 运行 Make 命令时应用 ‘-I’ 或 ‘–include-dir’ 参数指定的门路
- 如果如下目录存在的话,会挨个寻找。prefix/include(个别是 /usr/local/include)、/usr/gnu/include、/usr/local/include、/usr/include
在解决 include 时,如果一个 include 的文件没有找到,程序不会终止,只会打印一条正告信息,而后持续解决。当读取残缺个 Makefile 文件后,程序再去重试解决这些没有找到的文件,如果还是解决失败,会产生一个致命谬误。如果想疏忽文件不存在带来的报错,能够在 include 后面加上一个减号 ‘-‘,示意疏忽援用谬误。
-include filenames…
咱们个别都是有一个主文件 Makefile 对外裸露,其余的援用文件被主文件 Makefile 调用,相似函数调用。一个 target 调用 另一个 target,能够间接应用 $(MAKE)+target
。
a.mk
.PHONY: a_func
a_func:
echo "this is a_func"
Makefile
include a.mk
.PHONY: func
func:
$(MKAKE) a_func # 调用 a.mk 中的 a_func target
总结
本文次要介绍了 Makefile 的运行机制,分为以下几个方面:
- 规定:根据 prerequisites 是否比 target 新,决定是否执行 command
- 多指标:多个 target 的 prerequisites 和 command 相似时,应用多指标
- 伪指标:target 不是一个指标文件
- 运行:如何运行 Make
- 援用:援用其余 Makefile 文件
更多
集体博客: https://lifelmy.github.io/
微信公众号:漫漫 Coding 路