编译过程
通常的程序需要经过预处理阶段
,编译阶段
,汇编阶段
,链接阶段
- 预处理阶段:预处理阶段对包含源代码的文本文件(test.cc)处理,比如包含头文件到文件中,替换宏定义。生成预处理后的文件
test.i
- 编译阶段:编译器将预处理生成的文件翻译成汇编程序(test.s),汇编语言程序中的每条语句都以一种标准的文本格式确切的描述一条低级机器语言指令。汇编语言能为不同高级语言的不同编译器提供通用的输出语言。
- 汇编阶段:汇编器as将
test.s
翻译成机器语言,把这些指令打包成一种可重定位的目标程序格式,将结果保存在目标文件test.o
中。 - 链接阶段:再
test.cc
程序中调用了系统函数cout
,链接器将改函数的目标文件cout.o
合并到test.o
程序中生成可执行的目标程序。
代码:
#include<iostream>
using namespace std;
int main()
{
cout<<"hello world"<<endl;
}
1.生成预处理文件clang++ -E test.cc -o test.i
预处理文件test.i
如下
# 1 "test.cc"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 342 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "test.cc" 2
# 1 "/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/iostream" 1 3
# 37 "/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/iostream" 3
....
- 生成汇编源程序
test.s
,clang++ -S test.i
源程序如下:
.text
.file "test.cc"
.section .text.startup,"ax",@progbits
.p2align 4, 0x90 # -- Begin function __cxx_global_var_init
.type __cxx_global_var_init,@function
__cxx_global_var_init: # @__cxx_global_var_init
.cfi_startproc
# BB#0:
pushq %rbp
.Lcfi0:
....
3, 生成目标文件test.o
clang++ -c test.s
程序处理过程如下:
编译多文件
// main.cc
#include<iostream>
extern int add(int,int);
using namespace std;
int main()
{
int a,b;
cin>>a>>b;
cout<<"a+b="<<add(a,b)<<endl;
}
int add(int a,int b)
{
return a+b;
}
编译生成二进制文件clang++ -o t main.cc add.cc
或者可以直接将函数生成.o
文件,将.o
文件生成.a
静态链接库,将静态链接库添加到主函数中。
库文件
静态链接库和静态链接库:静态链接库是obj文件的一个集合,扩展名为.a。静态链接库由程序ar生成,可以再不用重新编译程序库代码的情况下,进行程序的重新链接,这种方法节省了编译过程的时间。静态库的另一个优势是开发者可以提供库文件给使用人员不用开放源代码。理论上静态库比动态库速度快1%-5%.
# 生成`add.o`文件
clang++ -c add.cc
# 生成`libadd.a`静态链接库
ar -rcs libstr.a add.o
# 生成二进制文件
clang++ -o t main.cc libadd.a
# 或者在系统目录下查找静态链接库参数不包含静态链接库`libadd.a`的`lib`和`.a`
clang++ -o t main.cc -ladd
# 如果在指定目录查找需要使用
clang++ -o t main.cc -L./ -l add
动态库是程序运行时加载的库,当动态库正确安装后,所有的程序都可以使用动态库运行程序。动态链接库是目标文件的集合,目标文件在动态库中的组织方式是按照特殊方式形成的。库中函数和变量的地址是相对地址,不是绝对地址,真实地址在调用动态库的程序加载时形成。
动态库的名称有别名(soname),真名(realname)和链接名(linker name)。别名由一个前缀lib,然后是库的名字加上.so构成。真名是动态库的真实名称,一般总是在别名的基础上加上一个小的版本号,发布版本构成。除此之外,还有一个链接名,即程序链接时使用的库的名字。在动态链接库安装的时候总是复制库文件到某个目录,然后用软连接生成别名,在库文件进行更新的时候仅仅更新软连接即可。
clang++ -shared -Wl,-soname,libadd.so -o libstr.so.1 add.cc
- shared:生成动态链接库
- -soname:生成动态链接库的别名
libadd.so
- 实际的动态链接库
libstr.so.1