在linux系统上编译大一点的项目时,会用到make/makefile文件
1.make与makefile
利用make工具,我们可以将大型的开发项目分解成为多个更易于管理的模块,对于一个包括几百个源文件的应用程序,使用make和makefile工具就可以简洁明快地理顺各个源文件之间纷繁复杂的相互关系。 而且如此多的源文件,如果每次都要键入gcc命令进行编译的话,那对程序员来说简直就是一场灾难。 而make工具则可自动完成编译工作,并且可以只对程序员在上次编译后修改过的部分进行编译。 因此,有效的利用make和makefile工具可以大大提高项目开发的效率。
-
make工具功能
-
利用make工具可以自动完成编译工作,这些工作包括:
- 如果修改了某几个源文件,则只重新编译这几个源文件
- 如果某个头文件被修改了,则重新编译所有包含该头文件的源文件
-
利用这种自动编译可以大大简化开发工作,避免不必要的重新编译。make工具通过一个称为Makefile的文件来完成并自动维护编译工作,Makefile文件描述了整个工程的编译、连接规则。
-
makefile工具功能
-
Makefile描述了整个工程的编译连接规则。
TARGET…: DEPENDENCIES…
COMMAND
TARGER:目标程序产生的文件,如可执行文件和目标文件,目标也可以是要执行的动作,如clean,也称为伪目标
DEPENDENCIES:依赖是用来产生目标的输入文件列表,一个目标通常依赖与多个文件。
COMMAND:命令是make执行的动作(命令是shell命令或是可在shell下执行的程序),注意每个命令行的起始字符必须为TAB字符。
如果DEPENDENCIES中有一个或多个文件更新的话,COMMAND就要执行,这就是Makefile最核心的内容。
…
makefile文件结构实例
//有五个文件:add.c add.h sub.c sub.h main.c
main:main.o add.o sub.o //【目标文件是main,它依赖于main.o,add.o,sub.o这三个文件】
gcc -Wall -g main.o sub.o -o main
mian.o main.c
gcc -Wall -g -c mian.c -o main.o
add.o:add.c
gcc -Wall -g -c add.c -o add.o
sub.o:sub.c
gcc -Wall -g -c sub.c -o sub.o
clean : //这是一个伪目标,等于执行了某一个动作
rm -f $ (OBJECTS) main
//$ (OBJECTS)变量的使用
// 【$@】:规则的目标文件名
// 【$<】 :规则的第一个依赖文件名
// 【$^】:规则的所有依赖文件列表
//OBJECTS = main.o add .o sub.o 【OBJECTS是自定义的变量名】
//main:$(OBJECTS) 【可以在需要的地方使用变量名进行替换,替换规则为$(变量名)】
复杂例子
BIN = main main2
OBJECTS= main.o add.o sub.o
CC = gcc
CFALGS = -Wall -g
all : $(BIN)
main : $(OBJECTS)
$(CC) $(CFALGS) $< -o $@
main2: $(OBJECTS)
$(CC) $(CFALGS) $< -o $@
.o .c : 【关注重点在这里】
$(CC) $(CFALGS) -c $< -o $@
clean :
rm -f $(OBJECTS) $(BIN)
//makefile中嵌套shell函数
CC = gcc
CFLAGS = -Wall -g
BIN = main
SUBDIR = $(shell ls -d */) 【SUBDIR变量保存了子目录的列表】
ROOTSRC = $(wildcard *.c) 【ROOTSRC保存了当前目录下的.c文件列表】
ROOTOBJ = $(ROOTSRC:%.c = %.o) 【ROOTBOJ 保存了当前目录下.c文件同名的.o列表】
SUBSRC = $(shell find $(SUBDIR) -name '*.c') 【SUBSRC 保存了所有子目录下的的.c文件】
SUBOBJ = $(SUBSRC:%.c = %.o) 【SUBOBJ保存了所有子目录下的.c文件同名的.o文件列表】
$(BIN):$(ROOTOBJ) $(SUBOBJ) 【main的生成依赖与当前目录及所有子目录下的.o文件】
$(CC) $(CFLAGS) -o $(BIN) $(ROOTOBJ) $(SUBOBJ)
.o .c:
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(BIN) $(ROOTOBJ) $(SUBOBJ)
- makefile中的元素含义及注意事项
(1)targets元素
①通常是需要生成的目标文件名
②make所需要执行的命令名称
③targets可以包含多个目标,使用空格对多个目标名进行分隔。
④工程开发中可以将最终可执行文件名和all同时作为makefile的第1条规则的目标。这样当执行make时会自动根据hello.out与依赖来判断是否执行命令,也可以使用make all来强制执行命令。
hello.out all: main.o func.o
gcc -o hello.out main.o func.o
(2)prerequisities元素:
①当前目标所依赖的其它目标或文件。
②可以包含多个依赖,使用空格对多个依赖进行分隔
(3)command元素:
①完成目标所需要执行的命令
②每个命令行必须以[Tab]字符开始,该字符告诉make此行是一个命令行
③续行符:\。可以将内容分开写到下一行,提高可读性
④命令前加上@符,表示命令无回显。