[转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)
在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库(*.a)与动态库(*.so)的生成与使用方式是不同的。刚开始可能会不适应,但是用多了应该会习惯这种使用,因为步骤上并没有VS下配置那么繁琐。下面就分别总结下linux下生成并使用静态库与动态库的方法:(由于是C++项目,所以编译器用的g++,但是与gcc的使用是相通的)
首先是准备工作,把我们需要封装成库文件的函数的头文件与源文件写好,如下:
//myAPI.h
int ADD(int a, int b);
int MINUS(int a, int b);
//myAPI.cpp
#include "myAPI.h" int ADD(int a, int b){
return a + b;
} int MINUS(int a, int b){
return a - b;
}
接下来准备一个测试用的主函数源文件:
//main.cpp
#include "myAPI.h"
#include <iostream> int main(){
std::cout << "1 + 1 = " << ADD(, ) << std::endl;
std::cout << "1 - 1 = " << MINUS(, ) << std::endl;
return ;
}
重要说明:
linux下用生成静态库的命令 ar 处理 myAPI.o 文件生成静态库文件,生成的库文件应遵循规范,及linux下库文件加“lib”前缀。
编译/链接生成时,也要注意,目标文件/库文件之间有依赖关系,则需要把被依赖文件放到后面(g++6.x),才能编译,
不然可能报错 找不到变量函数/ 未定义的引用 "undefined reference to".
贴上Makefile,有注解:
all: main-1 main-2 main-a main-so main-so2 main-1: myAPI.cpp main.cpp myAPI.h
g++ -o main-1 myAPI.cpp main.cpp
@echo "main-1 done. 直接编译省略显示编译.o文件"
@echo main-2: main.cpp myAPI.o
g++ -o main-2 myAPI.o main.cpp
@echo "main-2 done. 显示编译.o文件"
@echo main-a: libmyAPI.a
g++ -o main-a main.cpp libmyAPI.a
@echo "main-a done. 使用.a静态库文件 链接生成程序"
@echo main-so: libmyAPI.so
g++ -o main-so main.cpp ./libmyAPI.so
@echo "main-so done. 直接使用.so动态库文件(需要带路径,运行时直接使用此路径) 链接生成程序"
@echo main-so2: libmyAPI.so
g++ -o main-so2 main.cpp -L. -lmyAPI
@echo "main-so2 done. 让g++自动在当前目录("."表示当前目录,或"./")查找.so动态库文件 链接生成程序"
@echo " 但运行时默认到/usr/lib目录查找,,或运行前设置环境变量 LD_LIBRARY_PATH 为动态库的路径"
@echo myAPI.o: myAPI.cpp myAPI.h
g++ -c myAPI.cpp
@echo "myAPI.o done. 编译.o文件"
@echo libmyAPI.a: myAPI.o
ar crv libmyAPI.a myAPI.o
@echo "libmyAPI.a done. 编译.a静态库文件"
@echo libmyAPI.so:
g++ -fPIC -c myAPI.cpp
g++ -shared -o libmyAPI.so myAPI.o
@echo "libmyAPI.so done. 编译.so动态库文件,需要 .o文件编译时加选项 -fPIC"
@echo " 或者 直接编译动态库:"
@echo " g++ -shared -fPIC -o libmyAPI.so myAPI.cpp"
@echo #或者 直接编译动态库:
#libmyAPI.so:
# g++ -shared -fPIC -o libmyAPI.so myAPI.cpp
# clean:
rm -f *.o *.a *.so main-*
最后运行程序:
[root@lzp test2]# ./main-
+ =
- =
[root@lzp test2]# ./main-
+ =
- =
[root@lzp test2]# ./main-a
+ =
- =
[root@lzp test2]# ./main-so
+ =
- =
[root@lzp test2]# ./main-so2
./main-so2: error while loading shared libraries: libmyAPI.so: cannot open shared object file: No such file or directory
可以看到 main-so直接运行了,但是 main-so2 运行出错了,找不到动态库,需要把动态库放到/usr/lib目录; 或者使用"LD_LIBRARY_PATH"环境变量后可以直接运行
[root@lzp test2]# LD_LIBRARY_PATH=./
[root@lzp test2]# ./main-so2
./main-so2: error while loading shared libraries: libmyAPI.so: cannot open shared object file: No such file or directory
[root@lzp test2]# LD_LIBRARY_PATH=./ ./main-so2
1 + 1 = 2
1 - 1 = 0
PS:但是在 G++ 6.x版本下直接运行main-so2不出错,,以上是G++4.X版本编译的
在项目开发过层中尽量让lib是垂直关系,避免循环依赖;越是底层的库,越是往后面写!
例如:
g++ ... obj($?) -l(上层逻辑lib) -l(中间封装lib) -l(基础lib) -l(系统lib) -o $@
这样写可以避免很多问题,这个是在搭建项目的构建环境的过程中需要考虑 清楚地,在编译和链接上浪费太多的生命不值得!
推荐一本书,写的很深刻:《程序员的自我修养——链接、装载与库》
[参考: http://www.tuicool.com/articles/m67z2u2; http://blog.chinaunix.net/uid-24352482-id-3199452.html]
[参考: http://www.cnblogs.com/little-ant/p/3398885.html]
[转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)的更多相关文章
- Linux下g++编译thread出错的的解决方法
错误如下图所示: 因为thread是C++11新加入的特性,所以我们在用g++编译的时候不能直接用,需要在g++后面加上 -std=c++0x -pthread 如果是gcc编译多线程的话则应该要用 ...
- Linux下Gcc生成和使用静态库和动态库详解
参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...
- LINUX下文件编译
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...
- 从四个问题透析Linux下C++编译&链接
摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...
- Linux下Gcc生成和使用静态库和动态库详解(转)
一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...
- Linux环境g++编译TinyXML动态库
除了CMarkup,tinyxml也是C/C++下解析XML很好的工具.在linux下用g++编译tinyxml的步骤如下(tinyxml版本2.6.2): 进入tinyxml解压目录,用文本编辑器打 ...
- FFmpeg在Linux下安装编译过程
转载请把头部出处链接和尾部二维码一起转载,本文出自:http://blog.csdn.net/hejjunlin/article/details/52402759 今天介绍下FFmpeg在Linux下 ...
- 【转】Linux下gcc生成和使用静态库和动态库详解
一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不 ...
- Linux下GCC生成和使用静态库和动态库【转】
本文转载自:http://www.cppblog.com/deane/articles/165216.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本 ...
随机推荐
- 防御XSS攻击-encode用户输入内容的重要性
一.开场先科普下XSS 跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶 ...
- vue2.0实践的一些细节
最近用vue2.0做了个活动.做完了回头发现,好像并没有太多的技术难点,而自己好像又做了比较久...只能说效率有待提升啊...简单总结了一些比较细节的点. 1.对于一些已知肯定会有数据的模块,先用一个 ...
- .NET Core & ASP.NET Core 1.0在Redhat峰会上正式发布
众所周知,Red Hat和微软正在努力使.NET Core成为Red Hat企业版Linux (RHEL)系统上的一流开发平台选项.这个团队已经一起工作好几个月了,RHEL对.NET有许多需求.今天在 ...
- .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...
- [C#] C# 知识回顾 - 序列化
C# 知识回顾 - 序列化 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902005.html 目录 序列化的含义 通过序列化保存对象数据 众 ...
- PHP之Memcache缓存详解
Mem:memory缩写(内存):内存缓存 1. 断电或者重启服务器内存数据即消失,即临时数据: Memcache默认端口:11211 存入方式:key=>>value ...
- 编写高质量代码:改善Java程序的151个建议(第7章:泛型和反射___建议106~109)
建议106:动态代理可以使代理模式更加灵活 Java的反射框架提供了动态代理(Dynamic Proxy)机制,允许在运行期对目标类生成代理,避免重复开发.我们知道一个静态代理是通过主题角色(Prox ...
- 以向VS 程序打包集成自动写入注册表功能为例,介绍如何实现自由控制安装过程
最近由于项目部署时需要更灵活的控制程序安装的流程以及自定义安装行为,特意研究了一下VS程序打包,把解决办法和大家分享一下. 以VS2010为例: 这是一个已经设置好最基本的Visual Studio ...
- 第11章 Linux服务管理
1. 服务分类 (1)Linux的服务 ①Linux中绝大多数的服务都是独立的,直接运行于内存中.当用户访问时,该服务直接响应用户,其好处是服务访问响应速度快.但不利之处是系统中服务越多,消耗的资源越 ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(下)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...