0x00 前言文章中的文字可能存在语法错误以及标点错误, 请谅解; 如果在文章中发现代码错误或其它问题请告知, 感谢! 0x01make 工具简介 make 工具是一个根据 makefile 文件内容, 针对目标 (可执行文件) 进行依赖性检测 (要生成该可执行文件之前要有哪些中间文件) 并执行相关动作 (编译等) 的工具 . 而这个 makefile 文件类似一个脚本, 其中内容包含 make 所要进行的处理动作以及依赖关系. 另外 make 的一个好处就是当你对某个源文件进行了修改, 你再次执行 make 命令, 它将只编译与该源文件相关的目标文件而不是整个代码工程, 因此, 为编译完最终的目标 (可执行文件) 节省了大量的时间提高工作连贯性. 比如一个工程下面有 A.c ,B.c, B.c 三个文件, 在 make 生成可执行目标文件之后, 改动了 A.c, 则再次 make 时, 只会执行有关 A.c 处理动作, 其它的不处理. 学习 make 工具, 需要明白三个概念: 目标, 依赖, 处理动作. makefile 所要进行的主要内容是明确目标, 明确目标所依赖的内容, 明确依赖条件满足时应该执行对应的处理动作. 例如我们最终要实现 a 这个目标, 但是需要依赖 b, 而 b 依赖于 c 的存在, 则可以描述为: a:b
- cmdbtoa
- b:c
- cmdctob
- 1
- 2
- 3
4":" 代表依赖, 另外每个处理动作之前都要用 tab 键分隔. 上述四行的意思是: a 依赖于 b, 而处理 cmdbtoa;b 依赖于 c, 而处理 cmdctob.0x02 实例首先准备三个文件, test1.c,test2.c,test2.h.test1.c:
- #include
- #include "test2.h"
- int main()
- {
- printf("This is test1!\n");
- PrintTest2();
- return 0;
- }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- test2.c
- #include
- #include "test2.h"
- void PrintTest2t()
- {
- printf("This is test2!\n");
- }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- test2.h
- #ifndef TEST2_H_
- #define TEST2_H_
- void PrintTest2();
- #endif
- 1
- 2
- 3
- 4
- 5
6 使用 ls 指令查看目录内容: 在这里插入图片描述有了上述三个代码文件后, 下面介绍使用三种 makefie 文件编写方式 1. 基础版新建一个文件, 命名为 makefile, 文件内容如下 (注意要用 tab 来分隔处理动作指令):test: test1.o test2.o
- gcc -Wall test1.o test2.o -o test
- test1.o: test1.c test2.h
- gcc -c -Wall test1.c -o test1.o
- test2.o: test2.c test2.h
- gcc -c -Wall test2.c -o test2.o
- clean:
- rm -rf *.o test
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
11 在这里插入图片描述然后在终端内输入 make 指令编译工程: 在这里插入图片描述再次使用 ls 查看目录多了. o 和可执行文件: 在这里插入图片描述对 makefile 里的指令进行解释: test: test1.o test2.o :test 依赖于 test1.o,test2.o 两个目标文件 gcc -Wall test1.o test2.o -o test: 编译出可执行文件 test.-o 表示指定的可执行文件名称 test1.o: test1.c test2.h:test1.o 依赖于 test1.c,test2.h 两个文件 gcc -c -Wall test1.c -o test1.o: 编译出 test1.o 文件,-c 表示只把给它的文件编译成目标文件, 用源码文件的文件名命名, 但把其后缀由 ".c" 变成 ".o".make clean: 删除掉所有. o 以及可执行文件, 当修改了某一个源文件使用该指令清除旧的文件. 在终端输入 "make clean" 实现: 在这里插入图片描述此时修改了 test2.c 中内容, 在 printf() 下一行增加一个无意义的回车, 然后使用 make 编译会发现只有跟 test2.c 有关的部分进行了处理, 这种自动化的进行依赖性检测和选择性执行必要的处理动作的工作, 体现了 make 的特色: 在这里插入图片描述 2. 使用变量版 makefile 内容如下: OBJS = test1.o test2.o
- G = gcc
- CFLAGS = -Wall -O -g
- test:$(OBJS)
- $(G) $(OBJS) -o test
- test1.o:test1.c test2.h
- $(G) $(CFLAGS) -c test1.c
- test2.o:test2.c test2.h
- $(G) $(CFLAGS) -c test2.c
- clean:
- rm -rf *.o test
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
15 在这个 makefile 中使用了变量, 变量的格式是 "varName = content"; 若要引用这个变量, 只需要用 $ 即可,$(varName).CFLAGS = -Wall -O -g 配置编译器设置, 并把它赋值给 CFLAGS 变量 - Wall: 输出所有警告信息 - O: 在编译时进行优化 - g: 表示编译 debug 版本使用 make 后生成文件同上: 在这里插入图片描述这样写的 Makefile 比较简单, 但是缺点显著, 每添加一个. c 文件, 就需要修改 Makefile 文件. 3 使用函数 makefile 内容如下 C = gcc
- G = g++
- CFLAGS = -Wall -O -g
- TARGET = ./test
- %.o:%.c
- $(C) $(CFLAGS) -c $< -o [email protected]
- %.o:%.cpp
- $(G) $(CFLAGS) -c $< -o [email protected]
- SOURCES = $(wildcard *.c *.cpp)
- OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
- $(TARGET):$(OBJS)
- $(G) $(OBJS) -o $(TARGET)
- chmod a+x $(TARGET)
- clean:
- rm -rf *.o test
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
%.o:%.c$© $(CFLAGS) -c $< -o [email protected]%.o:%.cpp
$(G) $(CFLAGS) -c $< -o [email protected] 表示把所有的. c,.cpp 文件编译成. o 文件. SOURCES = $(wildcard *.c *.cpp) 表示产生一个所有以. c,.cpp 结尾的文件列表, 然后存入变量 SOURCES 里. OBJS = $ (patsubst %.c,%.o,$ (patsubst %.cpp,%.o,$(SOURCES))) 把 SOURCES 文件列表中所有. cpp 变成. o,.c 变成. o, 然后形成一个新的列表, 存入 OBJS 变量.$ @扩展成当前规则的目的文件名,$ < 扩展成依靠列表中的第一个依靠文件,$^ 扩展成整个依靠的列表 (除掉里面所有重复的文件名).chmod a+x $(TARGET) 表示把 firstTest 强制变成可执行文件. 使用 make 后生成文件同上: 在这里插入图片描述以上.----------------
来源: http://www.bubuko.com/infodetail-3529874.html