[转]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(1, 1) << std::endl;std::cout << "1 - 1 = " << MINUS(1, 1) << std::endl;return 0;
}

重要说明:

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

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

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

 

  贴上Makefile,有注解:

all: main-1 main-2 main-a main-so main-so2main-1: myAPI.cpp main.cpp myAPI.hg++ -o main-1 myAPI.cpp main.cpp@echo "main-1 done.  直接编译省略显示编译.o文件"@echomain-2: main.cpp myAPI.og++ -o main-2 myAPI.o main.cpp@echo "main-2 done.  显示编译.o文件"@echomain-a: libmyAPI.ag++ -o main-a  main.cpp libmyAPI.a@echo "main-a done.  使用.a静态库文件 链接生成程序"@echomain-so: libmyAPI.sog++ -o main-so main.cpp ./libmyAPI.so@echo "main-so done.  直接使用.so动态库文件(需要带路径,运行时直接使用此路径) 链接生成程序"@echomain-so2: libmyAPI.sog++ -o main-so2 main.cpp -L. -lmyAPI@echo "main-so2 done.  让g++自动在当前目录("."表示当前目录,或"./")查找.so动态库文件 链接生成程序"@echo "    但运行时默认到/usr/lib目录查找,,或运行前设置环境变量 LD_LIBRARY_PATH 为动态库的路径"@echomyAPI.o: myAPI.cpp myAPI.hg++ -c myAPI.cpp@echo "myAPI.o done.  编译.o文件"@echolibmyAPI.a: myAPI.oar crv libmyAPI.a myAPI.o@echo "libmyAPI.a done.  编译.a静态库文件"@echolibmyAPI.so:g++ -fPIC -c myAPI.cppg++ -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-1
1 + 1 = 2
1 - 1 = 0
[root@lzp test2]# ./main-2
1 + 1 = 2
1 - 1 = 0
[root@lzp test2]# ./main-a
1 + 1 = 2
1 - 1 = 0
[root@lzp test2]# ./main-so
1 + 1 = 2
1 - 1 = 0
[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]

转载于:https://www.cnblogs.com/lzpong/p/5776728.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cesium鼠标控制键盘_Cesium中级教程3 - Camera - 相机(摄像机)

CameraCesiumJS中的Camera控制场景的视图。有很多方法可以操作Camera&#xff0c;如旋转(rotate)、缩放(zoom)、平移(pan)和飞到目的地(flyTo)。CesiumJS有鼠标和触摸事件用来处理与Camrea的交互&#xff0c;还有API来以编程方式操作摄像机。了解如何使用Camera API和自定义相机…

JAVA Junit error java.lang.SecurityException: class junit.framework.JUnit4TestCaseFacade

运行junit4时报错: java.lang.SecurityException: class "junit.framework.JUnit4TestCaseFacade"s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(Unknown Source) at java.lan…

windows下统一mysql编码_mysql5.7 windows7编码统一utf-8

查看mysql数据编码登录mysql服务&#xff0c;查看mysql数据库默认的编码mysql> show variables like character%;---------------------------------------------------------------------------| Variable_name | Value |------------------------------------------------…

复制选中的listbox内容

private void lt_log_MouseClick(object sender, MouseEventArgs e){Clipboard.SetDataObject(lt_log.SelectedItem.ToString()); }转载于:https://www.cnblogs.com/XuPengLB/p/5779554.html

heroku_WhateverOrigin –与Heroku和Play对抗原产地政策! 构架

heroku不久前&#xff0c;在编写 Bitcoin Pie时 &#xff0c;我发现有必要克服臭名昭著的Same Origin Policy &#xff0c;该政策限制了运行在客户端浏览器上的javascript可以访问的域。 通过Stack Overflow&#xff0c;我找到了一个名为Any Origin的站点&#xff0c;这基本上是…

python读取配置文件失败原因_python读取配置文件报keyerror-文件路径不正确导致的错误...

- 在其他模块使用反射读取配置文件报错&#xff0c;但是在反射模块中读取GetData.check_list又是正确的反射模块如下&#xff1a;# get_data.pyfrom API_AUTO.p2p_project_7.tools import project_pathimport pandas as pdfrom API_AUTO.p2p_project_7.tools.read_config impor…

备忘录设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

redis命令学习

清空所有flushall 转载于:https://www.cnblogs.com/dragkiss/p/5784814.html

