1.Makefile的作用
1 项目代码管理编译
2 节省编译项目时间
在不使用Makefile编译的时候不免都要在终端下输入:
gcc -o app a.c b.c c.c d.c
诸如此类的命令,反复的输入这类命令很浪费时间,然而有了Makefile之后复杂的命令就变成了make一个命令了。同时合适的Makefile会根据源码是否修改来决定是否重新编译源文件。
- 3 一次编写终生受益
写得好的Makefile通用性一般都很好,也就说说,在A项目中使用的Makefile稍作修改就能在B项目中使用了。
2. Makefile的基本规则
2.1 Makefile的基本形式
Makefile的形式可表示成:
目标:依赖(条件)
[Tab键]命令
Makefile的执行有两个阶段,第一个阶段是分析各个目标和条件的依赖关系,第二阶段就根据依赖关系自底向上执行命令。举例来看一个Makefile:
app:add.o sub.o dive.o mul.o main.o
gcc add.o sub.o dive.o mul.o main.o -o app
add.o:add.c
gcc -c add.c
sub.o:sub.c
gcc -c sub.c
dive.o:dive.c
gcc -c dive.c
mul.o:mul.c
gcc -c mul.c
main.o:main.c
gcc -c main.c
上面的Makefile文件中,app是一个目标,后面的.o文件都是依赖,这个Makefile的执行过程就是首先分析到app有5个依赖,那么就去指向这5个依赖,这5个依赖在他们的段内又是一个目标,在重复这个过程。最终自底向上的完成Makefile的执行过程。
2.2 Makefile执行目标
Makefile默认执行第一个出现的目标,也可以通过指定目标来让Makefile来执行非第一个出现的目标。最常见的一个就是make clean。项目在生成的过程中会产生很多中间中间文件,有时候并不需要这些文件,所以在Makefile的编写的时候一般都会写一个clean目标,用于删除中间文件。
app:add.o sub.o dive.o mul.o main.o
gcc add.o sub.o dive.o mul.o main.o -o app
add.o:add.c
gcc -c add.c
sub.o:sub.c
gcc -c sub.c
dive.o:dive.c
gcc -c dive.c
mul.o:mul.c
gcc -c mul.c
main.o:main.c
gcc -c main.c
clean:
-rm -f *.o
-rm -f app
3. 编写通用性好的Makefile
3.1 使用变量CC
在不同的平台下编译器异能不同,这里通过变量可以解决这个问题,同样是上述的Makefile,如果现在我想用g++来编译它,那么是不是需要把全部的gcc改写成g++呢?
CC=g++
app:add.o sub.o dive.o mul.o main.o
$(CC) add.o sub.o dive.o mul.o main.o -o app
add.o:add.c
$(CC) -c add.c
sub.o:sub.c
$(CC)-c sub.c
dive.o:dive.c
$(CC)-c dive.c
mul.o:mul.c
$(CC)-c mul.c
main.o:main.c
$(CC)-c main.c
clean:
-rm -f *.o
-rm -f app
3.2 隐含规则和模式规则
在makefile中
$@
表示目标,
$^
表示所有依赖,
$<
表示依赖中的第一个
$(wildcard *.c)
查找符合条件的文件名
$(patsubst %.c,%.o,$(src))
模式查找替换
根据这些规则Makefile再次修改成如下样貌:
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
target = app
$(target):$(obj)
gcc $^ -o $@
%.o:%.c
gcc -c $< -o $@
clean:
-rm -f *.o
-rm -f app
3.3 隐含规则和模式规则
CPPFLAGS
CFLAGS
LDFLAGS
.PHONY 伪目标声明
CPPFLAGS= -Iinclude
CFLAGS= -g -Wall
LDFLAGS=
CC=gcc
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
target = app
$(target):$(obj)
$(CC) $^ $(LDFLAGS) -o $@
%.o:%.c
$(CC) -c $< $(CFLAGS) $(CPPFLAGS) -o $@
.PHONY:clean
#彻底清除生生过程文件
clean:
-rm -f *.o
-rm -f app
#彻底清除生生过程文件和生成配置文件
distclean:
rm /usr/bin/app
install:
cp app /usr/bin