linux g++编译以及库多重依赖

2023-10-26

目录

一、编译命令

二、编译相关选项

三、静态库和动态库的编译命令

1、生成动态库和静态库

2、-fPIC选项

3、如何解决运行时找不到链接库的问题

四、库多重依赖

1、动态库依赖动态库

2、动态库依赖静态库

3、静态库依赖静态库


一、编译命令

g++ –c Hello.cpp  编译文件,生成目标文件Hello.o

g++ Hello.o –o a.out  链接并重命名为可执行文件a.out

g++ Hello.cc    编译链接一起,生成a.out

g++ Hello.cc –o hello 生成a.out并命名为hello

二、编译相关选项

(1)-c

生成.o文件,对代码文件进行预处理、编译和汇编,相当于windows下生成目标文件obj

g++ -c hello.cpp

(2)-I DirPath

指定包含文件

-include file

-i file

指定包含目录

-I path

g++ hello.cpp -include ../include/a.h

-I- DirPath

就是取消前一个参数的功能,所以一般在-I DirPath之后使用

(3)-L LibPath

指定链接库的路径

-l LibraryPath

指定链接库

-llibrary

(4)  -g   
在编译的时候,产生调试信息,程序运行时可以dbg调试

(4)-static

此选项将禁止使用动态库。

优点:程序运行不依赖于其他库

缺点:文件比较大

gcc test_main.c -static -o test_main -lpthread

会发现test_main很大,它已经把各种依赖的东西都包含进来

(5) -shared (-G)

此选项将尽量使用动态库,为默认选项

优点:生成文件比较小

缺点:运行时需要系统提供动态库

(6)-Wall

一般使用该选项,允许发出GCC能够提供的所有有用的警告。也可以用-W{warning}来标记指定的警告。

三、静态库和动态库的编译命令

1、生成动态库和静态库

(1)得到hello.o

g++ -c hello.cpp

(2)得到静态库myhello.a

ar -cr libmyhello.a hello.o

(3)使用静态库

g++ -o hello main.c -L ./ -lmyhello

-L ./表示静态库位于当前目录下,myhello自动加上lib组成静态库名称libmyhello.a

(4)得到动态库myhello.so

 g++ -fPIC -shared hello.cpp -o libmyhello.so

(5)使用动态库

动态库的时候和静态库使用一样,唯一值得注意的是当目录中同时存在相同名称的动态库和静态库时,编译的时候优先使用动态库

2、-fPIC选项

加上-fPIC选项生成的动态库时位置无关的,可以实现多个进程共享动态库,多个进程引用同一个PIC动态库时,可以共享内存。这一个库在不同进程中的虚拟地址不同,但操作系统显然会把它们映射到同一块物理内存上。

不加fPIC,则加载so文件时,需要对代码段引用的数据对象需要重定位,重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于这个.so文件代码段和数据段内存映射的位置。可见,这种方式更消耗内存。

3、如何解决运行时找不到链接库的问题

(1)将链接库添加到系统默认的搜索路径下,如/lib、/usr/lib

(2)设置临时动态库路径的环境变量,这种方法设置的是临时的,系统重启之后就没了

export LD_LIBRARY_PATH=./

取消设置

export LD_LIBRARY_PATH=

(3)/etc/ld.so.cache中缓存了动态库路径,可以通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变

(4)编译链接添加-Wl,-rpath命令选项,将运行时动态库的搜索路径记录在可执行程序中

例如,有源文件test.cpp和func.cpp

g++ -shared -fPIC func.cpp -o libfunc.so

编译得到libfunc.so动态库

g++ main.cpp -o a.out -L ./ -lfunc

编译得到a.out,执行a.out,提示出错

ldd查看a.out依赖的动态库,发现libfunc.so找不到

g++ main.cpp -o a.out -L ./ -lfunc -Wl,-rpath ./

编译得到a.out,执行a.out,运行成功,ldd查看a.out依赖的动态库,发现libfunc.so路径正确

把a.out和libfunc.so拷贝到任何目录下,都能运行成功

-Wl:这个是gcc的参数,表示编译器将后面的参数传递给链接器ld。

-rpath:使用man ld命令查看手册,找到了-rpath的讲解:

Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects. All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared objects at runtime. The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link; see the description of the -rpath-link option. If -rpath is not used when linking an ELF executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.

四、库多重依赖