打印机一直显示正在删除不掉怎么办?

1、停止打印服务&#xff0c;按WinR键打开运行对话框&#xff0c;然后输入“services.msc ” 打开任务管理。 找到“Print Spooler”&#xff0c;先停止该服务。 按WinR键打开运行对话框&#xff0c;然后输入“Spool” 回车打开“spool” 文件夹&#xff0c;打开“PRINTERS”文…

java 并发 面试_Java 并发基础常见面试题总结

1. 什么是线程和进程?1.1. 何为进程?进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。系统运行一个程序即是一个进程从创建&#xff0c;运行到消亡的过程。在 Java 中&#xff0c;当我们启动 main 函数时其实就是启动了一个 JVM…

web性能测试基础 知识(引用)

1.1基本概念 并发用户&#xff1a;用户并发一般发生在使用比较频繁的模块中&#xff0c;而且遇到异常通常都是程序的问题。 用户并发数量&#xff1a;在线用户数量是计算并发用户数量的主要依据之一。使用系统的用户数量*(5%~20%) 并发主要针对WEB服务器而言&#xff0c;是否并…

javafx动画_JavaFX:创建Sprite动画

javafx动画到目前为止&#xff0c;尽管我的大多数文章都涉及JavaFX属性和绑定&#xff0c;但是今天我想写一讲我也致力于JavaFX运行时的另一部分&#xff1a;动画API。 在本文中&#xff0c;我将解释如何在JavaFX中编写自定义动画&#xff0c;以及如何使用这种方法为Sprite动画…

java自定义迭代器作用_Java实现的自定义迭代器功能示例

本文实例讲述了Java实现的自定义迭代器功能。分享给大家供大家参考&#xff0c;具体如下&#xff1a;编写自己的Iterator&#xff0c;实现Iterator接口&#xff0c;这里多说一句&#xff0c;实现Iterable后&#xff0c;可以用“foreach”循环遍历你的对象。import java.util.It…

FZU Problem 2238 Daxia Wzc's problem

Daxia在2016年5月期间去瑞士度蜜月,顺便拜访了Wzc,Wzc给他出了一个问题&#xff1a; Wzc给Daxia等差数列A(0),告诉Daxia首项a和公差d; 首先让Daxia求出数列A(0)前n项和,得到新数列A(1); 然后让Daxia求出数列A(1)前n项和,得到新数列A(2); 接着让Daxia求出数列A(2)前n项和,得到新…

生成器设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

java项目遇到的问题_java系列:项目中遇到的一些问题(持续更新中)

JSONArray去重的问题 JSONArray array = ["2","0","0","0","0","0"]; private String[] instanceAaary(JSONArray array) throws JSONException{String[] strs = new String[array.length()]; for (int i = 0; i …

【转】从 ArcGIS for Desktop 发布地图服务

原文链接&#xff1a;http://resources.arcgis.com/zh-CN/help/tutorials/01z300000007000000.htm 本教程的目的是将地图服务直接从 ArcGIS for Desktop 发布到 ArcGIS for Server 中。本教程与名为“在 ArcMap 中准备您的 Web 地图”的上一教程类似&#xff0c;需要使用 ArcGI…

Java tree set_Java TreeSet tailSet()方法

Java TreeSet tailSet()方法java.util.TreeSet.tailSet(E fromElement) 方法用于返回一组大于或等于指定元素的元素。1 语法public SortedSet tailSet(E fromElement)2 参数fromElement&#xff1a;这是返回集的最小边界值(包括该边界值)3 返回值返回此集合中元素大于或等于fro…

java map练习_JAVA Map练习

JAVA Map练习作者&#xff1a;萤火之森2015-04-21 12:46浏览&#xff1a;1203package pack3;import java.util.HashMap;import java.util.Iterator;import java.util.*;import java.util.Set;/*** 每一个学生都有对应的归属地* 学生Student 地址String* 学生属性&#xff1a;姓…

Objective-C 反射机制

该文章属于<简书 — 刘小壮>原创&#xff0c;特此感谢&#xff1a;<简书 — 刘小壮> http://www.jianshu.com/p/5bbde2480680 了解反射机制 Objective-C语言中的OC对象&#xff0c;都继承自NSObject类。这个类为我们提供了一些基础的方法和协议&#xff0c;我们可以…