上一章:C语言之Makefile基础(一)

上一章的Makefile写的中规中矩,比较繁琐,是为了讲清楚基本概念,其实Makefile有很多灵活的写法,可以写的更简洁,同时减少出错的可能

一个目标依赖的所有条件不一定非得写在一个规则中,也可以拆开来写,例如:

main.o: main.h stack.h maze.h
main.o: main.c
gcc -c main.c

  

就相当于:

main.o: main.c main.h stack.h maze.h
gcc -c main.c

    

如果一个目标拆开写多条规则,其中只有一条规则允许有命令列表,其他规则应该没有命令列表,否则make会报警告并采用最后一条规则的命令列表。

于是,之前的Makefile文件我们还可以写成这样:

main: main.o stack.o maze.o
gcc main.o stack.o maze.o -o main
main.o: main.h stack.h maze.h
stack.o: stack.h main.h
maze.o: maze.h main.h
main.o: main.c
gcc -c main.c
stack.o: stack.c
gcc -c stack.c
maze.o: maze.c
gcc -c maze.c
clean:
-rm main *.o
.PHONY: clean

  

这样虽然也允许执行,但相比以前更繁琐了些,于是我们把提出来的三条规则删去,写成:

main: main.o stack.o maze.o
gcc main.o stack.o maze.o -o main
main.o: main.h stack.h maze.h
stack.o: stack.h main.h
maze.o: maze.h main.h
clean:
-rm main *.o
.PHONY: clean

  

这样就比原来简单多了,可是现在main.o、stack.o和maze.o这三个目标连编译命令都没有了,怎么编译呢?试试看:

[root@localhost linux_c]# make
cc -c -o main.o main.c
cc -c -o stack.o stack.c
cc -c -o maze.o maze.c
gcc main.o stack.o maze.o -o main

  

现在解释一下前三条编译命令怎么来的。如果一个目标在Makefile中的所有规则都没有命令列表,make会尝试在内建的隐含规则数据库中查找适用的规则。make的隐含规则数据库可以用make -p命令来打印,打印出来的格式也是Makefile的格式,包含很多变量和规则,其中和我们这个例子有关的隐含规则有:

# default
OUTPUT_OPTION = -o $@
# default
CC = cc
# default
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
%.o: %.c
# commands to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<

  

#号在Makefile中表示单行注释。CC是一个Makefile变量,用CC = cc定义和赋值,用$(CC)取它的值,其值应该是cc。Makefile变量像C的宏定义一样,代表一串字符,在取值的地方展开。cc是一个符号链接,通常指向gcc,在有些Unix系统上可能指向另外一种C编译器

[root@localhost linux_c]# which cc
/usr/bin/cc
[root@localhost linux_c]# ls -l /usr/bin/cc
lrwxrwxrwx. 1 root root 3 Feb 13 11:13 /usr/bin/cc -> gcc

  

在make -p中包含这一段定义:

# default
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
%.o: %.c
# commands to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<

    

CFLAGS这个变量没有定义,$(CFLAGS)展开是空,CPPFLAGS和TARGET_ARCH也是如此,这样,$(COMPILE.c)展开应该是cc 空 空 空 -c,去掉“空”就得到cc -c。所以,%.o: %.c规则的命令 $(COMPILE.c) $(OUTPUT_OPTION) $<展开之后为cc -c -o $@ $<,和上面的编译命令很接近了

$@和$<是两个特殊的变量,$@的取值为规则中的目标,$<的取值为规则中的第一个条件。 %.o:%.c是一种特殊的规则,称为模式规则,我们再来回顾一下整个过程,在我们的Makefile中,以main.o为目标的规则都没有命令列表,所以make会查找隐含规则,发现隐含规则中有一条模式规则适用main.o符合%.o模式,%代表main,以.o结尾的文件,再替换到%.c中就是main.c,所以,这条规则相当于:

main.o: main.c
cc -c -o main.o main.c

  

同理:

stack.o: stack.c
cc -c -o stack.o stack.c

  

maze.o也同样处理。这三条规则可以由make的隐含规则推导出来,所以就不必写在Makefile中了

先前我们写Makefile都是以目标为中心,一个目标依赖若干条件,现在换个角度,以条件为中心,Makefile还可以这么写:

main: main.o stack.o maze.o
gcc main.o stack.o maze.o -o main
main.o stack.o: main.h
main.o maze.o: maze.h
main.o stack.o: stack.h
clean:
-rm main *.o
.PHONY: clean

    

写规则的目的是让make建立依赖关系图,不管怎么写,只要把所有的依赖关系描述清楚就行,对于多目标的规则,make会拆成几条单目标的规则来处理,例如:

