二. MakeFile

目录

一. 概述

二. Makefile介绍

2.1 语法规则

2.2 一个示例

2.3. make是如何工作的

2.4. Makefile中使用变量

2.5 让make自动推导

2.6 另类风格的makefile

三. Makefile总述

3.1 Makefile里有什么

3.2 make的工作方式

四. 变量

五. 预定义变量

六. 函数

七. 伪目标 .PHONY

八. 其他常用功能

九. 嵌套执行Makefile

十. 指定库文件路径

十一. 参考链接


一. 概述

如果我们在终端输入GCC命令一个一个编译,文件一多就不太现实,这样我们就可以使用一个工程编译工具:make,描述哪些文件需要编译,哪些需要重新编译的文件叫做Makefile,Makefile就跟脚本文件一样,Makefile里面还可以执行系统命令。使用的时候只需要一个make命令即可完成整个工程的自动编译。

二. Makefile介绍

2.1 语法规则

目标 ... : 依赖 ...
	命令1
	命令2
	. . .
//默认情况下Makefile的第一个目标为终极目标
//依赖:即目标文件由哪些文件生成
//命令:即通过执行命令由依赖文件生成目标文件。每条命令之前必须有一个tab
//all:Makefile文件默认只生成第一个目标文件即完成编译,但是我们可以通过all 指定所需要生成的目
//标文件。例如下面的例子。
all: target1 target2 target3
target1:
# 编译规则1
target2:
# 编译规则2
target3:
# 编译规则3


2.2 一个示例

edit : main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 
cc -o edit main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 
 
main.o : main.c defs.h 
gcc -c main.c 
kbd.o : kbd.c defs.h command.h 
gcc -c kbd.c 
command.o : command.c defs.h command.h 
gcc -c command.c 
display.o : display.c defs.h buffer.h 
gcc -c display.c 
insert.o : insert.c defs.h buffer.h 
gcc -c insert.c 
search.o : search.c defs.h buffer.h 
gcc -c search.c 
files.o : files.c defs.h buffer.h command.h 
gcc -c files.c
utils.o : utils.c defs.h 
gcc -c utils.c 
clean : 
rm edit main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o

反斜杠(\)是换行符的意思。这样比较便于 Makefile 的易读。我们可以把这个内容保 存在文件为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make” 就可以生成执行文件 edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单 地执行一下“make clean”就可以了。

2.3. make是如何工作的

在默认的方式下,也就是我们只输入 make 命令。那么,

1、make 会在当前目录下找名字叫“Makefile”或“makefile”的文件。

2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到 “edit”这个文件,并把这个文件作为最终的目标文件。

3、如果 edit 文件不存在,或是 edit 所依赖的后面的 .o 文件的文件修改时间要比 edit 这个文件新,那么,他就会执行后面所定义的命令来生成 edit 这个文件。

4、如果 edit 所依赖的.o 文件也存在,那么 make 会在当前文件中找目标为.o 文件的依 赖性,如果找到则再根据那一个规则生成.o 文件。(这有点像一个堆栈的过程)

5、当然,你的 C 文件和 H 文件是存在的啦,于是 make 会生成 .o 文件,然后再用 .o 文 件生命 make 的终极任务,也就是执行文件 edit 了。

2.4. Makefile中使用变量

比如:

objects = main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o

于是,我们就可以很方便地在我们的 makefile 中以“$(objects)”的方式来使用这个 变量了,于是我们的改良版 makefile 就变成下面这个样子:

objects = main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 
 
edit : $(objects) 
cc -o edit $(objects) 

main.o : main.c defs.h 
cc -c main.c 
kbd.o : kbd.c defs.h command.h 
cc -c kbd.c 
command.o : command.c defs.h command.h 
cc -c command.c 
display.o : display.c defs.h buffer.h 
cc -c display.c 
insert.o : insert.c defs.h buffer.h 
cc -c insert.c 
search.o : search.c defs.h buffer.h 
cc -c search.c 
files.o : files.c defs.h buffer.h command.h 
cc -c files.c 
utils.o : utils.c defs.h 
cc -c utils.c 

clean : 
rm edit $(objects) 

2.5 让make自动推导

只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make 找到一个 whatever.o,那么 whatever.c,就会是 whatever.o 的依赖文件。并且 cc -c whatever.c 也会被推导出来。

objects = main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 
 
edit : $(objects) 
cc -o edit $(objects) 
 
main.o : defs.h 
kbd.o : defs.h command.h 
command.o : defs.h command.h 
display.o : defs.h buffer.h 
insert.o : defs.h buffer.h 
search.o : defs.h buffer.h 
files.o : defs.h buffer.h command.h 
utils.o : defs.h 
 
.PHONY : clean 
clean : 
rm edit $(objects) 

2.6 另类风格的makefile

即然我们的 make 可以自动推导命令,那么我看到那堆[.o]和[.h]的依赖就有点不爽, 那么多的重复的[.h],能不能把其收拢起来,好吧,没有问题,这个对于 make 来说很容易, 谁叫它提供了自动推导命令和文件的功能呢?来看看最新风格的 makefile 吧。

