Linux下的makefile编写 ——陈皓《跟我一起写Makefile》学习笔记(二)

学习书籍原地址《跟我一起写Makefile》,感谢原作者的付出!

Makefile总述

一、Makefile里有什么

主要包含 :显示规则、隐晦规则、变量定义、文件指示和注释。

  1. 显示规则
    显示规则说明如何生成一个或多个目标文件,写Makefile的时候都是在写显示规则。
  2. 隐晦规则
    因为make的自动推导功能,可以将Makefile简化。
  3. 变量的定义
    变量一般都为字符串,类似于c的宏,调用时使用$(变量名)格式调用。
  4. 文件指示
    包括三个部分:
    1) 在一个Makefile中引用另一个Makefile,就像include;
    2)根据某些情况指定Makefile中的有效部分,就像#if;
    3)定义一个多行命令。
  5. 注释
    Make中只有行注释,用“#”字符进行注释。

二、Makefile的文件名

默认情况下,make会在目录下寻找名字为“GNUmakefile”、“makefile”和“Makefile”的文件。
最好使用“Makefile”,首字母大写,有种醒目的感觉;最好不要使用“GNUmakefile”,只有GNU的make对这个文件名敏感;有些make只对“makefile”敏感。

若要自定义文件名,可以在make后加上“-f”或者“–file”参数来指定你的自定义Makefile。

make -f myMake.Linux

或者

make --file myMake.Linux

三、引用其他的Makefile

语法:

include <filename>

filename可以使当前操作系统Shell的文件模式(可以包含路径和通配符)
在include前可以有一些空字符,但不能是[TAB]键开始;include可以同时包含几个Makefile,和变量差不多。例如:

  1. 目录下有多个.mk后缀的Makefile文件(a.mk b.mk c.mk):

    include *.mk
    

    等价于

    include a.mk b.mk c.mk 
    
  2. 满足1的基础上,定义一个变量$(makefiles),里面包含了d.mk和e.mk:

    #定义变量
    makefiles = d.mk e.mk
    

    则要包含所有的Makefile文件,可以这样写:

    #包含所有makefile
    include *.mk $(makefiles)
    

    等价于

    include a.mk b.mk c.mk d.mk e.mk
    

当make执行时,会将include所指出的其他Makefile的内容暂时安置在当前位置,就像c/c++的#include。如果文件都没有指定绝对路径或是相对路径的话,make会在当前目录下首先寻找,如果当前目录下没有找到,那么:

  1. 如果make后有“-I”或者“–include-dir”参数,make会在参数指定的目录下寻找。

  2. 如果目录/include(一般是/usr/local/bin或者/usr/include) 存在的话,make也会去找。

  3. 如果文件没有找到,make会生成一条警告信息,然后继续载入其他文件,完成Makefile的读取后,make会再次重新查找没有找到的文件,如果还是没有,那么make会生成致命信息,退出运行。可以在include前加一个“-”号让make忽略那些找不到的文件,继续执行下去:

    -include <filename>
    

    “-”在之前的clean命令中使用过,它的意思是:无论在命令执行过程中出现什么错误,都不要报错并继续执行。
    -include和其他版本的make兼容的相关命令是sininclude,作用相同。

四、环境变量MAKEFILES

MAKEFILES变量作用和include类似,其值是其他的Makefile,空格分隔。与include不同的地方在于用这个方法引入的Makefile里的“target”不会起作用,如果MAKEFILES中定义的文件有错误,make也不会报错。
建议不要使用MAKEFILES,因为当你使用这个变量,并且make时,所有的Makefile都会被影响。如果有时候Makefile出现的异常,可以看看当前环境中有没有这个变量。

五、make的工作方式

GNU make(其他的make类似):

  • 第一阶段

    1. 读取所有的Makefile;
    2. 读入被include的其它Makefile;
    3. 初始化文件中的变量;
    4. 推导隐晦规则,并分析所有规则;
    5. 为所有的目标文件创建依赖关系链。
  • 第二阶段

    1. 根据依赖关系,决定哪些目标要重新生成;
    2. 执行生成命令。

在第一个阶段中,make会将定义的变量在当前位置展开,但make并不会完全马上展开,如果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页