◆make是什么?
make是一个命令工具,是一个解释makefile中指令的命令工具。它可以简化编译过程里面所下达的指令,当执行 make 时,make 会在当前的目录下搜寻 Makefile (or makefile) 这个文本文件,执行对应的操作。make 会自动的判别原始码是否经过变动了,而自动更新执行档。
◆为什么要使用make?
假设,现在一个项目里面包含了100个程序文件,如果要对这个项目进行编译,那么光是编译指令就有100条。如果要重新进行编译,那么就又得像之前一样重新来一遍。这样重复且繁琐的工作实在是让我们很不爽啊。所以,用make来进行操作,间接调用gcc岂不是很方便?如果我们更动过某些原始码档案,则 make 也可以主动的判断哪一个原始码与相关的目标文件档案有更新过, 并仅更新该档案。这样可以减少重新编译所需要的时间,也会更加方便。
◆makefile又是干什么的?
makefile其实就是一个文档,里面定义了一系列的规则指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,它记录了原始码如何编译的详细信息! makefile一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
先看一下makefile的规则:
目标(target):目标文件1 目标文件2
<Tab>gcc -o 欲建立的执行文件 目标文件1 目标文件2
目标(target)就是我们想要建立的信息,而目标文件就是具有相关性的 object files ,建立执行文件的语法就是以 <tab> 按键开头的那一行!特别留意,『命令行必须要以 tab 按键作为开头』才行!它的规则基本上是这样的:
•在 makefile 当中的 # 代表批注;
•<tab> 需要在命令行 (例如 gcc 这个编译程序指令) 的第一个字符;
•标的 (target) 与相依档案(就是目标文件)之间需以『 :』隔开。
1. 接下来就根据这个Makefile基本规则来编写一个最基本的Makefile文件
.PHONY:clean
main:main.o sub.o add.o print.o
gcc -Wall -g main.o add.o sub.o print.o -o main
main.o:main.c
gcc -Wall -g -c main.c -o main.o
add.o:add.c add.h
gcc -Wall -g -c add.c -o add.o
sub.o:sub.c sub.h
gcc -Wall -g -c sub.c -o sub.o
print.o:print.c print.h
gcc -Wall -g -c print.c -o print.o
clean:
rm -f *.o main
我们可以看到,main是我们最终想要生成的目标文件,它依赖main.o sub.o add.o print.o这四个.o文件。因此要执行gcc -Wall -g main.o add.o sub.o print.o -o main命令来生成目标文件,但是当前没有这些.o文件,因此就要先生成这些.o文件。我们写了四条xxx.o:xxx.c然后执行gcc -Wall -g -c xxx.c -o xxx.o,这些语句就会生成目标文件的依赖项。
-Wall : 生成所有警告信息 -g : 在编译的时候,产生调试信息。
clean是一个伪目标文件,因为它没有依赖项。我们只是想通过make clean来将.o文件删除,但是我们通常要指定.PHONY:clean这条语句,用来显式的指定clean是伪目标,来防止当前目录下有一个同名的clean文件。这样,一个简单呢的Makefile文件就写好了。
2. Makefile自动化变量
虽然像上述那样可以完成编译,但是明显非常麻烦,接下来介绍Makefile的自动化变量。
选项名 作用
$@ 规则的目标文件名
$< 规则的第一个依赖文件名
$^ 规则的所有依赖文件列表
我们使用这些自动化变量来尝试从写刚才的Makefile
.PHONY:clean
OBJ=main.o sub.o add.o print.o
main:$(OBJ)
gcc -Wall -g $^ -o $@
main.o:main.c
gcc -Wall -g -c $< -o $@
add.o:add.c add.h
gcc -Wall -g -c $< -o $@
sub.o:sub.c sub.h
gcc -Wall -g -c $< -o $@
print.o:print.c print.h
gcc -Wall -g -c $< -o $@
clean:
rm -f *.o main
我们定义了一个变量叫OBJ,他是我们的依赖项列表。然后使用自动化变量来代替对应的文件,如上所示。
3. 但是,我们这些.c文件都要生成.o文件,这样写也非常麻烦,我们介绍另一些规则。
模式规则
%.o:%.c
后缀规则
.c:.o
我们来使用这两种规则:
.PHONY:clean
CC = gcc
CFLAGS = -Wall -g
OBJ = main.o sub.o add.o print.o
main:$(OBJ)
$(CC) $(CFLAGS) $^ -o $@
#%.o:%.c
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o main
使用这两个规则,就会将所有.c文件生成同名的.o文件,这样,Makefile就更加简洁。
4. make常用的内嵌函数
函数调用
$(function arguments)
$(wildcard PATTERN)
当前目录写的匹配模式的文件
例如:src=$(wildcard *.c)
$(patsubst PATTERN,REPLACEMENT,TEXT)
模式替换函数
例如:$(patsubst %.c, %.o, \$src)
等价于$(src:.c=.o)
shell函数
执行shell命令
例如:$(shell ls -d */)
下面是另一个实例:
OBJS:=deviceIo.o server.o sndData.o tool.o main.o
CC:=gcc -m32
CFLAGS:= -Wall
all: program
program: $(OBJS)
$(CC) $(CFLAGS) $^ -o $@ -lpthread
main.o: main.c tool.h server.h deviceIo.h common.h log.h sndData.h
$(CC) $(CFLAGS) -c $< -o $@ -lpthread
deviceIo.o: deviceIo.c tool.h server.h deviceIo.h common.h log.h sndData.h
$(CC) $(CFLAGS) -c $< -o $@ -lpthread
server.o: server.c tool.h server.h deviceIo.h common.h log.h sndData.h
$(CC) $(CFLAGS) -c $< -o $@ -lpthread
sndData.o: sndData.c tool.h server.h deviceIo.h common.h log.h sndData.h
$(CC) $(CFLAGS) -c $< -o $@ -lpthread
tool.o: tool.c tool.h server.h deviceIo.h common.h log.h sndData.h
$(CC) $(CFLAGS) -c $< -o $@ -lpthread
clean:
$(RM) program $(OBJS)