C++编译链接过程


gcc的编译(ciso)

hello.c给gcc-E预处理器生成hello.i;预处理:gcc -E test.c -o test.i 或 gcc -E test.c

经过gcc-S编译器生成hello.s汇编文件;编译:gcc -S test.i -o test.s

(编译器只检查程序语法、函数、变量是否声明。如果函数未被声明,编译器会给出一个警告,但可以生成object file。)

经过gcc-c汇编器生成hello.o二进制文件;汇编:gcc -c test.s -o test.o

经过gcc链接器生成a.out可执行文件。链接:gcc test.o -o test

(链接器会在所有的object file中找寻函数的实现,如果找不到就会报链接错误码linker error)

(1)多个程序文件的编译:通常整个程序是由多个源文件组成的,相应也就形成了多个编译单元,使用GCC能够管理这些编译单元。假设有一个由test1.c和test2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序test。

gcc -c test1.c test2.c -o test

(2)直接生成可执行程序

gcc sum.c -o myapp 

./myapp打印出来

(3)库文件的链接

函数库实际上是一些头文件.h和库文件(.so/.lib/.dll)的集合。

头文件放到/usr/include目录下,库文件放到/usr/lib目录下。

有时候,我们要用的库不在这些目录下,所以GCC在编译时必须用自己的方法来查找所需要的头文件和库文件。

例如我们的程序test.c是在linux上使用c连接mysql,这个时候需要去mysql官网下载mysql connectors的c库,下载下来解压之后,有一个include文件夹,里面包含mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so。其中include文件夹的路径是/usr/dev/mysql/include,lib文件夹是/usr/dev/mysql/lib

编译成可执行文件:gcc -c -I /usr/dev/mysql/include test.c -o test.o

然后再进行链接:gcc -L /usr/dev/mysql/lib -lMysqlclient test.o -o test

默认情况下,gcc在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库。如果需要的话可以在编译时加上-static选项,强制使用静态链接库。

在/usr/dev/mysql/lib目录下有链接时所需要的库文件libMysql.client.so和libMysql.client.a,为了让GCC在链接时只用到静态链接库,可以使用命令gcc -L /usr/dev/mysql/lib -static -lmysqlclient test.o -o test

不给客户源代码,但是代码会生成动态库和静态库可以给它们,根据头文件使用。

用户使用时有include和lib。比如include里面的head.h。

(4)静态库(lib/a)

windows下对应静态库lib文件。

Linux下命名规则:lib开头,静态库名,.a结尾。例如libsort.a

制作:使用gcc a.c b.c c.c -c,得到与位置有关的*.o

然后使用ar将生成的.o文件打包:ar rcs + 静态库的名字(libMytest.a) + 生成的所有的.o

静态链接是在编译的时候把add.o和sub.o编译成可执行文件。

静态库的使用需要有库文件和头文件,编译程序的时候通过“-l 静态库名”参数进行编译。

优点:寻址方便,速度快。库被打包到可执行程序中,直接发布可执行程序即可使用。

缺点:静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。

如果静态函数库改变了,那么你的程序必须重新编译。

使用场合:在核心程序上使用,保证速度,可忽视空间。主流应用于8/90年代,现在很少用。

(6)动态库(dll/so)

windows下对应动态库dll文件。

Linux下命名规则:lib+名字+.so

制作:首先生成与位置无关的代码.o,即编译gcc -fPIC -c *.c -I ../include

然后gcc将.o打包成动态库:gcc -shared -o libMytest.so *.o -I ../include

在应用程序打包的时候,不会被打包进去,只是做了符号的记录。

动态库的使用需要有库文件和头文件,编译程序的时候通过“-l 动态库名”参数进行编译。

在运行程序之前还需要配置动态库的加载路径,程序才能正常运行。

优点:执行程序的体积小,动态库更新了,不需要重新编译程序,函数接口不变。

缺点:发布程序的时候,需要将动态库提供给用户。动态库没有被打包到应用程序中,加载速度相对较慢。

(7)静态库和动态库的区别

gcc在进行静态库链接的时候,会把静态库中代码打包到可执行程序里,编译的时候加载;发布程序的时候无需提供静态库,移植方便,但是比较消耗内存,更新部署和发布的时候比较麻烦。

gcc在进行动态库链接的时候,动态库中的代码不会被打包,运行的时候加载;发布程序的时候需要提供动态库地址,内存占用比较小,更新部署发布简单。

C++