让你的makefile更专业。

在上一个Makefile所在目录下通过touch命令创建一个clean文件,执行make clean,将发现make总是提示clean文件是最新的,而不是按我们期望的那样对项目文件进行清楚操作。make这样的行为,是因为它将clean当做文件来处理,在当前目录下找到了clean文件,而且clean目标没有任何先决条件,所以当我们要求make构建clean目标时它会认为clean文件是最新的,从而拒绝我们真正的文件清除操作。出现这种情形,是因为我们对clean目标的定义与make所理解的有出入。目录文件名与makefile的目标名重名在现实项目中是难免的,假目标(phony target)概念的提出正是为了解决这种问题的。

假目标采用 .PHONY关键字来定义,注意必须是大写字母。运用假目标之后,更改makefile并运行如下:

 .PHONY: clean
app:main.o foo.o
gcc -o app main.o foo.o
main.o:main.c
gcc -o main.o -c main.c
foo.o:foo.c
gcc -o foo.o -c foo.c
clean:
rm -rf app main.o foo.o

采用.PHONY关键字声明一个目标之后,make并不会将其当做一个文件来处理。可以想象,由于假目标并不与文件关联,所以每次构建假目标时它所在规则中的命令一定会被执行。拿这里的clean目标做比方,即使多次执行make clean,make每次都会执行文件清楚操作。

运用变量提高可维护性:

编写专业的makefile离不开变量,通过使用变量可以使得makefile更具可维护性。

运用变量改写第一个makefiel。

 .PHONY: clean

 CC = gcc
RM = rm EXE =simple
OBJS =main.o foo.o $(EXE): $(OBJ)
$(CC) -o $(EXE) $(OBJS)
main.o:main.c
$(CC) -o main.o -c main.c
foo.o:foo.c
$(CC) -o foo.o -c foo.c
clean:
$(RM) -rf $(EXE) $(OBJS)

定义变量时其值可以为空,即无右值。引用变量需要采用 $(变量名)或 ${变量名} 的形式。

引入变量之后,如果需要更改编译器,只需要更改赋值变量的地方,其实相当于C语言宏定义的作用,便于更改移植。

上面的makefile,存在目标名和先决条件名在规则中重复出现,如果目标名或先决条件发生了改变,那么得在相应的命令中跟着更改这个很麻烦,为了省去这种麻烦,我们借助于如下一些自动变量:

除了这三个自动变量外,在makefile中还可以使用其他的自动变量,后面需要使用到的时候再提及。目前simple项目用这三个变量就足够了。

用上面的变量测试上面的Makefile,再正式介绍之前,得先介绍另外一个知识点。

 .PHONY: all
all:first second third
@echo "\$$@ = $@"
@echo "$$^ = $^"
@echo "$$< = $<"
first second third:

在Makefile中,dollar符(这个字符博客老抽风) 具有特殊的意思,如果采用echo输出dollar,则必须用两个连着的dollar;

对于bash shell 也有着特殊的意思,需要在  之前加一个反斜杠”\“。

最后一行是一个只有目标的规则,如果除去它会有什么问题呢?读者可以自己试试。

