gcc/g++编译器
gcc常用选项:
-c 表示编译源文件, -o表示输出文件, -g用gdb调试时要写上此参数, -D编译时将宏定义传入(DEBUG)
gcc编译过程:
- 预处理:将源文件的宏展开,载入头文件 gcc -E … .i
- 编译:将.c文件编译成汇编文件 gcc -S … .s
- 汇编:将汇编文件编译成机器码 as … .o
- 链接:将.o文件进行连接,得到可执行二进制文件 gcc
静态库与动态库
静态库:
创建:先gcc -c add.c 编译add.c得到.o文件,再 ar crsv libadd.a add.o 对目标文件.o进行归档,将libadd.a拷贝到/lib或/usr/lib下
编译时:gcc -o main main.c -ladd
编译时链接静态库会将静态库拷贝到可执行二进制文件中。
动态库:
创建:gcc -fPIC -Wall -c add.c; gcc -shared -o libadd.so add.o; gcc -o main main.c -ladd,将库文件拷贝到/lib或者/usr/lib下
使用:./main
动态库在执行时加载,而不是在编译时拷贝到程序中。静态库会使程序臃肿难以升级,动态库使程序易于升级但难以部署。
Makefile工程管理器
主要为了增量编译,防止只对少数文件进行修改时要重新编译所有文件。
Makefile格式:
1 | target:dependency_files |
有一个较为简单的例子:
1 | main:main.o func.o |
使用make时,make程序先读到第1行的目标文件main,和他的依赖文件main.o和func.o,之后去比较main文件和main.o和func.o的产生时间,若main比前两者旧(生成的时间要早),即执行第二条命令,此过程是一个递归过程,及会对main.o和func.o进行同样操作。
1 | main:main.o func.o |
输入make clean 命令可以删除生成的文件
1 | #定义变量 |
常用的自动变量(使用时,自动用特定的值替换该变量):
变量 | 作用 |
---|---|
$@ | 当前规则的目标文件 |
$< | 当前规则第一个依赖文件 |
$^ | 当前规则所有依赖文件,以空格分隔 |
$(@D) | 目标文件的目录名 |
$(@F) | 目标文件的文件名 |
常用预定义变量(内部定义好的变量,值是固定的)
变量 | 作用 |
---|---|
CC | C编译器(默认cc) |
CXX | C++编译器(默认g++) |
CFLAGS | C编译器选项(CFLAGS:=…) |
CXXFLAGS | C++编译器选项 |
通过使用内部变量,可以将上述makefile改写为:
1 | OBJS:=main.o func.o |
由于.o文件会自动依赖.c或者.cc文件,所以可以省略最后两个.o的书写。
1 | OBJS:=main.o func.o |
makefile 中常用的两个函数:
- wildcard会搜索当前目录下的文件,通过通配符进行匹配,并将所有符合要求的文件名展成一列,以空格隔开。如(SOURCES:=$(wildcard *.c))会将所有.c 文件按上述操作展成一列,并存入SOURCES变量中。
- patsubst字符串替换函数,用法:OBJS:=$(patsubst %.c,%.o,$(SOURCES)),将SOURCES中的.c换成.o
所以上面提到的makefile还可以这样写:
1 | SRCS:=$(wildcard *.c) |