用gcc/g++生成可执行的C或C++程序需要经过四步:
1.预处理程序对源文件(*.c, *.cpp, *.C, *.cxx)等进行宏扩展和条件处理,导入前导文件,生成.i文件(可用gcc -E filename生成,结果输出到标准输出)
2.编译程序将*.i文件中的C或C++源代码转换成汇编代码,生成.s文件(可用gcc -S filename生成)
3.汇编程序将*.s文件中的汇编代码转换成目标代码(机器代码),生成.o文件(可用gcc -c filename生成)
4.连接程序将*.o文件与库文件进行连接,生成可执行程序(可用gcc filename生成,默认输出文件名为a.out)
一、gcc的使用
1.gcc/g++命令格式:
gcc [options] filename
g++ [options] filename
多个选项要分开写
2.一些常用的选项:
gcc -o filename 改变输出文件的文件名,默认生成的可执行文件名为a.out
gcc -O0/O1/O2/O3 -O0表示关闭编译器优化功能,其他三个优化程度不断加深,-O1就等同于-o
二、make的使用
make就是一个gcc/g++的调度器,通过读入一个文件(默认文件名为Makefile或者makefile),执行一组以gcc/g++为主的shell命令序列。输入文件主要用来记录文件之间的依赖关系和命令执行顺序。
1.Makefile规则的组成:包含一个依赖行和多条以Tab开头的命令行组成
目标1 [目标2...]: [依赖文件列表]
[\t 命令]
...
2.规则目标
规则目标分为两种:真实目标和假象目标
(1)真实目标:命令执行后确实生成了该目标
xyz: x.c y.c assemble.o object.a
gcc -o xyz x.c y.c z.c assemble.o /usr/local/lib/object.a
(2)假象目标:顾名思意,命令执行后确实不生成该目标
作用1:生成多个互不相关的目标
all: object1 object2
object1: ...
...
object2: ...
...
作用2:执行一些不生成目标的命令
clean:
rm *.o
rm *.a
如果目标存在并且为最新,make将拒绝执行规则。因此,为了让假象目标总是执行,需要加上.PHONY前缀:
.PHONY clean:
...
3.自动生成规则依赖行:
gcc -MM filename 只包含用户头文件
gcc -M filename 包含系统头文件
用>>追加到Makefile中就可以了
4.隐含规则
当规则只有依赖行而没有命令行时,make命令将求助于隐含规则
隐含规则也称后缀转换规则,如.c.o的后缀为.o,表示将*.c文件转换为*.o文件;.s.o后缀为.o,表示将.s文件转换为.o文件;.c后缀为空,表示将.c文件转换为可执行文件。可以自己定义隐含规则:
.SUFFIXES: 清除所有隐含规则
.SUFFIXES: .s .t .l 声明两条隐含规则.s.t和.s.l,注意后缀之间用空格隔开
.s.t:
...
.s.l:
...
5.Makefile中的变量
变量用$()进行引用,可以代替编译器名,选项名,文件名,目标名等
内部变量:一类是静态的,如CFLAGS,CPPFLAGS,与普通变量同样使用;一类是动态的,根据规则确定其值,有以下几种:
$* 不包括文件扩展名的依赖文件名
$? 比目标文件名新的依赖文件
$@ 目标文件名
$< 当前规则中的依赖文件列表中的第一个文件名
$^ 当前规则中依赖文件列表中的所有文件
6.make命令的使用
使用格式:
make [选项] [参数]
其中参数为目标名,如果不制定则默认创建/更新第一个目标
选项有以下几种:
变量赋值,如:make CC=gcc。make命令按如下顺序对变量赋值:内部变量定义,环境变量定义,Makefile文件中的变量定义,make命令行中的定义。以最后赋值为准。
-e 将上述变量赋值顺序的2、3两项互换
-f 制定输入文件的文件名,默认为Makefile或makefile
-r 禁止隐含规则
-n 输出用于创建/更新目标的命令序列,但不真正执行
-I 忽略出错信息
-P 指示make以并行方式一次创建多个目标。可用.MUTEX关键字指示要求串行创建的目标
7.make命令工作方式
读入输入文件,找到要创建/更新的目标规则
检查目标与依赖文件列表的时间戳信息,如果目标文件比依赖文件列表旧,则需要更新。此时继续查找生成依赖文件列表中的文件的目标规则,同样比较时间戳,依此类推。然后从底层开始更新,最终完成目标的创建/更新。