关于makefile:Makefile-学习一运行机制

43次阅读

共计 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 键)

  1. 如果 prerequisites 比 target 要新,就会 执行 command 命令(已存在的文件比不存在的文件新)
  2. 如果 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

  1. hello 是个 target,走一遍例一形容的流程

    如果 hello 文件不存在,执行命令 go build hello.go,此时生成了 hello,比 world 新

    如果 hello 文件存在,然而 hello.go 又有了新的批改,执行 go build hello.go,,此时生成了 hello,比 world 新

    如果 hello 文件存在,且 hello.go 没有改变,持续判断 world.go

  2. world.go 是个一般文件,比不存在的 world 新
  3. world 的依赖中,存在有比 world 新的,因而执行 command

world 存在,遍历 prerequisites

  1. hello 是个 target,走一遍例一形容的流程

    如果 hello 文件不存在,那么就会执行命令 go build hello.go此时 hello 比 world 新了

    如果 hello 文件存在,然而 hello.go 又有了新的批改,也会执行 go build hello.go此时 hello 比 world 新

    如果 hello 文件存在,且 hello.go 没有改变,不执行任何操作

  2. world.go 是个一般文件,如果批改过,那么比 world 新,否则不如 world 新
  3. 判断 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 命令。那么,

  1. make 会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个 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 文件。

如果一个文件没有指定门路,会在以后门路下寻找,如果没找到,还会依照如下程序寻找:

  1. 运行 Make 命令时应用 ‘-I’ 或 ‘–include-dir’ 参数指定的门路
  2. 如果如下目录存在的话,会挨个寻找。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 路

正文完
 0