在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库(*.a)与动态库(*.so)的生成与使用方式是不同的。刚开始可能会不适应,但是用多了应该会习惯这种使用,因为步骤上并没有VS下配置那么繁琐。下面就分别总结下linux下生成并使用静态库与动态库的方法:(由于是C++项目,所以编译器用的g++,但是与gcc的使用是相通的)

首先是准备工作,把我们需要封装成库文件的函数的头文件与源文件写好,如下:

  1. //myAPI.h
  2. int ADD(int a, int b);
  3. int MINUS(int a, int b);
  1. //myAPI.cpp
  2. #include "myAPI.h"
  3.  
  4. int ADD(int a, int b){
  5. return a + b;
  6. }
  7.  
  8. int MINUS(int a, int b){
  9. return a - b;
  10. }

接下来准备一个测试用的主函数源文件:

  1. //main.cpp
  2. #include "myAPI.h"
  3. #include <iostream>
  4.  
  5. int main(){
  6. std::cout << "1 + 1 = " << ADD(, ) << std::endl;
  7. std::cout << "1 - 1 = " << MINUS(, ) << std::endl;
  8. return ;
  9. }

重要说明:

linux下用生成静态库的命令 ar 处理 myAPI.o 文件生成静态库文件,生成的库文件应遵循规范,及linux下库文件加“lib”前缀。

编译/链接生成时,也要注意,目标文件/库文件之间有依赖关系,则需要把被依赖文件放到后面(g++6.x),才能编译,

不然可能报错 找不到变量函数/ 未定义的引用 "undefined reference to". 

贴上Makefile,有注解:

  1. all: main-1 main-2 main-a main-so main-so2
  2.  
  3. main-1: myAPI.cpp main.cpp myAPI.h
  4. g++ -o main-1 myAPI.cpp main.cpp
  5. @echo "main-1 done. 直接编译省略显示编译.o文件"
  6. @echo
  7.  
  8. main-2: main.cpp myAPI.o
  9. g++ -o main-2 myAPI.o main.cpp
  10. @echo "main-2 done. 显示编译.o文件"
  11. @echo
  12.  
  13. main-a: libmyAPI.a
  14. g++ -o main-a main.cpp libmyAPI.a
  15. @echo "main-a done. 使用.a静态库文件 链接生成程序"
  16. @echo
  17.  
  18. main-so: libmyAPI.so
  19. g++ -o main-so main.cpp ./libmyAPI.so
  20. @echo "main-so done. 直接使用.so动态库文件(需要带路径,运行时直接使用此路径) 链接生成程序"
  21. @echo
  22.  
  23. main-so2: libmyAPI.so
  24. g++ -o main-so2 main.cpp -L. -lmyAPI
  25. @echo "main-so2 done. 让g++自动在当前目录("."表示当前目录,或"./")查找.so动态库文件 链接生成程序"
  26. @echo " 但运行时默认到/usr/lib目录查找,,或运行前设置环境变量 LD_LIBRARY_PATH 为动态库的路径"
  27. @echo
  28.  
  29. myAPI.o: myAPI.cpp myAPI.h
  30. g++ -c myAPI.cpp
  31. @echo "myAPI.o done. 编译.o文件"
  32. @echo
  33.  
  34. libmyAPI.a: myAPI.o
  35. ar crv libmyAPI.a myAPI.o
  36. @echo "libmyAPI.a done. 编译.a静态库文件"
  37. @echo
  38.  
  39. libmyAPI.so:
  40. g++ -fPIC -c myAPI.cpp
  41. g++ -shared -o libmyAPI.so myAPI.o
  42. @echo "libmyAPI.so done. 编译.so动态库文件,需要 .o文件编译时加选项 -fPIC"
  43. @echo " 或者 直接编译动态库:"
  44. @echo " g++ -shared -fPIC -o libmyAPI.so myAPI.cpp"
  45. @echo
  46.  
  47. #或者 直接编译动态库:
  48. #libmyAPI.so:
  49. # g++ -shared -fPIC -o libmyAPI.so myAPI.cpp
  50. #
  51.  
  52. clean:
  53. rm -f *.o *.a *.so main-*

