前言

  • 本笔记主要记录Makefile一些概念要点。
  • 本笔记为提取性笔记,章节与《跟我一起写Makefile》同步,所以会看到有些小标题会跳过。

概念

Chapter 3:书写规则

3.3 在规则中使用通配符

  • make 支持三个通配符:

    • *

      • 任意长度的任意字符
      • 长度为一的任意字符
    • ~以例子说明
      • ~/test

        • 表示当前用户的 $HOME 目录下的 test 目录
      • ~lzm/test
        • 表示用户为 lzm 的宿主目录下的 test 目录
        • 若用户没有宿主目录,则根据环境变量 HOME 而定。

举例

  • 例子1

    • 变量 objects 表示当前目录下所有的 .o 文件。
objects := $(wildcard *.o)
  • 例子2 *

    • :这里的变量 objects 表示的就是 *.o,因为就像 C语言 的宏。
objects = *.o
  • 例子3 *

    • 列出当前所有 .c 文件对应的 .o 文件。
    • 下面的 *,是make的 * ,% 是makefile的 % ,具体看函数定义。
$(patsubst %.c,%.o,$(wildcard *.c))

3.4 文件搜索

  • VPATH 变量

    • Makefile 文件会在当前目录下寻找依赖文件和目标文件,在找不到的情况下就在 VPATH 变量中指定的路径去找。
VPATH = src:../headers
* 上面例子中就是 **VPATH** 的格式,用 **:** 隔开多个路径。
  • vpath 关键字

    • vpath 关键字比 VPATH 变量更加灵活, vpath 可以指定不同的文件在不同的搜索目录中。
    • 使用方法有三种:
      1. vpath 在 。为符合模式 的文件指定搜索目录 (多个目录可以用空格或者 : 分开)。
      2. vpath 清除符合模式 的文件的搜索目录。
      3. vpath 清除所有已被设置好了的文件搜索目录。
vpath %.h include    //指定.h类型文件的搜索路径是include

3.8 自动生成依赖性

在 Makefile 中,我们的依赖关系可能会需要包含一系列的头文件,比如,如果我们的 main.c 中有一 句 #include "defs.h" ,那么我们的依赖关系应该是:

main.o : main.c defs.h

大多数的 C/C++ 编译器都支持一个“-M”的 选项,即自动找寻源文件中包含的头文件,并生成一个依赖关系。例如,如果我们执行下面的命令:

cc -M main.c

其输出是:

main.o : main.c defs.h

** 注:如果使用 GNU 的 C/C++ 编译器,得用 -MM 参数,不然,-M 参数会把一些标准库的头文件也包含进来。 **

如:

gcc -M main.c 的输出是:

main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h \
/usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/pthreadtypes.h \
/usr/include/bits/sched.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/wchar.h \
/usr/include/bits/wchar.h /usr/include/gconv.h \
/usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h \
/usr/include/bits/stdio_lim.h

gcc -MM main.c 的输出则是:

main.o : main.c defs.h

原理 *

  • 隐晦规则(其中之一)

    • 会自动生成 gcc -c *.c 等语句。

      • 如果使用了该 隐晦规则 规则,在不改变 源文件 的情况下,改变其它(如头文件),再去运行 make 命令,是不会干活的。

如果想使用 隐晦规则 + 依赖自动包含头文件,可以往下看。

  • gcc -MM main.c

    • 会在 makefile 的依赖上自动添加 main.c 包含的头文件。

基于上面这个原理,我们可以把 main.c 包含的头文件 信息 自动识别出来并保存到 main.d 文件中。

这时候,.d 文件就出来了。

直接解析例子 **
  • 头文件改变,make也会干活。
  • 该脚本实现了,.c 文件编译过程中,产生 .d 文件。
%.d : %.c
@set -e;rm -f $@;  \
$(CC)  -MM $(CPPFLAGS) $< > $@.;  \
sed 's,$∗\.o[ :]*,\1.o $@ : ,g' < $@. > $@;  \
rm -f $@.

参考

  • 源码解析

    • set -e;

      • 表示 直接在命令行模式上进行 sed 动作编辑,其实此为默认选项
    • rm -f $@;
      • 表示 删除所有目标文件,即是删除所有 .d 文件。
    • $(CC)  -MM $(CPPFLAGS) $< > $@.;
      • 表示 编译产生的一些标注库的头文件信息保存到 .d.xxx 随机文件中。
      • $@.
        • 表示后缀为随机的意思。
      • 假设 CC= gcc ,CPPFLAGS=空,即 gcc -MM main.c > main.d.xxxx
        • > 表示重定向的意思。
        • 即是把 main.c 所依赖的头文件信息写入 main.d.xxxx 文件。如
main.o: main.c defs.h
    * **sed 's,$∗\.o[ :]*,\1.o $@ : ,g' < $@. > $@;**
* 表示执行linux 命令 sed
* **< $@.**
* 该文件内容交给前面,让 sed 语句处理
* **$∗\.o[ :]\***
* 为匹配字段
* 表示 main 后面 .o 接着的字串段
* **$∗\.o[ :]\***
* 为替换字段
* **$@. > $@**
* 输入给 .d 文件,即是 main.d,内容如下:
main.o main.d : main.c defs.h
        * **rm -f $@.**
