g++ -o mysql_cgi mysql_cgi.cc -std=c++11 -I./include -L./lib -lmysqlclient -lpthread -ldl -static
/usr/bin/ld: cannot find -lmysqlclient
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: cannot find -ldl
/usr/bin/ld: cannot find -lstdc++
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lc
-
我们可以使用locate libxxx.a查看对应静态库的位置,并将其添加至LD_LIBRABY_PATH环境变量中
-
如果上一方法查看不到位置,说明当前机器没有配置相关的编译环境,即静态库确实是不存在的。此时可以通过
sudo yum install glibc-static
来安装相关的环境。
对于cannot found stdc++,需要额外使用
yum install libstdc++-static
安装对应的编译环境。
补充动静态库的知识
一、什么是库
将多个目标文件(.o)打包成一个单独的文件,这样的文件被称为库。
由于目标文件中包含二进制的可执行代码和数据,因此其它目标文件可以与库进行链接,形成可执行文件。
库根据生成和链接方式不同分为静态库和动态库。
二、静态库
静态库的命名方式为libxxx.a
,如C标准静态库libc.a
,去掉lib
和.a
,剩下c
的就是静态库名。
静态库与其它目标文件链接的方式称为静态链接。
1、静态库的优缺点
优点:
- 静态库在编译阶段加载,程序在运行时不需要依赖任何的外部函数库。
- 使用静态库的函数速度相比动态库较快。
缺点:
- 静态链接会将库中的所有代码和数据整合到可执行文件中,因此使用该方式创建的可执行文件一般占用较大的空间,如果有多个进程都使用了该静态库,那么在内存中就会存在好几份相同的代码数据。
- 一旦静态库作了改动,就要重新链接生成可执行文件。
2、静态库的打包
- 通过
gcc -c
将源文件编译成目标文件
- 使用
ar -rc
命令将目标文件整合为静态库
注:可以使用ar -tv xxx
查看xxx静态库包含了哪些目标文件。
3、静态库的使用
静态库需要通过gcc编译器完成链接。
方法一:指明静态库的完整路径(包含库名)
方法二:指明静态库和头文件的路径(不包含库名)
其中,-I
指明静态库相关头文件的路径,-L
指明静态库所在路径,-l
指明静态库的具体名称(去掉lib和.a)。
补充:
事实上,仅使用C官方库时,只需要使用
gcc -static
选项即可完成静态链接,因为官方库和头文件都会存储在操作系统的默认路径下(头文件在**/usr/include**,库在**/lib64**)。如果想避免复杂的gcc选项,可以直接将自己的库和头文件添加到默认路径,但是一般不推荐,因为会污染系统。
三、动态库
动态库的命名方式为libxxx.so
,如C标准动态库libc.so
,去掉lib
和.so
,剩下的c
就是动态库名。
动态库又被称为共享库,与其它目标文件链接的方式称为动态链接。
1、动态库的优缺点
优点:
- 动态库被内核加载到内存的某个位置,如果进程使用了动态库,那么内存中的动态库就会被映射到该进程地址空间的共享区,从而避免了静态库中相同代码在内存中重复的问题。
缺点:
- 使用动态链接的程序对动态库具有依赖性。一旦动态库缺失,就会导致程序无法运行。
- 动态库需要在运行时加载,并计算映射的地址,因此速度相对较慢。
1、动态库的打包
-shared
指明gcc生成动态库-fpic
指明gcc生成与位置无关的代码
注:
静态库的代码对应地址可以在链接时确定,但是动态库不能这样做。因为动态链接往往是运行时进行的,一旦动态库代码的地址确定,这就意味着进程需要为动态库保留这些地址,但事实上一个进程可能只使用了动态库中的一小部分代码,因此保留所有地址就是一种浪费!故而需要
-fpic
选项生成与位置无关的代码,这些代码的地址在运行时才被确定,避免在链接时保留地址的情况。
2、动态库的使用
方法一:指明动态库的完整路径(包含库名)
方法二:指明动态库和头文件的路径(不包含库名)
通过ldd
命令即可查看当前可执行文件使用了哪些动态库:
四、库的意义
- 使用高水平开发者写出来的库,能够提高开发效率和代码鲁棒性;
- 将目标文件封装成库,能够保护源代码,用户只要知道头文件的内容,对应调用需要的接口即可。