注释(makefile中用#表示注释,需要注释多行,在注释行的末尾加上反斜杠"\",下一行也会被注释)最后一行之后报错如上图。显示没有规则创建上述目标。因为all的先决条件决定了构建all目标之前必须先构建first ,而first如果不存在,报错也是应该的。

采用自动变量之后运行结果的Makefile如下所示:

 .PHONY: clean

 CC = gcc
RM = rm EXE =simple
OBJS =main.o foo.o $(EXE): $(OBJS)
$(CC) -o $@ $^
main.o:main.c
$(CC) -o $@ -c $^
foo.o:foo.c
$(CC) -o $@ -c $^
clean:
$(RM) -rf $(EXE) $(OBJS)

Makefile学习之路——2的更多相关文章

  1. Makefile学习之路——4

    变量的类别有递归扩展变量和简单扩展变量.只用一个“=”符号定义的变量被称为递归扩展变量.通过下面例子观察递归扩展变量的特点. .PHONY: all foo=$(bar) bar=$(ugh) ugh ...

  2. Makefile学习之路——3

    特殊变量: 在Makefile中,有两个变量特殊变量会经常用到:MAKE和MAKECMDGOALS.MAKE变量表示的是当前处理Makefile的命令名是什么.当需要在Makefile中运行另一个Ma ...

  3. Makefile学习之路——1

    编写makefile,不是一个猛子扎进去试着写一个规则并对之调试,而应该先采用面向依赖关系的思考方法勾勒出makefile要表达怎样的依赖关系,这一点尤为重要.通过不断地练习这种思考方法,才可能达到流 ...

  4. Makefile学习之路6——让编译环境更加有序

    在大多项目中都会合理设计目录结构来提高维护性,在编译一个项目时会产生大量中间文件,如果中间文件直接和源文件放在一起,就显得杂乱而不利于维护.在为现在这个complicated项目编写makefile之 ...

  5. Makefile学习之路5——通过函数增强功能

    通过函数能显著增强Makefile的功能.对于simple项目的Makefile,尽管使用了模式规则,但还是有一件比较麻烦的事情,就是要在Makefile中指明每一个项目源文件.下面介绍几个后期会使用 ...

  6. 运用Autoconf和Automake生成Makefile的学习之路

    作为Linux下的程序开发人员,大家一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Makefile,如果要想写出一个符合自由软件惯例的M ...

  7. Qt 学习之路 2(7):MainWindow 简介

    Qt 学习之路 2(7):MainWindow 简介  豆子  2012年8月29日  Qt 学习之路 2  29条评论 前面一篇大致介绍了 Qt 各个模块的相关内容,目的是对 Qt 框架有一个高屋建 ...

  8. Qt 学习之路 2(3):Hello, world!

     豆子  2012年8月22日  Qt 学习之路 2  107条评论 想要学习 Qt 开发,首先要搭建 Qt 开发环境.好在现在搭建 Qt 开发环境还是比较简单的.我们可以到 Qt 官方网站找到最新版 ...

  9. jQuery学习之路(1)-选择器

    ▓▓▓▓▓▓ 大致介绍 终于开始了我的jQuery学习之路!感觉不能再拖了,要边学习原生JavaScript边学习jQuery jQuery是什么? jQuery是一个快速.简洁的JavaScript ...

随机推荐

  1. eclipse Java注释修改

      eclipse Java注释修改 CreationTime--2018年6月1日09点15分 Author:Marydon 1.自定义java类自动生成注释的类型 window-->perf ...

  2. js 获取地址栏的值乱码问题

    传过去的参数是:(01) 0 6936841 40029 4. 接收的参数的:'(01)%200%206936841%2040029%204'. 因为包含空格,或者中文,就会乱码.要想不乱码,接收的使 ...

  3. linux利器expect的使用

    1.什么是expect在做系统管理时,我们很多时候需要输入密码,例如:连接 ssh,连接ftp,那么如何能做到不输入密码,我们需要有一个工具,能代替我们实现与终端的交互,它能够代替我们实现与终端的交互 ...

  4. PHP-二进制文件和文本文件的区别

    一.文本文件和二进制文件的定义 计算机上所有文件存储在存储设备上都是二进制的, 所以文本文件和二进制文件的区别并不是物理上的, 而是逻辑上的!简单来说, 文本文件是基于字符编码的文件, 常见的编码有A ...

  5. zookeeper与kafka安装部署及java环境搭建(发布订阅模式)

    1. ZooKeeper安装部署 本文在一台机器上模拟3个zk server的集群安装. 1.1. 创建目录.解压 cd /usr/ #创建项目目录 mkdir zookeeper cd zookee ...

  6. HDUOJ--Strange fuction

    Strange fuction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  7. Servlet乱码问题

    数据像水流一样从一个地方流向另一个地方. 文本流是特殊的二进制流. 既然提到乱码问题,那就必然是用错误的编码去解释二进制流. 在传输过程中必然都是以二进制流传输的. 所以,我们需要考虑的是: 有几个数 ...

  8. C# 小叙 Encoding (一)

    前言 众所周知计算机只能识别二进制数字,如1010,1001.我们屏幕所看到的文字,字符都是和二进制转换后的结果.将我们的文字按照某种规则转换二进制存储在计算机上,这一个过程叫字符编码,反之就是解码. ...

  9. AOV网与拓扑排序

    在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Activity on Vextex Network).AOV网中的弧表示活动 ...

  10. LCA近期公共祖先

    LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...