//world.cpp
#include <stdio.h>

void world(void)
{
    printf("world.\n");
}
//hello.cpp
#include <stdio.h>

void world(void);

void hello(void)
{
    printf("hello\n");
    world();
}
//test.cpp

void hello(void);

int main(void)
{
    hello();
    return 0;
}

1、动态库依赖动态库

动态库hello编译时需要链接world,并需要设置-Wl,-rpath ./

test编译时只需要链接hello,并需要设置-Wl,-rpath ./

(1)编译word动态库

g++ -shared -fPIC world.cpp -o libworld.so

(2)编译hello动态库

g++ -shared -fPIC hello.cpp -o libhello.so

ldd libhello.so

查看libhello.so的依赖库,没有看到依赖libword.so

g++ -shared -fPIC hello.cpp -o libhello.so -L ./ -lworld

ldd libhello.so

再次查看libhello.so的依赖库,看到了依赖库libword.so,但显示not found

g++ -shared -fPIC hello.cpp -o libhello.so -L ./ -lworld -Wl,-rpath ./

(3)编译可执行文件test

g++ test.cpp -o a.out -L ./ -lhello -lworld -Wl,-rpath ./

编译通过,得到可执行文件a.out,运行成功

2、动态库依赖静态库

静态库world编译也需要设置-fPIC选项

动态库hello需要链接world,但是不需要添加-Wl,-rpath选项

(1)编译word静态库

g++ -c world.cpp

ar -cr libworld.a world.o

(2)编译hello动态库

g++ -shared -fPIC hello.cpp -o libhello.so -L ./ -lworld

编译报错,因为world也必须使用-fPIC,重新编译

(3)编译可执行文件

g++ test.cpp -o a.out -L ./ -lhello -Wl,-rpath ./

3、静态库依赖静态库

一种方法是,  hello和world静态库都独立编译,编译test时链接两个静态库,被调用库调用顺序靠后。静态库依赖有顺序,动态库没有。

另一种方法是,编译hello静态库时,将hello.o和world.o都包含进去。

(1)编译world静态库

g++ -c world.cpp

ar -cr libworld.a world.o

(2)编译hello静态库

g++ -c hello.cpp

ar -cr libhello.a hello.o

(3)编译可执行文件

g++ test.cpp -o a.out -L ./ -lworld -lhello

因为静态库的依赖有顺序,被调用库应该放在调用库后面,动态库没有依赖顺序,正确输入如下

g++ test.cpp -o a.out -L ./ -lhello -lworld

 (4)静态库包含静态库

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux g++编译以及库多重依赖 的相关文章

