1. 介绍
C++语言的相关后缀
- .a 文件是一个静态库文件
.c
,.c++
,.cp
,.cpp
,.cc
,.cxx
这几种后缀都可以表示c++的源文件.h
,.hpp
c++语言的头文件.i
是c++预处理文件.o
目标文件.s
汇编语言的文件- .so 动态库或者共享库或者称为运行时库
2. C++编译
2.1 预处理
g++ -E helloworld.cpp # 虽然预处理了,但不会输出.i文件
g++ -E helloworld.cpp -o helloworld.i # 指定输出.i文件
- -E选项告诉编译器只进行预处理操作
- -o 选项把预处理的结果输出到指定文件
2.2 生成汇编语言
g++ -S helloworld.cpp
g++ -S helloworld.cpp -o helloworld.s
- -S 选项告诉编译器,进行预处理和编译成汇编语言操作
每个平台对应的汇编语言的形式是不同的,例如有很多型号的开发板,有很多型号的CPU
2.3 源文件生成目标文件
g++ -c helloworld.cpp # 默认生成 helloworld.o 目标文件
g++ -c helloworld.cpp -o harumph.o # 指定目标文件名
#编译多个.c文件
g++ -c helloworld.cpp helloworld1.cpp hellworld2.cpp
2.4 生成可执行文件
(1) 单个源文件编译为可执行文件
- 注意: 后面2个命令执行后并没有按编译过程出现
.i
,.s
,.o
文件,并不意味着没有经历这些过程
g++ helloworld.cpp
g++ helloworld.cpp -o howdy
执行程序
./可执行文件
(2) 多个源文件编译为可执行文件
g++ hellomain.cpp sayhelo.cpp -o hello
3. 生成库文件
3.1 生成静态库
(1) 编译成.o
文件
g++ -c [.cpp] -o [自定义文件名] #单个源文件
g++ -c [.cpp] [.cpp] ... # 多个源文件
(2) 编译静态库
ar -r [lib自定义库名.a] [.o] [.o] ...
(3) 链接成可执行文件
g++ [.cpp] [.a] -o [自定义输出文件名]
g++ [.cpp] -o [自定义输出文件名] -l[库名] -L[库所在路径]
3.2 生成动态库
(1) 编译二进制.o
文件
g++ -c -fpic [.c/.cpp] [.c/.cpp] ...
(2) 编译动态库
g++ -shared [.o] [.o] ... -o [lib自定义库名.so]
(3) 链接动态库到可执行文件
g++ [.c/.cpp] -o [自定义可执行文件名] -l[库名] -L[库路径] -Wl,-rpath=[库路径]
4. 总结
(1). 编译过程
源文件.cpp
文件 -> 预编译成.i
文件 -> 编译成汇编语言.s -> 汇编成.o文件 -> 链接成可执行文件(名字自定义,后缀没关系)
(2). 编译过程命令
- 预处理
g++ -E [.cpp源文件] -o [自定义输出文件名.i]
- 编译成汇编语言[隐藏了预处理操作]
g++ -S [.cpp源文件]
- 编译目标文件(二进制文件,可用于链接)
g++ -c [.cpp源文件] [.cpp源文件] [...] (可选项:-o [自定义文件名])
(3). 库
静态库
- 编译(先转成.o文件,在编成
lib(自定义库名).a
)
g++ -c [.cpp源文件] [.cpp源文件] [...] (可选项:-o [自定义文件名]) #编译目标文件
ar -r lib[自定义库名].a [.o文件] [.o文件] [...]
动态库
- 编库
- 第一种做法,先转成.o文件,再编成.so文件
g++ -c fpic [.cpp源文件] [.cpp源文件] [...] g++ -shared [.o文件] [.o文件] [...] -o lib[库名].so```
- 第二种做法,直接转成.so
g++ -fpic -shared [.cpp源文件] [.cpp源文件] [...] -o lib[库名].so
- 链接
g++ [main文件] -o [自定义输出可执行文件名] -l[库名] -L[库所在路径] -Wl, -rpath=[库所在路径]
可以看出C++的编译和库连接与C的编译和链接,基本上都是一模一样。区别很简单:
- 命令中
c++
用的是g++
编译器,c
语言用的是gcc
编译器 - 并且
g++
编译器同时也支持.c
c文件的编译