【转】gcc/g++ 链接库的编译与链接

转自:gcc/g++ 链接库的编译与链接_Surge-CSDN博客_g++ 链接

 gcc/g++ 链接库的编译与链接

surgewong@gmail.com

Surge_surgewong_CSDN博客

      程序编译一般需要经预处理、编译、汇编和链接几个步骤。在实际应用中,有些公共代码需要反复使用,就把这些代码编译成为“库”文件。在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中,这种库称为静态(链接)库,其特点是可执行文件中包含了库代码的一份完整拷贝,缺点是被多次使用就会多份冗余拷贝。还有一种库,就是程序在开始运行后调用库函数时才被载入,这种库独立于现有的程序,其本身不可执行,但包含着程序需要调用的一些函数,这种库称为动态(链接)库(Dynamic Link Library)

       在widows平台下,静态链接库是.lib文件,动态库文件是.dll文件。在linux平台下,静态链接库是.a文件,动态链接库是.so文件。这里主要讲在linux平台下的动态库和静态库的生成以及链接。本文主要参考【1】【2】【3】【4】

一、库的基本知识

     首先说明要对库有一个比较直观的理解。库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上说来库是一种可执行代码的二进制形式(注,其本身不可执行),可以被操作系统载入内存执行。

       静态链接库,之所以称为“静态库”,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,因此对应的链接方式为静态链接。其实一个静态链接库可以简单看成一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结:

              1. 静态库对函数库的链接是放在编译时期完成

              2. 程序在运行时对函数库再唔瓜葛,一直方便。

              3. 浪费空间和资源,因为所有相关的目标文件和牵涉到的函数库被链接合成一个可执行文件。

       linux下使用ar工具(windows下用lib.exe)(具体的用法参考【5】),可以将目标文件压缩到一起,并且对其进行编号和索引,一便于查找和索引。一般创建静态链接库的步骤如下:

        静态链接库的命名规则,库的名称和库文件名称不同,有联系,假定库名称为"my_library_name",那么起库文件名为"lib[my_library_name].a"(方括号是为了区分,实际上没有)

        动态链接库,在程序编译是并不会被连接到目标代码中,而是在程序运行时才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库的一些总结:

           1. 动态库把对一些库函数的链接载入推迟到程序运行时期

           2. 可以实现进程之间的资源共享,(动态库也成为共享库)

           3. 将一些程序升级变得简单

           4. 设置可以真正做到链接载入完全由程序员在程序代码中控制(显式调用)

        Linux下gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。与windows系统下的格式不同。与创建静态库不同的是,不需要打包工具,直接使用编译器即可创建动态库。

        动态链接库的命名规则,与静态链接库的方式相同,不过其后缀名为.so,命名形式为 "lib[my_library_name].so"     。但是在实际使用过程中libxxx.so 大多数情况只是一个链接,它链接到一个包含版本信息的库文件 libxxxx.so.xx,如下图。当然自己可以使用 ln 命令,制作链接 ln -s libxxxx.so.xx libxxxx.so。

二、库的编译和链接

        下面使用一个例子来说明链接库是如何生成与链接的。这个例子的源代码参考【4】。这里有五个文件,头文件“SoDemoTest.h”,三个cpp文件“one.cpp”、"two.cpp"、"three.cpp",main函数实现文件“main.cpp”。

#ifndef _SO_DEMO_TEST_HEADER_
#define _SO_DEMO_TEST_HEADER_
#include <iostream>
using namespace std;
void one();
void two();
void three();
#endif
/* one.cpp */
#include "SoDemoTest.h"
void one(){cout << "call one() function" << endl;
}
/* two.cpp */
#include "SoDemoTest.h"
void two(){cout << "call two() function" << endl;
}
/* three.cpp */
#include "SoDemoTest.h"
void three(){cout << "call three() function" << endl;
}

/* main.cpp */
#include "SoDemoTest.h"
int main(){one();two();three();return 0;
}


 

      gcc/g++的编译参数,这里只介绍 -L 、-l、-include、-I、-shared、-fPIC

      -L :表示要链接的库所在的目录。-L.  表示要链接的库在当前目录, -L/usr/lib 表示要连接的库在/usr/lib下。目录在/usr/lib时,系统会自动搜索这个目录,可以不用指明。

     -l (L的小写):表示需要链接库的名称,注意不是库文件名称,比如库文件为 libtest.so,那么库名称为test

     -include :包含头文件,这个很少用,因为一般情况下在源码中,都有指定头文件。

      -I (i 的大写):指定头文件的所在的目录,可以使用相对路径。

     -shared :指定生成动态链接库

     -fPIC:  表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时事通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码共享的目的。

      生成链接库

      第1步,生成目标文件:g++ -c xxx.cpp

       第2步,创建静态链接库:  ar  cqs  libxxxx.a  xx1.o xx2.o xx3.o (参数选项请看【5】)

        第3步,程序中使用静态链接库

        第4步,创建动态链接库 g++ -fPIC -shared -o libxxx.so xx1.cpp xx2.cpp xx3.cpp

        第5步,动态链接库使用

       库的链接,上面简单演示了一遍库的生成过程,但是还有很多细节没有讲清楚。以下问题需要注意:

       1. 链接过程中可能出现多种链接方式,需要使用一些参数来指定,下面只是一个演示,在测试时,自己填写具体的名称