随机推荐

  • Python数据分析8-时间序列

    目录 8 1datetime模块 8 1 1datetime的构造 8 1 2数据转换 8 2时间序列基础 8 2 1时间序列构造 8 2 2索引与切片 8 3日期 8 3 1日期范围 8 3 2频率与移动 8 4时期 8 4 1时期基础
  • 什么是推荐系统?推荐系统类型、用例和应用

    推荐系统是机器学习的一类 它可使用数据来帮助预测 缩小范围 并找到人们在呈指数级增长的选项中寻找的内容 什么是推荐系统 推荐系统是一种人工智能或人工智能算法 通常与机器学习相关 使用大数据向消费者建议或推荐其他产品 这些推荐可以基于各种标准
  • 构建IoT系统必须的五项内容 (Page 3)

    本文译至 http japan zdnet com article 35076390 3 2 高度的分析实现 抽取出的高精度特征值适用于机器学习算法 从时间序列数据计算异常度 自动检查异常状况或变化点 图5 等 能应用于人眼难以判断的现象的
  • C++中如何进行txt文件的读入和写入

    大家可能大部分写代码都是在devc或者 vs里面直接输入数据 这一般常见于简单算法和数据的处理 但是一旦处理大数据的话 几百万 几千万 上亿个数据手打似乎不能轻易实现的 那么这篇文章我们来搞懂C 环境下如何进行io流读取txt文件 其实我们
  • MYSQL:如何清空表中的数据(一张表和多张表)

    方法1 delete from 表名 方法2 truncate table 表名 比 较 1 gt truncate 是整体删除 速度较快 delete是逐条删除 速度较慢 2 gt truncate 不写服务器 log delete 写服
  • 如何设置笔记本电脑扩展屏幕的亮度

    方法一 通过外设显示屏的本身按钮直接调节 方法二 打开控制面板 查看方式 小图标 英特尔 显卡设置 颜色设置 选择显示器 亮度 对比度调节 或鼠标右键找到英特尔 显卡设置
  • C++ 51.基于多态的职工管理系统(7)——删除职工功能

    功能描述 按照员工的编号进行删除职工操作1 删除职工函数声明 在workerManager h中添加成员函数 删除职工 void Del Emp 2 职工是否存在函数声明 按照职工编号判断职工是否存在 在workerManager h中添加
  • matlab数字和字符串转换

    一 数字转字符串 1 整数转字符串 int1 10 num2str int1 2 小数转字符串 dec1 1 23456 1 方法1 num2str dec1 6 保留6位有效数 2 方法2 num2str dec1 6f 保留小数点后6位
  • 解决axios发送数据到后端中文乱码问题

    解决axios发送数据到后端中文乱码问题 axios请求 const that this axios method post url http localhost 8080 2 SelectByIdServlet data this stu
  • Altium Designer22中修改元件库后,更新原理图的2种方法及这2种方法的区别。

    PCB设计过程中 经常会涉及到修改原理图库和PCB库的情况 那么修改了这些库之后 如何更新到已经绘制好的原理图中呢 更新过程中 如果想保留设置好的description footprint和value等属性 又该如何设置呢 方法一 在原理图
  • python3:retrying模块

    retrying是一个python的重试包 可以用来自动重试一些可能运行失败的程序段 retrying提供一个装饰器函数retry 被装饰的函数就在运行失败的情况下将重新执行 默认只要一直报错就会不断重试 Web sit https git
  • FPGA零基础学习之Vivado-RTC实时时钟系统设计

    FPGA零基础学习之Vivado RTC实时时钟系统设计 本系列将带来FPGA的系统性学习 从最基本的数字电路基础开始 最详细操作步骤 最直白的言语描述 手把手的 傻瓜式 讲解 让电子 信息 通信类专业学生 初入职场小白及打算进阶提升的职业
  • mobx的使用

    mobx的使用 1 API mobx react Provider 包裹根组件 用于传递数据 observer 组件变为响应式 inject 接收mobx实例 用于类组件 MobXProviderContext mobx observabl
  • 远程控制---实验九:IPC远程植入木马

    目录 一 实验目的及要求 二 实验原理 IPC 空会话 IPC建立的过程 木马 三 实验环境 四 实验步骤及内容 五 实验总结 六 分析与思考 一 实验目的及要求 1 掌握利用 IPC 入侵目标计算机 windows XP 或 window
  • Java虚拟机内存参数设置

    Java虚拟机内存参数设置 前言 Java虚拟机 JVM 是一种抽象的计算机器 JVM是一个程序 对于编写在其中执行的程序来说 它看起来像一台机器 通过这种方式 Java程序被写入相同的接口和库集 针对特定操作系统的每个JVM实现都将Jav
  • 使用nginx反向代理docker安装的jenkins

    描述 使用nginx反向代理jenkins nginx反向代理 docker安装的jenkins 方法 一 nginx反向代理docker安装的jenkins 1 使用 vim etc nginx nginx conf进入nginx 的配置
  • Typescript类型注解和类型推断

    在TypeScript中有两个基本概念 类型注解和类型推断 这两个概念在我们使用TypeScript代码时会一直使用 一 类型注解 type annotation 如 let count number count 123 这种就是类型注解
  • QT运行出现The CDB process terminated解决办法(亲测有效)

    QT运行出现The CDB process terminated解决办法 运行程序时出现如图所示的问题 检查2件事 1 检查编译器和调试器 工具 选项 构建和运行 如果是电脑图标证明不是这里的问题 如果出现黄色的感叹号证明编译器和调试器没有
  • XNA简介

    href file C DOCUME 1 ADMINI 1 LOCALS 1 Temp msohtml1 02 clip filelist xml rel File List gt XNA简介 XNA简介 首先声明 XNA不是游戏引擎 它只
  • linux g++编译以及库多重依赖

    目录 一 编译命令 二 编译相关选项 三 静态库和动态库的编译命令 1 生成动态库和静态库 2 fPIC选项 3 如何解决运行时找不到链接库的问题 四 库多重依赖 1 动态库依赖动态库 2 动态库依赖静态库 3 静态库依赖静态库 一 编译命