最后运行程序:

  1. [root@lzp test2]# ./main-
  2. + =
  3. - =
  4. [root@lzp test2]# ./main-
  5. + =
  6. - =
  7. [root@lzp test2]# ./main-a
  8. + =
  9. - =
  10. [root@lzp test2]# ./main-so
  11. + =
  12. - =
  13. [root@lzp test2]# ./main-so2
  14. ./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"环境变量后可以直接运行

  1. [root@lzp test2]# LD_LIBRARY_PATH=./
  2. [root@lzp test2]# ./main-so2
  3. ./main-so2: error while loading shared libraries: libmyAPI.so: cannot open shared object file: No such file or directory
  4. [root@lzp test2]# LD_LIBRARY_PATH=./ ./main-so2
  5. 1 + 1 = 2
  6. 1 - 1 = 0

PS:但是在 G++ 6.x版本下直接运行main-so2不出错,,以上是G++4.X版本编译的

在项目开发过层中尽量让lib是垂直关系,避免循环依赖;越是底层的库,越是往后面写!

例如:

  1. 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) (+修正与解释)的更多相关文章

  1. Linux下g++编译thread出错的的解决方法

    错误如下图所示: 因为thread是C++11新加入的特性,所以我们在用g++编译的时候不能直接用,需要在g++后面加上 -std=c++0x -pthread 如果是gcc编译多线程的话则应该要用 ...

  2. Linux下Gcc生成和使用静态库和动态库详解

    参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...

  3. LINUX下文件编译

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...

  4. 从四个问题透析Linux下C++编译&链接

    摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...

  5. Linux下Gcc生成和使用静态库和动态库详解(转)

    一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...

  6. Linux环境g++编译TinyXML动态库

    除了CMarkup,tinyxml也是C/C++下解析XML很好的工具.在linux下用g++编译tinyxml的步骤如下(tinyxml版本2.6.2): 进入tinyxml解压目录,用文本编辑器打 ...

  7. FFmpeg在Linux下安装编译过程

    转载请把头部出处链接和尾部二维码一起转载,本文出自:http://blog.csdn.net/hejjunlin/article/details/52402759 今天介绍下FFmpeg在Linux下 ...

  8. 【转】Linux下gcc生成和使用静态库和动态库详解

    一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不 ...

  9. Linux下GCC生成和使用静态库和动态库【转】

    本文转载自:http://www.cppblog.com/deane/articles/165216.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本 ...

随机推荐

  1. iOS代码规范(OC和Swift)

    下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...

  2. javascript动画系列第三篇——碰撞检测

    前面的话 前面分别介绍了拖拽模拟和磁性吸附,当可视区域内存在多个可拖拽元素,就出现碰撞检测的问题,这也是javascript动画的一个经典问题.本篇将详细介绍碰撞检测 原理介绍 碰撞检测的方法有很多, ...

  3. ExtJS 4.2 Grid组件的单元格合并

    ExtJS 4.2 Grid组件本身并没有提供单元格合并功能,需要自己实现这个功能. 目录 1. 原理 2. 多列合并 3. 代码与在线演示 1. 原理 1.1 HTML代码分析 首先创建一个Grid ...

  4. .NET Core的日志[5]:利用TraceSource写日志

    从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试和跟踪信息的日志记录.在.NET ...

  5. 谈谈一些有趣的CSS题目(二)-- 从条纹边框的实现谈盒子模型

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  6. JAVA构造时成员初始化的陷阱

    让我们先来看两个类:Base和Derived类.注意其中的whenAmISet成员变量,和方法preProcess(). 情景1:(子类无构造方法) class Base { Base() { pre ...

  7. VC中的MFC到底是什么?

    1. 微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API ...

  8. 中国CIO最关心的八大问题(上)

    中国CIO最关心的八大问题(上) 近期,ITValue和ValueResearch联合展开<IT决策者投资与生存状态大调查>,调查范围从关注CIO本身,延展至关注CIO所供职企业--其赖以 ...

  9. MySQL常见面试题

    1. 主键 超键 候选键 外键 主 键: 数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合.一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null). 超 键: 在关系中 ...

  10. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...