利其器系列会继续更新,这期先讲讲其他的。
文|工程师Johnny
对于有年纪的,或者说以前做过Linux下的C/C++开发的朋友来说,Make和Makefile是很熟悉的东西了。在C语言盛行的时代,Makefile的编写肯定是面试必考项目之一。随着时间的推移,尤其是互联网的崛起,Java开始成为主流开发语言,包括后面什么python,nodejs之类的异军突起,乃至今天云计算为主的go语言大行其道。从客观角度来说随着C/C++开发的需求不断萎缩,慢慢很多工程师也都淡忘了Make和Makefile。最多就是在Linux上需要从源码编译安装一些软件工具的时候,随手输入下make, make install即可。已经很少再关注和使用Makefile了。
其实可能在实际工作和项目中,Makefile在很多程序员那里用的比较少。但是在很多开源项目中,你会发现都会有一个Makefile文件在项目根目录下。
今天我们就来说说,到底该不该用Makefile,以及简单入门学习下如果编写简单的Makefile。

一个典型的Makefile(图片来自google)
举个“栗子”
很多朋友说Makefile用不上,或者说是“开倒车”。其实都有道理,不过很多东西换一个思路使用会很有奇效。下面就举例一个常见的应用场景,大家可以代入考虑下。
现在比如说,我们有一个k8s的应用的go语言为主的项目。假如说,它的目录结果可能是这样的:
├── doc
├── docker
│ ├── docker-compose-dev.yaml
│ ├── docker-compose.yaml
│ ├── Dockerfile
│ └── Dockerfile.dev
├── helm
└── src
这里主要是docker文件夹下面可能有针对dev,prod不同环境的不同配置,以求生产不同的image。
如果说不用任何工具的帮助下,我们可能直接就利用build参数来指定不同的配置文件。比如:
docker build -f ***
docker-compose -f ****.yaml up --build
等等。
想这种情况还算比较简单的,有时候可能我们除了要指定不同的配置文件之外,还需要结合不同情况传入不同的其他参数,比如docker build的时候传入arg。
在Debug的时候一遍遍地敲入完整的命令是比较累人的。而且是否能记得住记得全也是问题。所以大部分工程师采用的是用一个文本记录下来这些经常运行的命令,下次使用的时候直接粘贴复制运行即可。
所以,一些想偷懒的一些工程师朋友,会编写一些shell脚本。比如dockerDevBuild.sh, dockerProdBuild.sh 等等。这样以后每次直接运行这些个shell脚本即可,不用再去记住那些很长的build命令。但是这种方式也不是很那么美好。第一,会有很多shell脚本,而这些脚本和项目本身并不是很紧密需要的,会干扰阅读源码。第二,shell脚本的命名是否能一目了然知道该脚本的用处也是个问题,有时候要么在shell脚本开头进行一段说明的注释。由此可见,这种处理方式并不是很理想。
对于这种情况,我们就可以考虑请出Makefile了。将我们这些不同的需求转变成类似下面的命令:
make all
make image-dev
make image-prod
……
这样一来只需要保留一个Makefile文件在根目录下,就可以了。而且大部分程序员基本上扫一眼Makefile或者Readme,就应该知道怎么利用Makefile来运行make命令。
简单入个门吧
网络上有很多前辈留下了丰富的文档,来教大家如何编写Makefile。有兴趣的朋友可以去查阅,比如比较有名的《跟我一起写Makefile》等等。
入门的话。。。。非常简单。格式如下:
# rule
:
[tab]
大家一看就懂了吧?
那么再给大家带来一个例子吧。结合上面的格式,应该就和反推出来其中的逻辑了。
PROJECT="example"
default:
echo ${PROJECT}
build:
@go build
install:
@go install
test: install
@go test ./...
.PHONY: default install test
这里只提示下:.PHONY是伪指令,内置的关键字。@是表示禁止回声,意思就是说,不会在终端打印执行的命令。其他的应该一看就明白了吧?
对于一些复杂的,且符合生产需求的Makefile大家请结合阅读相关文档自己来完成和编写了。顺便想想,上述提到的场景下Makefile该如何编写呢?
“ 勿问成功的秘诀为何,且尽全力做你应该做的事吧。——美华纳 ”
感谢您的时间阅读!谢谢大家!
期待您的关注

