linux开发之gcc与g++区别,静态库、动态库
gcc
广义上指GNU编译器套装(英语:GNU Compiler Collection,缩写为GCC)是GNU计划制作的一种优化编译器,支持各种编程语言、操作系统、计算机系统结构。
狭义上指GNU C语言编译器(GNU C Compiler)。
常用gcc/g++参数。
编译选项 | 说明 |
---|---|
-E | 预处理指定文件,不进行编译 |
-S | 编译指定文件,不进行汇编 |
-c | 编译汇编指定文件,不进行链接 |
-o [filename] | 令生成文件名为filename |
-I 目录 | 指定include包含文件的搜索目录 |
-g | 编译时候附带调试信息 |
-D | 编译时指定一个宏 |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告信息 |
-On | n取值[0,3]。编译器优化的4个级别。0表示不进行优化,1为默认值,3为最高级别 |
-l | 在程序编译时候指定使用的库 |
-L | 在程序编译时使用的库的搜索路径 |
-fpic/fPIC | 生成与为止无关代码(一般用于动态库 |
-shared | 生成共享目标文件,建立动态库 |
-std | 指定标准版本 |
gcc 与 g++区别
我们一般在编译c语言用的是gcc,编译c++用的是g++。但其实gcc也可以编译c++程序,只不过链接时候缺少c++库。可以通过参数指定成功链接。
假设我们有如下代码文件acpp.cpp
#include <iostream>
int main() {
std::cout << "I'm a cpp program\n";
return 0;
}
如图为gcc编译链接c++代码不指定c++库。可以看到链接失败。
如图为gcc只编译c++代码。可以看到,成功编译。
如图为gcc编译链接c++代码并指定库。可以看到,成功编译链接,能够正常执行程序。
当然可以gcc编译cpp代码后,用g++去链接。其实本质上,g++编译c++代码同样是调用gcc去编译的。
方便来说,其实就是用gcc去编译连接c语言,g++去编译连接c++语言。只不过两者并不是互相不通的,而是联系紧密。
静态库、动态库
当分发代码时候,可以使用静态库、动态库。
库 | 操作系统 | 文件名 |
---|---|---|
静态库 | linux | libxxx.a |
静态库 | windows | libxxx.lib |
动态库 | linux | libxxx.so |
动态库 | Windows | libxxx.dll |
注意:xxx是库的名字,libxxx.a等是库的文件的名字。
静态库的使用方式是链接时候,将代码插入带可执行程序中融为一体。动态库的使用方式是,当程序运行时,将动态库加载到内存中供程序调用。
假设我们有如下代码文件。head.h中包含了add函数的声明。
// a.cpp
int add(int a, int b) {
return a + b;
}
// test.cpp
#include <iostream>
#include "head.h"
using namespace std;
int main() {
cout << "Hello World" << endl;
printf("a + b = %d\n", add(1, 3));
return 0;
}
静态库
制作
目标是将a.cpp的内容制作成静态库,静态库名为aaa。
步骤为先用g++生成其目标文件,再用ar rcs libxxx.a 目标文件1 目标文件2...
将其打包成为静态库。
使用
编译时指定库名称-l库名称
,并且指定库的搜索路径-L路径
。
动态库
制作
目标是将a.cpp的内容制作成动态库,动态库名为aaa。
步骤为先用g++生成其目标文件(参数-fpic
),再用g++ -shared 目标文件1 目标文件2... -o libxxx.so
生成动态库。
使用
编译时指定库名称-l库名称
,并且指定库的搜索路径-L路径
。
然而,当动态库不和可执行文件在同一目录下时,会出现问题。
其原因是,无法找到动态库的位置,解决方法大概分为4种:
- 修改程序的DT_RPATH段(不推荐
- 修改环境变量
LD_LIBRARY_PATH
- 修改 /etc/ld.so.cache文件列表
- 复制到/lib/或/usr/lib/目录下(不推荐
修改环境变量LD_LIBRARY_PATH
:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ubuntu/nccourse/lesson-3/lib
修改 /etc/ld.so.cache文件列表:
修改/etc/ld.so.conf,然后ldconfig
来个更新/etc/ld.so.cache。