make 工程管理器
只要将上课讲的这些掌握即可。会写最简单的情况和最终版的情况。
每个公司都有自己的编译框架。编译框架中连makefile都是自动产生的。
所以一是不一定写;二是不一定让你写,有的会有专门的人写;三是看得懂,能改就行。
make是增量编译。只把修改过的.c编译成.o,然后把所有的.o进行链接。如果没有修改,就不编。
Makefile1(最简单的情况)
main:main.o func.o //目标项:依赖项
gcc main.o func.o -o main //必须按TAB键
main.o:main.c
gcc -c main.c
func.o:func.c
gcc -c func.c
.PHONY:clean //.PHONY是Makefile的关键字,表示后面的是伪目标、假目标。
clean: //伪目标通常用在清理文件、强制重新编译等情况。
rm -rf main.o func.o main
Makefile2(使用自定义变量之后)
OBJS:=main.o func.o //变量的定义
ELF:=main
$(ELF):$(OBJS) //变量的引用
gcc $(OBJS) -o $(ELF)
main.o:main.c
gcc -c main.c
func.o:func.c
gcc -c func.c
.PHONY:clean
clean:
rm -rf $(OBJS) $(ELF)
Makefile3:自动变量
OBJS:=main.o func.o
ELF:=main
$(ELF):$(OBJS) gcc $^ -o $@ //$@:当前规则的目标文件$(ELF);$^:当前规则的所有依赖文件$(OBJS)
main.o:main.c
gcc -c main.c
func.o:func.c
gcc -c func.c
.PHONY:clean
clean:
rm -rf $(OBJS) $(ELF)
Makefile4:(使用预定义变量)
OBJS:=main.o func.o //自定义变量
ELF:=main
CFLAGS:=-Wall -g //这是预定义变量。-g表示增加调试信息
CC:=gcc //这是预定义变量
$(ELF):$(OBJS) $(CC) $^ $(CFLAGS) -o $@ //自动变量:$@:当前规则的目标文件;$^:当前规则的所有依赖文件
main.o:main.c
$(CC) -c main.c
func.o:func.c
$(CC) -c func.c
.PHONY:clean
clean:
rm -rf $(OBJS) $(ELF)
Makefile5:(使用隐含规则)
OBJS:=main.o func.o
ELF:=main
CFLAGS:=-Wall
CC:=gcc
$(ELF):$(OBJS) $(CC) $^ $(CFLAGS) -o $@ //$@:当前规则的目标文件;$^:当前规则的所有依赖文件
//隐含规则:.o自动依赖于.c,可以省略
.PHONY:clean
clean:
rm -rf $(OBJS) $(ELF)
Makefile6(使用函数后的最终版)
SOURCES:=$(wildcard *.c) //把当前目录下的所有.c文件存入变量SOURCES里
OBJS:=$(patsubst %.c,%.o,$(SOURCES)) //自定义变量。函数。把SOURCES中的.c 换成.o
ELF:=main //自定义变量
CFLAGS:=-Wall //预定义变量
CC:=gcc //预定义变量
$(ELF):$(OBJS) $(CC) $^ $(CFLAGS) -o $@ //自动变量。$@:当前规则的目标文件;$^:当前规则的所有依赖文件
//隐式规则
.PHONY:clean //.PHONY是Makefile的关键字,表示后面是伪目标
clean:
rm -rf $(OBJS) $(ELF)
make:把gcc保存下来。
一般怀疑别人动过了.o 就需要重新编译。
变量的递归展开。不常用,容易把人搞晕。
模式规则:
通配符% 代表1-多个字符
函数:
wildcard搜索当前目录下的文件名,展开成一列所有符合由其参数描述的文件名,文件间以空格间隔。SOURCES = $(wildcard *.cpp)把当前目录下所有'.cpp'文件存入变量 SOURCES 里。