target1 target2: prerequisite1 prerequisite2
command $< -o $@

  

这样的规则相当于:

target1: prerequisite1 prerequisite2
command prerequisite1 -o target1
target2: prerequisite1 prerequisite2
command prerequisite1 -o target2

  

注意这两条规则的命令列表是一样的,但$@的取值不同

Makefile基础(二)的更多相关文章

  1. Makefile基础(三)

    第一章:C语言之Makefile基础(一) 第二章:C语言之Makefile基础(二) 再来看一个简单的例子: [root@localhost linux_c]# cat Makefile foo = ...

  2. 彻底掌握Makefile(二)

    彻底掌握Makefile(二) 前言 在前面的文章彻底掌握Makefile(一)当中,我们简要的介绍了一些常见的makefile使用方法,在本篇文章当中我们将继续介绍一些makefile当中的常见用法 ...

  3. Python全栈开发【基础二】

    Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...

  4. Bootstrap <基础二十九>面板(Panels)

    Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素添加 class .panel 和 class .pa ...

  5. Bootstrap <基础二十八>列表组

    列表组.列表组件用于以列表形式呈现复杂的和自定义的内容.创建一个基本的列表组的步骤如下: 向元素 <ul> 添加 class .list-group. 向 <li> 添加 cl ...

  6. Bootstrap<基础二十七> 多媒体对象(Media Object)

    Bootstrap 中的多媒体对象(Media Object).这些抽象的对象样式用于创建各种类型的组件(比如:博客评论),我们可以在组件中使用图文混排,图像可以左对齐或者右对齐.媒体对象可以用更少的 ...

  7. Bootstrap <基础二十六>进度条

    Bootstrap 进度条.在本教程中,你将看到如何使用 Bootstrap 创建加载.重定向或动作状态的进度条. Bootstrap 进度条使用 CSS3 过渡和动画来获得该效果.Internet ...

  8. Bootstrap <基础二十五>警告(Alerts)

    警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警告(Alerts)向用户提供了一种定义消息样式的方式.它们为典型的用户操作提供了上下文信息反馈. 您可以为警告框添加一个 ...

  9. Bootstrap<基础二十四> 缩略图

    Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ...

随机推荐

  1. scrollHelper

    (function ($) { var mouseScroll = function (e) { try { var origEvent = e.originalEvent; origEvent.pr ...

  2. .net的基础知识点

    在这个It市场都是风云变化的,都是又市场供需来定的,当年iOS火的一塌糊涂的,现在也出现找不到工作的,满地的出入门者,我就属于其中一个,在一个逼不得已的情况下,开始转行做.net ,我相信当年的很多. ...

  3. 【extjs6学习笔记】1.5 初始:关于布局

    absolute 绝对布局,这个布局使用 x 和 y 属性来指定组件的绝对定位 accordion 手风琴布局[可折叠布局]这个布局展示了在一个时间里只有一个内置的可支持折叠和展开的子级 panel ...

  4. 使用nginx搭建一个简单的负载均衡

    在windows系统上使用IIS模拟出两个不同服务器的站点: 然后再NGINX使用轮询机制配置两个服务器以及虚拟服务器的端口: 需要注意的是,配置虚拟代理域名的话需要找到windowsC盘下的host ...

  5. IOS CoreData 多表查询(下)

    http://blog.csdn.net/fengsh998/article/details/8123392 在iOS CoreData中,多表查询上相对来说,没有SQL直观,但COREDATA的功能 ...

  6. [论文理解] Connectionist Text Proposal Network

    Connectionist Text Proposal Network 简介 CTPN是通过VGG16后在特征图上采用3*3窗口进行滑窗,采用与RPN类似的anchor机制,固定width而只预测an ...

  7. TextView中使用Linkify添加超链接

       首先,在TextView所属xml配置文件中,直接添加android:autoLink特性即可,它支持一个或多个(用分割线)自定义的值:none.web.email.phone或all. 另外, ...

  8. 1066: 输入n个数和输出调整后的n个数

    1066: 输入n个数和输出调整后的n个数 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 2739  Solved: 1578[Submit][Stat ...

  9. 校招准备-关系型数据库与nosql

    深入理解常见的数据库的设计架构, 其中用到的数据结构, 算法等 SQL执行流程和优化, 可以了解一下calcite: https://calcite.apache.org/

  10. fence_vmware_soap UnicodeEncodeError

    执行如下命令 fence_vmware_soap -z -l administrator@vsphere.local -p 2wsx@QAZ -a 10.0.2.200 -o list --ssl-i ...