g++ testmain.o -o testmain -WI,-Bstatic -lstaticlib -WI,-Bdynamic -ldynamiclib


 

       2. 链接过程中同一个库(名称相同)的静态和动态两种链接库,在链接过程中,系统优先选择动态链接库

     3. 动态链接库路径,系统默认在/usr/lib 和/usr/local/lib两个库目录搜索,自己定义的库需要格外指定路径(设定变量LD_LIABRARY_PATH)或者将其拷贝到这两个目录下,在上面的例子的测试过程,已经有说明。当然也可以将当前路径添加到/etc/ld.so.conf文件中或者/etc/ld.so.conf.d目录下的一个文件中。

      4. 查看动态链接库。 有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种:

        一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;

        一种是在库中定义的函数,用T表示,这是最常见的;

        另一种所谓的“弱态”符号,它们虽然在库中定义,但可能被其他库中的同名符号覆盖,用W表示。

         使用ldd命令可以查看程序的库依赖:

         注:更多详细的信息请阅读下面的链接中的内容~

       

【1】博客园:C++静态库与动态库

【2】CSDN:Linux 静态库&动态库调用

【3】博客园:gcc/g++ 动态编译和链接问题

【4】Linux公社:用g++编译生成动态连接库*.so的方法及连接

【5】CSDN:linux ar命令

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

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

相关文章

常用WebServices返回数据的4种方法比较

以前经常在群里听到朋友们说WebServices的性能特别的慢&#xff0c;说的如何如何。说实话&#xff0c;WebServices的确比调用本地数据要慢一些&#xff0c;可是究竟有多慢&#xff0c;真的如朋友们说的那么难以忍受吗&#xff1f;我个人感觉&#xff0c;多半原因在处理的方式上…

让S3c2410里拥有HIVE注册表的 全部步骤

首先&#xff0c;我是花了几天的时间才搞好的&#xff0c;当然我也在网上找了很多资料&#xff0c;可是网上朋友说可行的方法&#xff0c;我试来试去就是不行&#xff0c;这我也不清楚为什么&#xff0c;一开始有说用到BINFS格式的[指NandFlash分区格式]&#xff0c;后来又看到…

【转】vscode下编译告警“undefined reference”?三步教你如何解决

转自&#xff1a;vscode下编译告警“undefined reference”&#xff1f;三步教你如何解决_squall0984的博客-CSDN博客 近些年来&#xff0c;由于VS Studio体积庞大、价格昂贵等原因&#xff0c;越来越多的C/C开发者转投VSCode的怀抱。VSCode有着免费1、开源2、多平台支持、占…

写在S3C2440A平台+winCE5.0+NAND +HIVE注册表的实现

最近一直弄这个注册表的永久保存&#xff0c;在网上看到很多相关的贴子&#xff0c;就像大部分人说的一样&#xff0c;很少有人照着做就可以成功的。 今天总算成功了&#xff0c;总结经验如下&#xff0c;但愿对后来者有所帮助。 首先&#xff0c;要实现注册表的永久保存&…

非常实用的Asp.net常用的51个代码

1.弹出对话框.点击转向指定页面 Code: Response.Write("<script>window.alert(该会员没有提交申请,请重新提交&#xff01;)</script>");Response.Write("<script>window.location http://www.msproject.cn/index.asp</script>");…

【转】VScode tasks.json和launch.json的设置

转自&#xff1a;VScode tasks.json和launch.json的设置 - 知乎 目录 C&#xff08;方法1&#xff1a;不使用VSCode插件&#xff0c;较繁琐&#xff09;C&#xff08;方法2&#xff1a;使用Native Debug插件&#xff09;C&#xff08;方法3&#xff1a;使用C/C Compile Run插…

小处见大问题

如果有以下几种很简单的需求&#xff0c;可是小需要中隐藏着大问题。 给页面添加4个web按钮&#xff0c;点击4个按钮分别实现 &#xff08;1&#xff09;打开一个摸态对话框 &#xff08;2&#xff09;页面在客户端转向 &#xff08;3&#xff09;页面转向并且进行一个服务器端…

巧手定制Windows CE系统

