预编译: 处理以# 开头的指令 , 比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。
汇编 :把C语言编译成汇编语言
编译 :把汇编语言的文件编译成计算机能看懂的二进制文件
gcc(编译工具)的编译过程
gcc -[参数] relying_file -o dest_filename 目标文件 依赖文件 gcc可以追加多个参数
参数: -o 把gcc的参数生成的东西输出到指定文件里不存在则创建
当然gcc有个隐式规则, 可直接生成.o文
-E 预编译 基于 .c 生成 .i 预编译过的文件
-S 汇编 基于 .i 生成 .s 汇编文件
-c 编译 基于 .s 生成 .o 二进制文件
-g 生成符号表方便gdb调试时参考代码
-c 编译而不链接
-o 生成的文件 .c .i .s .o ,优化生成目标文件, 以最小最优为前提
-O和 -O1指定1级优化
-O2 指定2级优化
-O3 指定3级优化
-O0指定不优化
-D 快速控制代码是否执行 和#ifdefine 作用一样
-I 可指定查找include文件的其他位置 如:gcc -c -I/usr/local/include -I/opt/include hello.c
-L 指定链接库的搜索目录 gcc -o main mian.o -L/usr/lib ,一般都是使用手动安装的自定义库时用
-l(小写L)指定链接库的名字 gcc -o main mian.o -lqt 系统会在环境变量里查找自动安装的库
-Wall 提升警告
-static 静态编译的文件更大, 动态链接库编译则比较小
.c----(预编译)-----> .i ----(汇编)-----> .s ----(编译)-----> .o ---------> ELF(可执行文件)
可在gcc后面追加多个参数及其值
只有gcc [filname] 的话会默认生成一个a.out的可执行文件 , 加-o可指定的生成目标文件
Makefile: 控制指导gcc的工作 批量的生成指定文件
make语法:
目标文件:依赖文件
命令(基于依赖文件使用gcc生成目标文件)
因为依赖会有传递性的,make会执行第一行 如果生成目标文件时依赖文件不存在则会找后面是否有生成依赖文件的命令,这样逐层的生成最终的目标文件
hello:hello.o 依赖.o生成elf文件如果.o不存在则执行第二行
gcc hello.o -o hello
hello.o:hello.s 依赖.s生成.o文件 如果.s不存在则执行第三行以此类推
gcc hello.s -o hello.o
hello.s:hello.i
gcc hello.i -o hello.s
hello.i:hello.c
gcc hello.c -o hello.c
makefile的变量:
OBJ = 代表常量
OBJ := 可追加变量
OBJ += 变量追加
引用变量 $(变量名)
比如: 定义变量 OBJ := a.o b.o 变量追加 OBJ += c.o 引用变量 gcc -o hello $(OBJ) 依赖变量里的文件生成elf文件hello
伪目标: make中提供了一个关键字 .PHONY 用于定义一个伪目标, make不再将伪目标当做实际文件处理, 而当成一种标签 , 标签代表了rm -rf x.o这个命令,当make后面加上这个标签 make clean 时会执行这段删除命令, 如果只是 make 则执行 hello:hello.o 这个生成目标
.PHONY:
clean:
rm-rf x.o
通配符:
% 任意一个 %.c 任意一个.c文件
? 匹配 a?c.c 匹配 abc.c acc.c aac.c 等文件
* 所有 *.c 所有的.c文件
$@ 代表目标文件
$^ 代表依赖文件
$< 代表第一个依赖文件
隐式规则: gcc -o a.o a.c 为什么可直接基于.c 生成 .o 而不用再经过 .i .s 等过程? 因为编译器具有智能性会自动的帮你执行这些过程
OBJ := a.o b.o
CC = gcc
FLAG = -c
target = hello
$(target):$(OBJ) 基于.o文件生成目标文件
$(CC) FLAG -o $@ $^
%.o:%.c 任意一个.c生成同名的任意一个.o 因为没有.o文件所以执行当前的命令生成.o文件
$(CC) FLAG -o $@ $^
因为编译器的隐式规 要生成一个可执行文件不需要主动的生成一个.o文件 ,只需指明生成可执行文件的所需的.o文件 编译会自动的执行编译过程
OBJ := a.o b.o
CC = gcc
FLAG = -c
target = hello
$(target):$(OBJ)
$(CC) FLAG -o $@ $
makefile的函数
函数的调用 $([函数名] [参数]...)
SRC = $(wildcard *.c) 提取当前文件目录下的所有.c文件 SRC代表了当前目录下的所有.c文件
OBJS = $(patsubst %.c , %.o , $(SRC)) 把SRC里所有的 .c替换成 .o
SRC = $(wildcard *.c) OBJS = $(patsubst %.c , %.o , $(SRC))
CC = gcc
FLAG = -g
LIB = -lpthread TARGET = hello $(TARGET):$(OBJS)
$(CC) $(FLAG) -o $@ $^ $(LIB)
.PHONY:
clean:
rm -rf *.o $(TARGET)