Makefile学习笔记1

Makefile学习笔记1

基本概念

  1. 编译
  2. 链接
  3. 静态库
  4. 共享库

make介绍

  make在执行时,需要一个Makfile文件。这个文件告诉make以何种方式编译源代码和链接程序。如果你修改了工程中的文件,要重新生成可执行文件,只需要在命令行窗口敲一个make命令就可以了。
  make通过比较对应文件(规则的目标和依赖)的最后修改时间,来决定哪些文件需要更新,哪些文件不需要更新。需要更新的make就会执行相应规则中的命令,不需要重建的,什么也不做。
  也可以在make命令后面指定更新哪些文件。比如 make app,make clean等

make规则介绍

  当使用 make 工具进行编译时,工程中以下几种文件在执行 make 时将会被编译(重新编译):
1. 所有的源文件没有被编译过,则对各个 C 源文件进行编译并进行链接,生成最后的可执行程序;
2. 每一个在上次执行 make 之后修改过的 C 源代码文件在本次执行 make 时将会被重新编译;
3. 头文件在上一次执行 make 之后被修改。则所有包含此头文件的 C 源文件在本次执行 make 时将会被重新编译。

Makefile规则介绍

一个简单的Makefile描述规则组成:
target: prerequisites
  command
  …

target: 规则目标,就是要生成的文件,或者中间过程文件名
prerequisites: 规则的依赖
command: 规则的命令,规定了生成目标文件要执行的命令

  一个规则可以有多个命令,每条命令占一行。* 注意:每一个命令行必须以[Tab]字符开始,[Tab]字符告诉make此行时一条命令。make按照命令完成相应的动作 *

  规则描述了目标之间的依赖关系和更新目标所用的命令。

举一个简单的例子,假设我们有一个工程,这个工程有两个源文件和一个头文件,Makefile的内容如下:

ltftpd: main.o utils.o
    gcc -o ltftpd main.o utils.o

main.o: main.c utils.h
    gcc -c -o main.o main.c

utils.o: utils.c utils.h
    gcc -c -o utils.o utils.c

clean:
    rm main.o utils.o ltftpd

在这个Makefile中,目标文件是ltftpd,它依赖main.o utils.o,main.o依赖main.c utils.h,utils.o依赖utils.h
clean是一个伪目标

使用变量

  上面的Makefile有个问题,就是main.o utils.o重复出现了3次,不好维护。避免重复的办法是定义变量。
实际工作中比较认同的做法是定义一个变量,名字取 objects OBJECTS OBJS objs obj OBJ 这种样子,如下

OBJS=main.o utils.o

OBJS作为一个变量,它代表.o文件的列表。在使用.o文件的地方,使用$(OBJS)来表示,这有点像C语言的宏。

OBJS=main.o utils.o

ltftpd: $(OBJS)
    gcc -o ltftpd $(OBJS)

main.o: main.c utils.h
    gcc -c -o main.o main.c

utils.o: utils.c utils.h
    gcc -c -o utils.o utils.c

clean:
    rm $(OBJS) ltftpd.exe

需要增加或修改.o文件,只需要修改OBJS变量即可。

自动推导规则

  编译.c文件的规则可以不用明确给出。make本身存在一个默认规则,会用gcc -c xxx.c -o xxx.o的命令编译.c文件生成.o文件。所以上面的Makfile可以简化成:

OBJS=main.o utils.o

ltftpd: $(OBJS)
    gcc -o ltftpd $(OBJS)

main.o: utils.h

utils.o: utils.h

clean:
    rm $(OBJS) ltftpd.exe

在cygwin下测试make的这个默认规则没有生效

  书写规则建议的方式是:单目标,多依赖。就是说尽量要做到一个规则中只存在一个目标文件,可有多个依赖文件。 尽量避免使用多目标,单依赖的方式

Makefile的内容

