请选择 进入手机版 | 继续访问电脑版
搜索
查看: 715|回复: 4

天天写Makefile,你知道Makefile在代码中真正的意义吗?

[复制链接]
发表于 2017-6-9 15:25 | 显示全部楼层 |阅读模式
Makefile 并不复杂,我们也无需运用它更多的功能,因为一些简单的功能足够让工作变得更自动化,更有效率,也更轻松。当然如果你想更深的了解Makefile,可以搜索相关文档。
之前我写了很多的脚本,这些脚本能够帮助我解决具体的问题,但它们大都没有关联,也不是一个整体,而Makefile就是这样一个能够把单个的脚本联系起来的工具。一个工具只有你真正使用它的时候,你才会发现它的强大。make 小而强大。
make是系统中不可缺少的工具,许多程序员用它来编译大规模程序。赶快用which make检查一下,它是否存在在系统中。如果存在,那么我们开始创建一个名为Makefile的文件来做一个测试。
基本语法:
target:dependencies
[tab] <command>
文件内容:
#Makefile example
first:

echo “hello” > hello.txt
second: hello.txt

cat hello.txt

现在我们运行
%make
结果只运行第一步first阶段。
如果要运行第二阶段就要运行
%make second

当然我们现在可以在Makefile里增加 :
all : first second
依次运行两个步骤。
第一步每次都会运行,因为它的dependencies 为空。而第二步要当hello.txt存在时才运行,因为hello.txt是第二步的dependence。

现在我们要运用一些变量,增加:
USER_FILE = hello.txt
调用时使用:
${USER_FILE}
同时,我们把命令放到脚本中,因为这样关系到我们如何让现有脚本关联起来。所以,我们增加:
#hello.sh include echo “hello”
SHELL_CREATE = hello.sh
#showhello.sh include cat $1
SHELL_SHOW = showhello.sh

现在完整的Makefile 是这样:
#Makefile example
USER_FILE = hello.txt
SHELL_CREATE = hello.sh
SHELL_SHOW = showhello.sh

all : first second
first:

${SHELL_CREATE} > ${USER_FILE}
second: ${USER_FILE}

${SHELL_SHOW} ${USER_FILE}

如果一行太长,可以用“\\”换行,命令之间使用“;”分隔。

但现在有一个问题,就是阶段之间没有关联。也就是,如果我使用make second 就只运行第二步骤,并不会因为第一步没有运行,而启动第一步。
现在要改进就是将第一步的target作为第二步的dependence。
second:
first ${USER_FILE}
现在即使没有all target,因为阶段之间有了相互关系,也会依次运行,也就是运行:
%make second

现在另一个问题,就是如果第一步已经完成,是否可以不再运行。那么我们要考虑的是第一步依靠什么运行:
1,
文件没有产生;(要生成文件)
2,
产生的文件比产生文件的脚本旧。(要更新文件)
第一个要求就是将要产生的文件作为target,第二个要求就是将脚本作为dependence。这样我们要作的修改就是:
${USER_FILE} : ${SHELL_CREATE}
因为first才是我们真正的target,也就first的dependence是要实现二个要求的target,所以结果为:
first : ${USER_FILE}
${USER_FILE} : ${SHELL_CREATE}

现在最终的Makefie为:
#Makefile example
USER_FILE = hello.txt
SHELL_CREATE = hello.sh
SHELL_SHOW = showhello.sh

all : first second
first : ${USER_FILE}
${USER_FILE} : ${SHELL_CREATE}

${SHELL_CREATE} > ${USER_FILE}
second: ${USER_FILE}

${SHELL_SHOW} ${USER_FILE}
我们删除了second中first dependence,
因为first与${USER_FILE}是相同的,只要保留其中一个即可。
现在,如果我们运行第二步,make发现第一步没有运行就会运行第一步,再运行第二步。如果第一步已经完成,即文件已经产生,并且比产生文件的脚本更新,就会只运行第二步。
也就是说,如果运行第二步,希望同时启动第一步的条件是:
1,
删除产生的文件;
2,
更新产生文件的脚本的日期。

通过这样的修改,我们就可以将整个流程的步骤关联起来,并且如果前一步没有完成,后一步会将前一步追加运行。即使你运行all target,也只会从没有完成的阶段继续运行。这在实际工作流程中,是很有用的。
一个常用的make 选项,-n,只查看动作,不实际运行。

回复

使用道具 举报

发表于 2017-6-13 09:51 | 显示全部楼层
以前搞AVR的时候,研究过,不用都忘了
回复 支持 反对

使用道具 举报

发表于 2017-6-13 10:09 | 显示全部楼层
好文章,值得学习
回复 支持 反对

使用道具 举报

发表于 2017-6-13 10:54 | 显示全部楼层

好文章,值得学习
回复 支持 反对

使用道具 举报

发表于 2017-6-14 14:06 | 显示全部楼层
现在不写makefile了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

facebook google plus twitter linkedin weibo
©2017 Tensilica Corporation

小黑屋|手机版|Archiver|Tensilica技术社区  

GMT+8, 2017-12-13 01:52 , Processed in 0.086785 second(s), 7 queries , Memcache On.

快速回复 返回顶部 返回列表