* 删除 main.d.xxxx 的随机文件。
  • 生成 .d 文件后,Makefile 文件可以 include 该文件进入 Makefile 中,这样, .o .d 都是目标文件,后面有很多依赖的头文件,一旦头文件更新,目标文件便会更新
sed 命令
  • 要点格式,具体百度
  • sed 为linux命令,用于替换。
sed‘s:/usr/local:/usr:g’
  • s: 就是于把 : 当作分隔符 /
sed‘s;/usr/local;/usr;g’
  • s; 就是于把 ; 当作分隔符 /

参考

书籍

  • 《GUN Makefile》
  • 《跟我一起写Makefile》

Makefile-3-书写规则的更多相关文章

  1. Makefile 书写规则

    1.1 Makefile的规则 在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则. target ... : prerequisites ...   command   ...

  2. 很详细、很移动的Linux makefile教程:介绍,总述,书写规则,书写命令,使用变量,使用条件推断,使用函数,Make 的运行,隐含规则 使用make更新函数库文件 后序

    很详细.很移动的Linux makefile 教程 内容如下: Makefile 介绍 Makefile 总述 书写规则 书写命令 使用变量 使用条件推断 使用函数 make 的运行 隐含规则 使用m ...

  3. Linux makefile教程之书写规则三[转]

    书写规则———— 规则包含两个部分,一个是依赖关系,一个是生成目标的方法.在 Makefile中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来 ...

  4. [转] Makefile 基础 (3) —— Makefile 书写规则

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...

  5. Dockerfile的书写规则和指令的使用方法

    Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令.Docker程序将这些Dockerfile指令翻译真正的Linux命 ...

  6. dockerfile简介及书写规则

                                       Dockerfile 简介 Dockfile是一种被Docker程序解释的脚本, Dockerfile由一条一条的指令组成,每条指 ...

  7. 学习Shell脚本编程(第1期)_Shell命令行书写规则

    Shell命令行的书写规则 对Shell命令行基本功能的理解有助于编写更好的Shell程序,在执行Shell命令时多个命令可以在一个命令行上运行,但此时要使用分号(:)分隔命令,例如: [root@l ...

  8. Route@书写规则的总结

    路由书写规则的总结 概念:Routing System由一组路由组成,每一个路由规则可以匹配一种类型的URL,在请求过来的时候,Ruting ystem 就用它来处理这个URL,路由的任务就是匹配UR ...

  9. makefile的编写规则

    2.       编写makefile 示例: test:main.o func.o gcc -o test main.o func.o func.o:func.c gcc -c func.c mai ...

  10. web.xml文件书写规则

    在为class文件写xml配置文件的书写规则,需要书写的东西如下 <servlet> <servlet-name></servlet-name> <servl ...

随机推荐

  1. Activiti7 表介绍

    由于Activiti自生成的表较多,这里先对activiti自生成数据库表进行介绍. 数据库表的创建在后续的demo文章中进行介绍,并且后续会写一篇关于数据库详解的文章,这里先大概知道Activiti ...

  2. Zabbix如何解决“System time is out of sync (diff with Zabbix server > 60s)”告警

    Zabbix如何解决"System time is out of sync (diff with Zabbix server > 60s)"这种告警呢? 这个错误对应的中文提 ...

  3. 字符串split的用法

    拆分字符串:张三:20|李四:40|王五:40 这个可以使用两次分割,第一次使用 | 分割,放到arr数组里,然后使用循环对arr[i]进行使用:分割 public static void main( ...

  4. origin Tips

    origin Tips 注意事项 在最初画图时,需要考虑到最好将图片的尺寸限制在 1 张 A4 纸的大小,不然有可能在插入 latex 的时候出问题 . 如何修改图片的尺寸?简而言之就是将画布中的图片 ...

  5. console.info(sum(1, 2, 3, 4)(5)(6));

     function add() {    // 第一次执行时,定义一个数组专门用来存储所有的参数    var _args = [].slice.call(arguments); // 在内部声明一个 ...

  6. MVC中将枚举类型数据应用到下拉列表中的方法

    例如: public enum ItemTypes   {      Movie = 1,      Game = 2,      Book = 3   }    在MVC2.0中如何将以上枚举类型使 ...

  7. python基础:面向对象

    一.定义 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类:一个种类,一个模型. 对象:指具体的东西,模型造出来的东西叫做对象. 实例:实例和对象是一样的. 实例化:实例化就 ...

  8. [LeetCode] 221. 最大正方形(DP)

    题目 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 输出: 4 ...

  9. js 去掉字符串最后一个逗号:笑死我了

    今天突然遇到js 去掉字符串最后一个逗号的问题,本想偷懒搜个代码吧,没想到看到百度的第一条记录是这么一篇文章. 网易博客: http://blog.163.com/li_crane/blog/stat ...

  10. Java语言的优势

    首先, Java语言是一种纯粹的面向对象的编程语言.这样就决定了Java语言更能直接客观地反映现实生活中的对象,因此Java语言更适合大型的复杂系统开发. 其次, Java语言是一种平台无关的语言.  ...