在一个完整的Makefile中,包含了5个东西:显式规则、隐式规则、变量定义、指示符和注释。

  • 显式规则:它描述了在何种情况下如何更新一个或者多个被称为目标的文件。
  • 隐式规则:它是make根据一类目标文件(典型的是根据文件名的后缀)而自动推导出来的规则。
  • 变量定义:使用一个字符或字符串代表一段文本串,当定义了一个变量以后,Makefile后续在需要使用此文本串的地方,通过引用这个变量来实现对文本串的使用。
  • Makefile指示符:指示符指明在make程序读取Makefile文件过程中所要执行的一个动作。其中包括:
    • 读取一个文件,包含其他的makefile文件。
    • 决定(通常根据一个变量的值)处理或者忽略Makefile中的某一特定部分。
    • 定义一个多行变量。
  • 注释:Makefile中的“#”开始的行时注释。

包含其他makefile文件

  include指示符告诉make暂停读取当前的Makefile,而转去读取“include”指定的一个或者多个文件。完成后再继续当前makefile文件的读取。形式如下

include FILENAMEs

bar=bash bish
include foo *.mk $(bar)

include 使用场景
1. 多个makefile文件,有一些通用的变量和模式规则。放在单独一个文件里然后在其他makefile文件里include这个文件。
2. 根据源文件自动产生依赖文件时。将自动产生的依赖文件保存在单独的文件里,然后在主makefile里包含这个依赖文件。

包含文件的搜索路径。
先搜索当前目录,然后搜索命令行选项-I或者–include-dir指定的目录,如果没找到,则继续搜索/usr/gnu/include和/usr/local/include /usr/include 目录。

环境变量MAKEFILES,make执行时首先将此变量的值作为需要读入的Makefile文件,多个文件之间使用空格分开。类似使用指示符“include”包含其他的makefile文件一样,如果文件名非局对路径而且当前目录页不存在此文件,make会在一些默认的目录去寻找。
它和用“include”的区别:
1. 环境变量指定的makefile文件的目标不能作为终极目标。
2. 环境变量所定义的文件列表,在执行make时,如果不能找到其中一个文件,make不会提示错误,也不退出。
3. make在执行时,首先读取的是环境变量“MAKEFILE”所指定的文件列表,之后才是工作目录下的makefile文件,“include”所指定的文件是在make发现此关键字的时候暂停正在读取的文件而转去读取的。

此环境变量不推荐使用

变量MAKEFILE_LIST

make会通过include,环境变量等,包含一大堆makefile文件,MAKEFILE_LISTd的最后一个字包含当前正在被执行的文件名。

其他特殊变量

.VARIABLES 这个变量展开以后是此引用点之前、makefile文件中所定义的所有全局变量列表。包括:空变量和make的内嵌变量

Makefile的重建

重载另一个Makefile

有些情况下,存在两个比较类似的makefile文件。其中一个(makefile-A)需要使用另一个(makefile-B)中定义的变量和规则。通常我们会想到在makefile-A中使用指示符“include”包含“makefile-B”来达到目的。但使用这种方式,如果在两个makefile文件中存在相同的目标,而在不同的文件中其描述规则使用不同的命令。这样相同的布标文件就同时存在两个不同的规则命令,者时makefile所不允许的。
怎么办?Gnu make提供了另一种途径:在需要包含的makefile文件中定义一个称之为“所有匹配模式的规则,它用来描述哪些在“makeifle-A”中没有给出明确创建规则的目标重建规则。就是说,如果在当前makefile中找不到重建规则时,就是用“所有匹配模式”所在的规则来重建这个目标。
看一个例子,如果存在一个命名为“Makefile”的makefile文件,其中描述目标“foo”的规则和其他的一些规则,我们也可以书写一个内容如下命名为“GNUMakefile”的文件。

foo:
    frobnicate > foo

%: force
    @($MAKE) -f Makefile $@
force:;

执行命令“make foo”,make 可以找到目标foo的规则命令,实行之,如果执行另一个命令“make bar”,因为在“GUNmakefile”中没有这个目标。make就是用“所有匹配模式”规则,执行@($MAKE) -f Makefile bar。如果文件Makefile中存在这个目标更新的规则定义,这个规则就会被执行。依赖force保持了即使目标已经存在也会执行这个规则。force的规则使用空命令,是为了防止创建创建目标force时,又使用了模式规则”%:force”而陷入无限循环。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值