目录
在linux下如何编译c/c++代码(库)
将函数编译为C++库文件
运行环境
CentOS 7
学知资料
Linux下静态库和动态库的区别
1. 静态函数库
这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。
2. 动态函数库
这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。
基本文件类型
linux下文件的类型是不依赖于其后缀名的,但一般来讲:
.o,是目标文件,相当于windows中的.obj文件
.so 为共享库,是shared object,用于动态连接的,和dll差不多
.a为静态库,是好多个.o合在一起,用于静态连接
.la为libtool自动生成的一些共享库, vi编辑查看,主要记录了一些配置信息。可以用如下命令查看*.la文件的格式 $file *.la
*.la: ASCII English text
所以可以用vi来查看其内容。
c/c++程序编译使用基本流程
一般程序编译的过程可以分为编译和链接两个阶段。链接阶段,需要把所有的obj文件(.o)链接起来,生成可执行程序,这个过程可以链接其他外部的库文件。 有时候也有省略写法。
gcc -c test.c #源文件编译,生成 .o 文件
gcc -o test test.o #将Obj文件链接,可以多个文件
#省略写法
gcc test.c #默认生成 a.out
gcc -o test test.c #两个阶段省略成一个。意为
gcc和g++区别
GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran、Pascal、Object-C等语言。
gcc是GCC中的GUN C Compiler(C 编译器)
g++是GCC中的GUN C++ Compiler(C++编译器)
gcc和g++的主要区别
1. 对于 *.c和*.cpp文件,gcc分别当做c和cpp文件编译(c和cpp的语法强度是不一样的)
2. 对于 *.c和*.cpp文件,g++则统一当做cpp文件编译
3. 使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL
4. gcc在编译C文件时,可使用的预定义宏是比较少的
5. gcc在编译cpp文件时/g++在编译c文件和cpp文件时(这时候gcc和g++调用的都是cpp文件的编译器),会加入一些额外的宏。
6.在用gcc编译c++文件时,为了能够使用STL,需要加参数 –lstdc++ ,但这并不代表 gcc –lstdc++ 和 g++等价,它们的区别不仅仅是这个。
注意,直接使用 `g++` 编译 C 语言源代码会被当作 C++ 源代码处理。
gcc基本使用
不使用参数,直接gcc
通过gcc 不加参数可以一步直接编译生成可执行文件
gcc main.c
-o参数
在 -o 后面输入自定义的文件名(简单说,链接)
gcc HelloWord.c -o HelloWord
# 这个HelloWord.c是目标文件,不是可执行文件,执行文件是自动生成的a.out
# 想修改a.out的名字为HelloWord,HelloWord是可执行文件
-c参数
只激活预处理,编译,和汇编,也就是他只把程序做成obj文件(简单说,编译)
gcc -c HelloWord.c
# _这个HelloWord.c是目标文件,不是可执行文件,因为这里用到了-c,
# 告诉gcc到汇编为止,不要进行链接。
# _链接就是将目标文件、启动代码、库文件链接成可执行文件的过程,
# 这个文件可被加载或拷贝到存储器执行。
# _会生成一个HelloWord.o的文件
静态库的详细编译
一般情况下也就是 .a 文件。静态库就是指在链接的过程中,将库文件所有数据都整合到目标代码,这样生成的可执行文件执行时就不再需要外部库支持,随便哪里运行。这样就导致了静态库编译生成的可执行库文件较大,而且,当库文件需要更新改变时,可执行文件也必须重新编译生成。
步骤一,准备环境
创建funTestA.h, funTestA.cpp,testMainA.cpp,准备测试文件
// funTestA.h 头文件进行函数接口定义
#include <iostream>
using namespace std;
void printHello();
//--------------------------------------------
// funTestA.cpp 源文件中实现
#include "funTestA.h"
void printHello(){
cout<<"Hello,World\n";
}
//-------------------------------------------
// testMainA.cpp 主程序文件,调用库函数
#include "funTestA.h"
int main(){
printHello();
return 0;
}
Linux下目录,如下所示(若在windows下创建文件,可通过xftp软件进行相应移动)
步骤二,编译源文件
源文件编译,生成.o文件
[root@localhost resource]# g++ -c funTestA.cpp
步骤三,编译静态库文件
ar指令, 编译生成静态库文件
[root@localhost resource]# ar -rsv libfunTest.a funTestA.o
#可加入多个obj对象,例如ar -rsv libfunTest.a funTestA.o funTestB.o
注意:为了在编译程序中正确找到库文件,静态库必须按照 lib[name].a 的规则命名,如下例中[name]=funTest
补充:
1.
[root@localhost resource]# ls -l *.a
#查看当前目录下所有的 .a类型文件,也就是静态库
2.
[root@localhost resource]# ar -t libfunTest.a
#查看指定静态库所包含的所有obj对象,也就是编译生成静态文件时,所加入的源文件个数
3.
ar命令详解
Linux ar命令用于创建或者操作静态库。
ar命令的参数如下:
参数 意义
-r 将objfile文件插入静态库尾或者替换静态库中同名文件
-x 从静态库文件中抽取文件objfile
-t 打印静态库的成员文件列表
-d 从静态库中删除文件objfile
-s 重置静态库文件索引
-v 显示详细信息
-c 创建静态库文件
步骤四,链接静态文件
链接静态库文件,生成可执行文件
[root@localhost resource]# g++ -o testMain testMainA.cpp -L./ -lfunTest
注意:指明库文件时,不需要写静态库文件全名以及后缀。也就是说不要
[root@localhost resource]# g++ -o testMain testMainA.cpp -L./ -llibfunTest.a
而是
[root@localhost resource]# g++ -o testMain testMainA.cpp -L./ -lfunTest
补充:
-L 及-l 参数放在后面.其中,-L 加载库文件路径,-l 指明库文件名字
步骤五,测试
运行可执行文件
[root@localhost resource]# ./testMain
一般情况下就是 .so 文件。与静态库不同,动态库文件在链接时不会将所有的代码实现整合到目标代码中,而是在可执行程序执行到相应位置时才会去库文件中搜索相应的方法。所以动态库链接生成的函数就比较小,而且库文件更新时,只需要重新生成库文件就可以了,不需要重新编译可执行程序。这就给库文件升级更新带来了极大的便利。
步骤一,准备环境
创建funTestSO.h, funTestSO.cpp,testMainSO.cpp,准备测试文件
// funTestSO.h 头文件进行函数接口定义
#include <iostream>
using namespace std;
void printHello();
//--------------------------------------------
// funTestSO.cpp 源文件中实现
#include "funTestSO.h"
void printHello(){
cout<<"Hello,World\n";
}
//-------------------------------------------
// testMainSO.cpp 主程序文件,调用库函数
#include "funTestSO.h"
int main(){
printHello();
return 0;
}
Linux下目录,如下所示(若在windows下创建文件,可通过xftp软件进行相应移动)
步骤二,编译源文件
源文件编译,生成.o文件
[root@localhost resource]# g++ -c -fpic funTestSO.cpp
补充:
-fPIC 或 -fpic 参数的作用是使得 g++ 生成的代码是与位置无关的,也就是使用相对位置
步骤三,编译动态库文件
g++指令, 编译生成动态库文件
[root@localhost resource]# g++ -shared funTestSO.o -o dllfunTest.so
补充:
-shared参数的作用是告诉编译器生成一个动态链接库。
步骤四,链接动态文件
链接动态库文件,生成可执行文件
[root@localhost resource]# g++ -o testMain testMainSO.cpp ./dllfunTest.so
注意:指明库文件时,需要写动态库文件全名以及后缀。
步骤五,测试
运行可执行文件
[root@localhost resource]# ./testMain
此时,将源文件funTestSO.cpp进行修改
#include "funTestSO.h"
void printHello(){
cout<<"Hello,World!This is my Test\n";
}
并再次重新生成动态库,并不再重新编译生成testMain可执行文件
参考资料
Linux——gcc -c -o 等参数的解释
(18条消息) Linux——gcc -c -o 等参数的解释_Wyatt_zhai的博客-CSDN博客
g++以及gcc的区别
linux .o,.a,.so文件解析
linux .o,.a,.so文件解析_bytxl的博客-CSDN博客
Linux下制作C++动态库