嵌入式系统正在日益广泛的应用于各个方面&#xff0c;嵌入式系统的最大特点在于其精简和实时性。公司近期委派我负责一个新的嵌入式系统项目&#xff0c;因为是小型设备&#xff0c;所以我面临的第一个难题是需要找一个体积少&#xff0c;但非常灵活添加外围接口的嵌入式系统。…

【转】vscode配置C/C++环境

转自&#xff1a;vscode配置C/C环境 - 知乎 VS Code配置作者&#xff1a;谭九鼎 链接&#xff1a;Visual Studio Code 如何编写运行 C、C 程序&#xff1f; - 知乎 有改动。个人按照步骤后&#xff0c;做到复制上三个json那一步&#xff0c;就可以运行了。 我将settings.json…

Boot Loader的启动流程和开发经验总结

Windows CE最大程度继承了桌面版Windows的丰富功能&#xff0c;但是Windows CE并不是一个通用的安装版操作系统。在形形色色的嵌入式设备世界里&#xff0c;一款CE系统通常只会针对某一种硬件平台生成。 一般来说&#xff0c;Windows CE的开发过程可以分为&#xff1a;0AL…

c# 相对路径的一些文献

1.获取和设置当前目录的完全限定路径。string str System.Environment.CurrentDirectory;Result: C:\xxx\xxx2.获取启动了应用程序的可执行文件的路径&#xff0c;不包括可执行文件的名称。string str System. Windows .Forms.Application.StartupPath;Result: C:\xxx\xxx3.获…

【转】dicom网络通讯入门(1)

转自&#xff1a;dicom网络通讯入门&#xff08;1&#xff09; - assassinx - 博客园 如果只看标准就会越看越糊涂&#xff0c;根本原因就是因为dicom抽象得太严重&#xff0c;是“专家”弄的。没办法。 那么到底服务类是什么&#xff1f;sop 又是什么&#xff1f;&#xff0…

三种嵌入式操作系统的分析与比析

1.1 嵌入式系统 嵌入式系统是以嵌入式计算机为技术核心&#xff0c;面向用户、面向产品、面向应用&#xff0c;软硬件可裁减的&#xff0c;适用于对功能、可靠性、成本、体积、功耗等综合性能有严格要求的专用计算机系统。 嵌入式系统应具有的特点是&#xff1a;高可靠性&#…

用WebORB实现flex + .net后台的Remoting

实现flex与后台通信最简单的方式是采用httpServic的方式&#xff0c;或webservice。但这两种方式都是基于文本的传输&#xff0c;传输效率低&#xff0c;采用RemoteObject的方式&#xff0c;传输的内容采用AMF3格式的二进制编码&#xff0c;效率较高&#xff0c;并且能实现远程…

【转】dicom网络通讯入门(2)

转自&#xff1a;dicom网络通讯入门&#xff08;2&#xff09; - assassinx - 博客园 首先我们现一个echo响应测试工具&#xff0c;也就是echo 的scu&#xff0c;不是实现打印作业管理么。同学我告诉你还早着呢。本来标题取的就是《dicomviewer 第二弹 之 实现打印管理》名字多…

基于WINCE6.0下载multiple XIP镜像文件

备注&#xff1a;基于usb下载的方式&#xff0c;MLC nand flash为K9G8G08U 1. Multiple XIP模式的文件说明 Multiple XIP模式下生成的文件有chain.bin、chain.lst、NK.bin、xip.bin和xipkernel.bin&#xff0c;如下图所示&#xff1a; 图1 2. Eboot下载Multiple XI…

Final Michael Scofield

转载于:https://www.cnblogs.com/andrewx/archive/2009/08/16/1547738.html

【转】dicom网络通讯入门(3)

转自&#xff1a; dicom网络通讯入门&#xff08;3&#xff09; - assassinx - 博客园 接下来可以进行消息传递了 &#xff0c;也就是dimse &#xff0c;再来复习下 什么是dimse 。n-set n-create c-echo 这些都是dimse 他们都是属于一种结构的pdu 那就是tf-pdu&#xff08;传…

从零开始学习jQuery (三) 管理jQuery包装集【转】

一.摘要 在使用jQuery选择器获取到jQuery包装集后, 我们需要对其进行操作. 本章首先讲解如何动态的创建元素, 接着学习如何管理jQuery包装集, 比如添加,删除,切片等. 二.前言 本系列的2,3篇上面列举了太多的API相信大家看着眼晕. 不过这些基础还必须要讲, 基础要扎实.其实对于…

【转】ubuntu 下 VNCview 远程桌面无法传输文件问题

转自&#xff1a;ubuntu18.04VNCview文件传输问题_gsls200808的专栏-CSDN博客_vnc传输文件按钮不可用 很多文章说VNCview不能传输文件&#xff0c;实际上这是一个误区。 以ubuntu为例&#xff0c;默认使用 sudo apt-get vnc4server 这个命令安装上的vncserver实际是tigerVNC…