学习资料
跟我一起学makefile
准备vs code
gcc 参数详解
- -c
-c”选项我们上面说了,是只编译不链接
他将生成 .o 的 obj 文件
例子用法:
gcc -c hello.c
- -S
只激活预处理和编译,就是指把文件编译成为汇编代码。
例子用法:
gcc -S hello.c
他将生成 .s 的汇编代码,你可以用文本编辑器察看。
- -E
只激活预处理,这个不生成文件, 你需要把它重定向到一个输出文件里面。
例子用法:
gcc -E hello.c > pianoapan.txt
gcc -E hello.c | more
慢慢看吧, 一个 hello word 也要与处理成800行的代码。
- -o
制定目标名称, 默认的时候, gcc 编译出来的文件是 a.out, 很难听, 如果你和我有同感,改掉它, 哈哈。
例子用法:
gcc -o hello.asm -S hello.c
gcc编译流程-shell脚本去编译
gcc编译的四个过程
案例:hello.c编译一个可执行文件
shell.sh 文件内容如下
#!/bin/bash
# 使用-o 替换名称名称
gcc -E main.c -o main.i
gcc -S main.i -o main.s
gcc -c main.s -o main.o
gcc main.o -o main
编译完成后生产如上图文件。
makefile 介绍
把源文件编译成中间代码文件UNIX 下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的 Object File 合成执行文件,这个动作叫作链接(link)。
makefile 规则介绍
target ... : prerequisites ...
command
...
...
...
- target :也就是一个目标文件,可以是 Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性
- prerequisites: 就是,要生成那个 target 所需要的文件或是目标
- command 也就是 make 需要执行的命令。(任意的 Shell 命令)
target 这一个或多个的目标文件依赖于prerequisites 中的文件,其生成规则定义在 command 中。
说白一点就是说,prerequisites中如果有一个以上的文件比 target 文件要新的话,command 所定义的命令就会被执行。
这就是 Makefile 的规则。也就是 Makefile 中最核心的内容。
“=”和“:=”的区别
object = yql
curname = $(object)
curname1 := $(object)
object = other
print:
@echo curname:$(curname)
@echo curname:$(curname1)
- 赋值符“:=”不会使用后面定义的变量,只能使用前面已经定义好的
“?=”和“+=”案例
- ?=:如果变量 curname 前面没有被赋值,那么此变量 yql
- +=:变量追加
object = yql
curname ?= $(object)
curname += $(object)
print:
@echo curname:$(curname)
案例3个.c和2个.- 使用makefile编译
代码如下
main.c
#include <stdio.h>
#include "input.h"
#include "calcu.h"
int main(int argc, char *argv[])
{
int a, b, num;
input_int(&a, &b);
num = calcu(a, b);
printf("%d + %d = %d\r\n", a, b, num);
}
input.c
#include <stdio.h>
#include "input.h"
void input_int(int *a, int *b)
{
printf("input two num:");
scanf("%d %d", a, b);
printf("\r\n");
}
calcu.c
#include "calcu.h"
int calcu(int a, int b)
{
return (a + b);
}
calcu.h
#ifndef _CALCU_H
#define _CALCU_H
int calcu(int a, int b);
#endif
input.h
#ifndef _INPUT_H
#define _INPUT_H
void input_int(int *a, int *b);
#endif
使用shell脚本编译
gcc -c main.c
gcc -c input.c
gcc -c calcu.c
# 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件**他将生成 .o 的 obj 文件**
gcc main.o input.o calcu.o -o main
使用makefile 方式编译
main : main.o input.o calcu.o
gcc -o main main.o input.o calcu.o
main.o: main.c
gcc -c main.c
input.o: input.c
gcc -c input.c
calcu.o: calcu.c
gcc -c calcu.c
clean :
rm *.o
rm main
在第一次编译的时候
由于 main 还不存在,因此第一条规则会执行,第一条规则依赖于文件 main.o、input.o 和 calcu.o这个三个.o 文件,
这三个.o 文件目前还都没有,因此必须先更新这三个文件。make 会查找以这三个.o 文件为目标的规则并执行。
makefile 变量
- #使用"$"获取变量object的值为main.o input.o calcu.o
object = main.o input.o calcu.o
main : $(object)
gcc -o main $(object) #使用"$"获取变量object的值为main.o input.o calcu.o
main.o: main.c
gcc -c main.c
input.o: input.c
gcc -c input.c
calcu.o: calcu.c
gcc -c calcu.c
clean :
rm *.o
rm main
注意:图片验证了这段话----第一条规则依赖于文件 main.o、input.o 和 calcu.o这个三个.o 文件,
这三个.o 文件目前还都没有,因此必须先更新这三个文件。make 会查找以这三个.o 文件为目标的规则并执行。
make 自动推导–优化一
GNU 的 make 很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必
要去在每一个[.o]文件后都写上类似的命令,因为,我们的 make 会自动识别,并自己推导
命令。
只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make找到一个whatever.o,那么whatever.c,就会是 whatever.o 的依赖文件。
并且 cc -c whatever.c 也会被推导出来,于是,我们的 makefile 再不用写得这么复杂。我们的是新
的 makefile 又出炉了。
object = main.o input.o calcu.o
main : $(object)
gcc -o main $(object) #使用"$"获取变量object的值为main.o input.o calcu.o
main.o: input.h calcu.h
input.o: input.h
calcu.o: calcu.h
.PHONY : clean
clean :
rm *.o
rm main
make 自动推导–优化二
object = main.o input.o calcu.o
main : $(object)
cc -o main $(object) #使用"$"获取变量object的值为main.o input.o calcu.o
$(object): input.h calcu.h
.PHONY : clean
clean :
rm *.o
rm main
## make 自动推导–优化三(通配符)%
- %:表示对文件名的匹配,“%”表示长度任意的非空字符串
- 举例:比如“%.c”就是所有的以.c 结尾的文件
- 举例a.%.c 就表示以 a.开头,以.c 结束的所有文件。
object = main.o input.o calcu.o
main : $(object)
cc -o main $(object)
%.o : %.c
gcc -c $< #依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<”就是符合模式的一系列的文件集合。
.PHONY : clean
clean :
rm *.o
rm main
## make 自动推导–优化四(通配符)*
object = main.o input.o calcu.o
main : $(object)
cc -o main $(object)
*.o : *.c
gcc -c $< #依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<”就是符合模式的一系列的文件集合。
.PHONY : clean
clean :
rm *.o
rm main
伪目标 .PHONY :clean
上述规则中并没有创建文件 clean 的命令,因此工作目录下永远都不会存在文件 clean,当我们输入“make clean”以后,后面的“rm *.o”和“rm main”总是会执行。可是如果我们“手贱”,在工作目录下创建一个名为“clean”的文件,那就不一样了,当执行“make clean”的时候,规则因为没有依赖文件,所以目标被认为是最新的,因此后面的 rm 命令也就不会执行
object = main.o input.o calcu.o
main : $(object)
cc -o main $(object)
%.o : %.c
gcc -c $< #依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<”就是符合模式的一系列的文件集合。
.PHONY : clean
clean :
rm *.o
rm main
判断语句使用
关键字 | 功能 |
---|---|
ifeq | 判断参数是否不相等,相等为 true,不相等为 false。 |
ifneq | 判断参数是否不相等,不相等为 true,相等为 false。 |
ifdef | 判断是否有值,有值为 true,没有值为 false。 |
ifndef | 判断参数是否不相等,相等为 true,不相等为 false。 |
条件判断的使用方式如下:
ifeq (ARG1, ARG2)
ifeq ‘ARG1’ ‘ARG2’
ifeq “ARG1” “ARG2”
ifeq “ARG1” ‘ARG2’
ifeq ‘ARG1’ “ARG2”
案例说明