objects = main.o kbd.o command.o display.o \ 
insert.o search.o files.o utils.o 
 
edit : $(objects) 
cc -o edit $(objects) 
 
$(objects) : defs.h 
kbd.o command.o files.o : command.h 
display.o insert.o search.o files.o : buffer.h 
 
.PHONY : clean 
clean : 
rm edit $(objects) 

这种风格,让我们的makefile变得很简单,但我们的文件依赖关系就显得有点凌乱了。

三. Makefile总述

3.1 Makefile里有什么

Makefile 里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。

3.2 make的工作方式

1、读入所有的 Makefile。 
2、读入被 include 的其它 Makefile。 
3、初始化文件中的变量。 
4、推导隐晦规则,并分析所有规则。 
5、为所有的目标文件创建依赖关系链。 
6、根据依赖关系,决定哪些目标要重新生成。 
7、执行生成命令。

四. 变量

1、"="是最普通的等号,在Makefile中容易搞错赋值等号,使用 “=”进行赋值,变量的值是整个Makefile中最后被指定的值

2、“:=” 表示直接赋值,赋予当前位置的值。":="才是真正意义上的直接赋值

3、“?=” 表示如果该变量没有被赋值,赋值予等号后面的值。

4、"+="和平时写代码的理解是一样的,表示将符号后面的值添加到前面的变量上

五. 预定义变量

//CC:c编译器的名称,默认值为cc。cpp c预编译器的名称默认值为$(CC) -E
CC = gcc
//回显问题,Makefile中的命令都会被打印出来。如果不想打印命令部分 可以使用@去除回显
@echo "clean done!"

六. 函数

//通配符
SRC = $(wildcard ./*.c)
//匹配目录下所有.c 文件,并将其赋值给SRC变量。
OBJ = $(patsubst %.c, %.o, $(SRC))
这个函数有三个参数,意思是取出SRC中的所有值,然后将.c 替换为.o 最后赋值给OBJ变量。
示例:如果目录下有很多个.c 源文件,就不需要写很多条规则语句了,而是可以像下面这样写

SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
 
ALL: hello.out
 
hello.out: $(OBJ)
        gcc $(OBJ) -o hello.out
 
%.o: %.c
        gcc -c $< -o $@

七. 伪目标 .PHONY

伪目标只是一个标签,clean是个伪目标没有依赖文件,只有用make来调用时才会执行
当目录下有与make 命令 同名的文件时 执行make 命令就会出现错误。
解决办法就是使用伪目标

SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
 
ALL: hello.out
 
hello.out: $(OBJ)
        gcc $< -o $@
 
$(OBJ): $(SRC)
        gcc -c $< -o $@
 
clean:
        rm -rf $(OBJ) hello.out
 
.PHONY: clean ALL

八. 其他常用功能

代码清理clean

SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
 
ALL: hello.out
 
hello.out: $(OBJ)
        gcc $< -o $@
 
$(OBJ): $(SRC)
        gcc -c $< -o $@
 
clean:
        rm -rf $(OBJ) hello.out

九. 嵌套执行Makefile

在一些大工程中,会把不同模块或不同功能的源文件放在不同的目录中,我们可以在每个目录中都写一个该目录的Makefile这有利于让我们的Makefile变的更加简洁,不至于把所有东西全部写在一个Makefile中。
  列如在子目录subdir目录下有个Makefile文件,来指明这个目录下文件的编译规则。外部总Makefile可以这样写

subsystem:
            cd subdir && $(MAKE)
其等价于:
subsystem:
            $(MAKE) -C subdir

定义$(MAKE)宏变量的意思是,也许我们的make需要一些参数,所以定义成一个变量比较有利于维护。两个例子意思都是先进入"subdir"目录,然后执行make命令
我们把这个Makefile叫做总控Makefile,总控Makefile的变量可以传递到下级的Makefile中,但是不会覆盖下层Makefile中所定义的变量,除非指定了 "-e"参数。
如果传递变量到下级Makefile中,那么可以使用这样的声明
export
如果不想让某些变量传递到下级Makefile,可以使用
unexport

export variable = value
等价于
variable = value
export variable
等价于
export variable := value
等价于
variable := value
export variable
如果需要传递所有变量,那么只要一个export就行了。后面什么也不用跟,表示传递所有变量

八. 指定头文件路径

将该目录添加到头文件搜索路径中
在Makefile中则可以这样写:、

CFLAGS=-I/home/develop/include

然后在编译的时候,引用CFLAGS即可,如下

yourapp:*.c
    gcc $(CFLAGS) -o yourapp

十. 指定库文件路径

//与上面指定头文件类似只不过使用的是"-L"来指定
LDFLAGS=-L/usr/lib -L/path/to/your/lib
//告诉链接器要链接哪些库文件,使用"-l"(小写L)如下:
LIBS = -lpthread -liconv

十一. 参考链接

1. Makefile入门(超详细一文读懂)-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值