C/C++文件的编译
众所周知,C/C++程序想要得到执行,主要需要执行编译和链接两个过程,这个过程比较繁琐,尤其是程序使用到了其他的头文件的时候。gcc是常用的编译工具,其流程主要是预处理、编译、汇编、链接。
1、单个程序下的编译过程
编写一个经典的helloworld程序,vi创建程序文件名hello.c,代码如下截图:
接下来对hello.c源代码进行编译及生成可执行代码。
第一步,使用gcc对源文件进行编译,生成目标代码(形如xxx.o),参照下面的截图。
gcc -c hello.c
-c :编译或汇编源文件,输出obj文件
第二步,使用gcc链接xxx.o,生成可执行文件
gcc -o hello hello.o
-o:生成可执行文件,其后可以是hello.c/hello.o(源文件/目标文件)。
如果不使用-o,默认生成a.out
这种单个文件的编译及运行非常简单,自己动手试一下就能理解了。
2、包含头文件的编译
创建cpptest目录并进入,分别创建一个include和src路径用于存放头文件和源代码。
第一步,先进入include目录,创建一个头文件hello.h及它的实现代码hello.c。
第二步,进入src目录下创建main.c程序,该程序调用hello.h的hello方法。
此时,如果我们还是按照第1章节中的方法执行main.c,肯定是报错的。
因为对于生成的可执行文件来说,它不知道hello.h头文件所在的位置,所以#include的时候就中止编译了。现在来引入gcc的另一个参数-I(大写的i)。
-I :该参数选项指定路径让编译器去相应的路径查找头文件
现在我们指定hello.h的所在位置,看看程序是否能成功编译
可以发现,没有报“fatal error:hello.h:No such file or directory”这个错误了,说明include找到了hello.h这个头文件,但是随之而来又出现了一个新的报错,显示没有定义引用“hello”,意思就是没有定义hello()函数呗。因为我们只是在hello.h头文件里声明了hello(),并没有定义函数体,关于为什么只在头文件里声明函数名而不对其实现,主要是C语言的模块化设计中.h头文件主要是对外的一些接口,一些私有的数据等等实现都会封装在我们的.c中。在这个例子里,如果把hello.c文件里实现的程序直接写在hello.h里,就可以编译成功获取到可执行文件。
前面的hello.h声明函数和hello.c实现函数这种方式,常常用于生成和使用库文件。
库文件和头文件的作用类似,提供大量的模块/函数。但其实两者并不能混为一谈,它们之间最大的区别是:
- 头文件主要用于变量声明和存储、函数/类等功能模块的声明
- 库文件主要负责模块的具体实现
库文件又有静态链接库和动态链接库的分别,这里就简要介绍一下。
3、生成静态链接库及使用
在linux中,静态链接库文件通常是形如libxxx.a的文件,xxx一般是xxx.h头文件的名字;在windows中,静态链接库文件是xxx.lib。
先使用gcc命令编译hello.c文件,再使用ar命令生成静态库文件,如下截图。这样就完成了静态库libhello.o的创建。接下来就是把main.c程序链接到库,生成一个可执行文件,运行可执行文件main,打印结果。
1.单个目标文件生成静态库
ar (-)crs libhello.a hello.o
-c :创建备存文件
-r :把xx文件插入备存文件中(默认替换)
-s :若备存文件中包含了对象模式,可利用此参数建立备存文件的符号表
gcc -o main main.c -I ../include -L ../include -l hello
-L:指定一个目录,用于编译过程中搜索,即指定库文件的路径
-l(小写L):根据参数后的库名查找链接的库文件,搜索几个系统目录以及-L指定的目录
-
多个目标文件生成静态库
在include目录下新建一个add2int函数,实现两个整数的加法,并在main.c程序中调用。
将hello.o和add.o链接到一个静态库libhelloAndadd.a中
4、生成动态链接库及使用
动态链接库,顾名思义,
在linux中,动态链接库文件通常是形如libxxx.so的文件;在windows中,动态链接库文件是xxx.dll。(命名规则和静态链接库是一样的,只是后缀不同)
生成动态链接库的命令与静态链接库稍有不同,需要使用gcc的-fPIC(或-fpic)、-shared参数。
1.单个源文件/目标文件生成动态库
gcc -fPIC -shared hello.c -o libhello.so
-fPIC(-fpic):生成posotion-independent code(PIC),在共享库中使用
-shared:创建一个共享对象,能够链接到其他对象文件,完成执行
//gcc -fPIC -shared hello.o -o libhello.so --目标文件(xxx.o)
可以看到链接了libhello.so文件仍然显示找不到,这需要把.so文件拷贝到/usr/lib等目录下,就可以运行了
或者以这种形式执行
2.多个源文件/目标文件生成动态库
其实类比多个目标文件生成静态链接库,把ar命令替换成gcc -fPIC -share xxx.o -o libxxx.so,然后将动态链接库文件拷贝到/usr/lib目录下,生成可执行文件即可正常调用。