Linux学习笔记——如何在交叉编译时使用共享库

2023-05-16

0.前言
    在较为复杂的项目中会利用到交叉编译得到的共享库(*.so文件)。在这种情况下便会产生以下疑问,例如:
    【1】交叉编译时的共享库是否需要放置于目标板中,如果需要放置在哪个目录中。
    【2】交叉编译时的共享库是否需要放置于宿主机中,如果需要放置于哪个目录中。
    【3】交叉编译时如何指定共享库
    【4】程序运行时如何查找共享库
    等等问题。
    
    博文总结了使用共享库的一般方法,并通过一个例子说明问题。如果已经有了交叉编译好的共享库,可以从【2】开始,步骤【1】只是为了说明问题,捏造一个简单的共享库试图说明问题。
    【1】交叉编译获得链接库
    【2】交叉编译源文件并加入链接库
    【3】移动动态链接库
    【4】执行
    【必要说明】
    【宿主机】Ubuntu 14.04 AMD64
    【目标板】树莓派
    
    【相关博文】
    【 例说makefile索引博文】
    【 树莓派学习笔记——交叉编译工具链】
    【代码仓库】—— makefile-example
    代码仓库位于bitbucket,可借助TortoiseHg(GUI工具)克隆代码或者在网页中直接下载zip包。    

1.交叉编译获得动态链接库
    本例先制作一个非常简单的共享库,共享库包含两个API——add和sub。
    【libtest.h】
    指定接口,给出相应声明
#ifndef __LIBTEST_H
#define __LIBTEST_H
int sub(int a, int b);
int add(int a, int b);
#endif
    【test-add.c】
int add(int a, int b)
{
    return a+b;
}
    【test-sub.c】
int sub(int a, int b)
{
    return a-b;
}
    【makefile】
    在同目录下包含makefile文件,请替换其中的[tab],并以代码仓库中的makefile文件为主。编译完成之后,把libtest.so移动到上级lib目录中。请注意此时的交叉工具链为arm-linux-gnueabihf-gcc
 ,目标b
# 指令编译器和选项
CC = arm-linux-gnueabihf-gcc
CFLAGS = -Wall -std=gnu99
# 目标文件
TARGET = libtest.so
# C文件
SRCS = test-add.c test-sub.c
# 目标文件
OBJS = $(SRCS:.c=.o)
# 链接为可执行文件
$(TARGET):$(OBJS)
[tab]$(CC) -shared -o $@ $^
[tab]mv $(TARGET) ../lib
clean:
[tab]rm -rf $(TARGET) $(OBJS)
# 编译规则 $@代表目标文件 $< 代表第一个依赖文件
%.o:%.c
[tab]$(CC) $(CFLAGS) -o $@ -fPIC -c $<
    【必要的验证】
    使用file指令查看libtest.so信息。
    file libtest.so
libtest.so: ELF 32-bit LSB   shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=e22558b8cf089b92e5534b636c6d501f1cc54581, not stripped
    从控制台的输出信息可以看出,libtest.so运行于ARM平台,而不是宿主机的AMD64平台。

2.交叉编译源文件并加入动态链接库
    【源文件】
#include <stdio.h>
#include <libtest.h>
int main(void)
{
    int a = 3;
    int b = 2;
       
    printf("a=%d\n", a);
    printf("b=%d\n", b);
   
    printf("a+b=%d\n", add(a, b));
    printf("a-b=%d\n", sub(a, b));
    return 0;
}
    【makefile文件】    
# 指定编译器和选项
# 指定树莓派交叉编译器
CC = arm-linux-gnueabihf-gcc
CFLAGS = -Wall -std=gnu99
# 目标文件
TARGET = test
# C文件
SRCS = test.c
# 头文件查找路径
INC = -I.
# 库文件和库查找路径
DLIBS = -ltest
LDFLAGS = -L./lib
# 目标文件
OBJS = $(SRCS:.c=.o)
# 链接为可执行文件
$(TARGET):$(OBJS)
[tab]$(CC) -o $@ $^ $(LDFLAGS) $(DLIBS)
clean:
[tab]rm -rf $(TARGET) $(OBJS)
# 编译规则 $@代表目标文件 $< 代表第一个依赖文件
%.o:%.c
[tab]$(CC) $(CFLAGS) $(INC) -o $@ -c $<
    【说明】
    【1】交叉工具链为arm-linux-gnueabihf-gcc
    【2】指定了交叉编译之后的共享库和共享库路径,链接共享库使用-ltest,共享库位于lib目录下。请注意-ltest对应libtest.so。
    【3】make之后可获得可执行文件,通过file test查看信息。
test: ELF 32-bit LSB   executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=88e4142dceabd295369657b29757141f98a03753, not stripped
    从控制台的输出可以看出,该可执行文件运行平台为ARM,而不是AMD64。
3.移动动态链接库
    【移动共享库至目标板/usr/lib目录中】
    通过FTP工具把共享库传输至树莓派中,然后通过cp指令复制到/usr/lib中
    sudo cp libtest.so /usr/lib
    linux系统中默认的搜多路径为/lib和/usr/lib,libtest.so可以复制到任何目录中。
    修改libtest.so的执行权限。
    sudo chmod 775 libtest.so
4.执行
    【FTP上传】
    通过FTP工具把可执行文件test复制到树莓派中,然后通过ldd指令查看共享库链接状态。
    【检验】
    ldd test
/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6f7f000)
libtest.so => /usr/lib/libtest.so (0xb6f6b000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6e3b000)
/lib/ld-linux-armhf.so.3 (0xb6f8d000)
    从控制台的输出可以看出,test成功链接了位于/usr/lib中的libtest.so
    【执行】
    ./test
a=3
b=2
a+b=5
a-b=1
    从执行结果看,前面所做的努力是正确的。
5.总结
    回答在前言中的问题。
    【1】交叉编译时的共享库是否需要放置于目标板中,如果需要放置在哪个目录中。
    交叉编译之后的共享库需要复制到目标板中,最好放置于/usr/lib或/lib中,当然也有其他的方法,在这里不详细说明。
    【2】交叉编译时的共享库是否需要放置于宿主机中,如果需要放置于哪个目录中。
    交叉编译时确切的说链接过程中需要指定共享库的问题,通过-L指定目录,通过-l指定共享库名称。但是此时交叉编译的共享库最好不要放置于宿主机的/lib或/usr/lib中,以免产生混淆。
    综合【1】和【2】,libtest.so同时存在于目标板和宿主机中。
    【3】交叉编译时如何指定共享库
    通过-L指定目录,通过-l指定共享库名称
    【4】程序运行时如何查找共享库
    最直观的方法,复制到/usr/lib目录中,让linux系统自动查找。
    最后,发现博文写多了自己感觉好累啊,希望这些总结对大家有用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux学习笔记——如何在交叉编译时使用共享库 的相关文章

  • window下c/c++异步发送udp和非阻塞的方式接收udp的类封装

    以下代码对udp发送和接收都做了封装 xff0c 在发送和接收前都需要去注册使用的功能 xff0c 从而做到需要哪个模块才启动哪个模块的功能 xff0c 避免资源的浪费 udp发送功能 使用列表和信号量的方式实现异步发送数据 xff0c 避
  • c/c++使用libhdfs对HDFS(Hadoop分布式文件系统)进行读写操作

    最近需要对HDFS进行读写操作 xff0c 参考hdfs h头文件里面的注解 xff0c 编写了一个例子 详细的说明在代码的注释中 如发现问题欢迎批评指正 span class token macro property span class
  • 使用c/c++将十六进制的stl字符串转换成IEEE - 754 浮点数

    span class token keyword typedef span span class token keyword union span span class token punctuation span span class t
  • 使用 C++ 处理 JSON 数据交换格式

    使用 C 43 43 处理 JSON 数据交换格式 一 摘要 JSON 的全称为 xff1a JavaScript Object Notation xff0c 顾名思义 xff0c JSON 是用于标记 Javascript 对象的 xff
  • C++ -- 智能指针( C++11与boost库的智能指针及其使用)

    1 智能指针的引入 1 在动态内存管理中 xff0c 如果new上一块空间 xff0c 但是没有delete xff0c 就会产生内存泄露的问题 2 但是有时候 xff0c 我们new了 xff0c 也delete了 xff0c 但是还会出
  • 动态库与静态库区别

    首先 xff0c 两者最重要的区别在于该库是否被编译进目标程序当中 静态库 xff1a 该库在编译的时候会直接整合到目标程序当中 xff0c 也就是说 xff0c 每个程序的静态库都是独立的 这样使得文件比较大 而且因为是编译的的时候整合进
  • 解决ubuntu20.04虚拟机无法上网的问题

    64 linux虚拟机无法正常上网 前言 刚建立好的linux虚拟机使用NAT方式可以连接外网 xff0c 系统重启几次 xff0c 系统无法上网 xff0c 这是什么问题导致的呢 xff1f 提示 xff1a 以下是本篇文章正文内容 xf
  • Arduino系列教程之 – PWM的秘密

    转载地址 xff1a http www diy robots com p 61 814 感谢作者的翻译 PWM是啥玩意儿 xff1f PWM是 怕玩命 的缩写 xff0c 英文写法是 Pulse width modulation xff0c
  • YOLOv2代码分析_读取labels[by zhangzexuan]

    YOLOv2代码分析 读取labels by zhangzexuan YOLOv2代码分析 读取labelsby zhangzexuan YOLOv2的输入代码阅读 嗯 现在参与的项目要求在人脸检测步骤直接连同人脸特征点一起预测出来 xff
  • 【企业微信】获取token & 发送应用消息

    企业微信获取token 存入redis 设置时长2小时 amp amp 发送企业应用消息接口 1 常量类 span class token keyword package span span class token namespace co
  • 学习笔记--HTTP-字段总结(一)-与传输实体相关的报文字段总结

    目录 一 概述 二 介绍一些常用字段 三 传输实体的一些属性 1 传输的数据类型 2 实体的语言类型和编码 3 编码类型 四 文件类型和压缩编码字段 1 Accept 2 Content Type 3 Accept Encoding 4 C
  • C/C++ 去掉宏定义__FILE__路径

    一 问题 在日志模块中往往带着文件信息 xff0c 有的源文件是加载其他路径下的源文件 xff0c 但是不想让别人看到文件路径信息 xff0c 只显示源文件的名字和行数即可 如下图所示 xff0c 有烦人的相对路径 二 解决方案 自定义一个
  • C语言提高(一)

    C语言提高 CS和BS的区别函数封装和数组形参退化为指针数据类型本质变量的本质内存分区模型全局区以文字常量区为例分析全局区 栈区堆区 函数的调用模型函数调用变量传递分析静态局部变量的使用栈地址的生长方向堆地址的生长方向内存的存放方向 以数组
  • ROS Gazebo(三):启动gazebo/URDF

    打开Gazebo的方式主要有两种 xff1a rosrun 和 roslaunch 1 启动ROS节点 启动ROS节点 bring up 机器人的标准工具是roslaunch 打开一个空的Gazebo世界命令如下 xff1a roslaun
  • Windows与Ubuntu之间通过网线传输文件

    一 windows与Ubuntu之间网线直连搭建局域网 把网线连好后 xff0c 在两个系统中做以下设置 Windows下的配置 右键右下角的网络图标 xff08 或者右键网络 属性 xff09 更改适配器设置 以太网 右键属性 TCP I
  • Jetson TX2——CAN口的使用

    Jetson TX2 之CAN口的使用 TX2上有2个CAN控制器 xff0c CAN控制器需要通过CAN收发器连接到物理总线上 具体参阅原理图和相关技术参考手册 下载地址 xff1a https developer nvidia com
  • Jetson TX2——串口的使用(TTL-RS485)

    Jetson TX2之串口的使用 xff08 TTL RS485 xff09 TX2串口设备 TX2 有5个 UARTs 到主连接器 其中UART3 用于 WLAN BT 有关 UARTs 的典型任务 请参见下表 查看可用串口设备 xff1
  • 面试题知识点全纪录---容器

    注意 xff1a 该博客仅是本人对掌握知识的测试 xff0c 具体内容请移步guide哥网站 xff01 xff01 xff01 https snailclimb gitee io javaguide 链接 JAVA集合框架 https w
  • 高并发-消息队列

    一 消息队列 消息队列在分布式系统中主要是为了解耦和削峰 什么是消息队列 我们可以把消息队列看作是一个存放消息的容器 xff0c 当我们需要使用消息的时候 xff0c 直接从容器中取出消息供自己使用即可 消息队列是分布式系统中重要的组件之一
  • Ublox-M8N GPS接收机UBX协议解析

    Ublox M8N GPS接收机UBX协议解析 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61

随机推荐

  • Java清空List方法

    1 用list clear 方法清空list xff1b 用此方法 xff0c 其它引用该list的值也会变成空 2 用list 61 null来清空list 3 new ArrayList 来清空list
  • fastjson用java转json时间的格式化

    一 项目中需求遇到需要接收其他应用数据 xff0c 通过 64 RequestBody注解接收参数后 xff0c 到本地利用fastJson把json格式化 需要注意一下几点 xff1a 需要在调用JSON toJSONString 的时候
  • 工具类里面调用service接口或者mapper接口

    我们在开发中经常会遇到需要将一些频繁进行的操作抽取封装到工具类中 xff0c springboot不支持注入静态属性 所以在工具类中使用 64 Autowired或者其他注解自动注入会失败 xff0c 才用如下方法这可以避免注入失败 spa
  • windows下停止【kill】nginx命令

    杀死nginx taskkill fi 34 imagename eq nginx EXE 34 f taskkill f t im nginx exe stop bat taskkill f t im nginx exe pause
  • 基本类型对应的缓冲池

    基本类型对应的缓冲池如下 xff1a boolean values true and false all byte values short values between 128 and 127 int values between 128
  • 记录JVM中Eden区、Survivor from区和Survivor to区及Minor GC和Major GC的理解

    仅做学习笔记 JVM中Eden区 Survivor from区和Survivor to区 本文主要根据 深入理解JVM 中内存回收策略 xff0c 主要关注如下五个方面 xff1a 1 xff1a Eden区分配 2 xff1a 大对象直接
  • ubuntu下修改python默认版本的方法

    Ubuntu安装之后会面临多个python版本共存的问题 xff08 python2和python3 xff09 xff0c 但是有时候安装其他库的时候会安装在默认的python版本环境下 xff08 比如 xff0c 通常默认版本是pyt
  • C++:C语言实现HTTP的GET和POST请求

    https www cnblogs com diligenceday p 6255788 html
  • Linux C/C++ UDP Socket 网络通信

    Python微信订餐小程序课程视频 https edu csdn net course detail 36074 Python实战量化交易理财系统 https edu csdn net course detail 35475 昨晚 Vv 让
  • Xcode工程创建多个target

    Xcode工程创建多个target 小菜本人有时候会在一个Xcode工程中新建多个包含main函数的 m文件用于用于学习Objective C xff0c 于是要用到target这个东西 target对应于一个可运行文件和一些编译配置 点击
  • JLINK简介

    一 什么是JLINK JLINK是一个兼容JTAG的仿真器 xff0c 作用是烧入程序和Debug 二 JLINK是如何处理数据的 xff1f 1 PC端应用程序将数据以某种协议格式 xff0c 通过USB接口发送给J Link 2 J L
  • 蓝桥杯单片机-DS1302时钟模块

    一 简介 1 采用SPI三线接口通信 xff08 SCK SDA RST xff09 上升沿数据被写入DS1302 xff0c 下降沿被读出 二 应用 1 在ds1302 c文件中定义三个数组 unsigned char code READ
  • 蓝桥杯单片机-定时器

    一 简介 有三个寄存器与定时器相关 xff08 TMOD xff0c TCON xff0c 数值设置寄存器TH TL xff09 1 定时器工作方式设置寄存器TMOD GATE 门控制位 GATE 61 0时 定时器 计数器启动与停止仅受T
  • 蓝桥杯单片机-NE555模块

    一 简介 1 NE555在开发板中用于输出频率可变 xff0c 占空比不变的方波 2 NE555是纯硬件的设计 xff0c 通过电位器RB3可改变其信号输出频率 不需要编程实现其功能 考点 xff1a 使用定时器的计数模式测量NE555输出
  • C语言学习笔记(基于单片机)

    目录 一 关键字部分 static code const extern bit sbit sft struct xff08 结构体 xff09 1 结构体的初始化 2 结构体的赋值 3 应用 data idata pdata xdata 与
  • 蓝桥杯单片机-赛前总结

    目录 一 省赛中开发平台涉及的模块 xff1a 1 IIC驱动 2 DS1302驱动 3 onewire驱动 4 定时器读取NE555频率 二 一些功能性操作 1 外部中断 2 矩阵按键 3 PWM输出 4 毫秒延时函数 三 需要注意的一些
  • 相互依赖的so库,在编译时如何解耦

    有时候 xff0c 我们写的程序 xff0c 会涉及到相互引用的问题 比如frameworks av media libstagefright下的这个libstagefright xff0c 被frameworks av media lib
  • boost库学习总结

    第一次使用boost库是因为网络编程 xff0c 由于时间比较紧 xff0c 没有时间每个库都学 xff0c 所以前期想找个专门的boost库网络教程 xff08 以前自己就用过socket写过 xff0c 但是为了跨平台 xff0c 而且
  • C51单片机判断点亮的是奇数位还是偶数位

    学单片机的时候想到一个问题 xff1a 如何判断单片机点亮的LED灯是奇数位还是偶数位 xff1f 在网上搜了一圈没找到 xff0c 于是打算自己写一个 单片机型号 xff1a AT89C52 xff0c LED为低电平有效接法 xff0c
  • Linux学习笔记——如何在交叉编译时使用共享库

    0 前言 在较为复杂的项目中会利用到交叉编译得到的共享库 xff08 so文件 xff09 在这种情况下便会产生以下疑问 xff0c 例如 xff1a 1 交叉编译时的共享库是否需要放置于目标板中 xff0c 如果需要放置在哪个目录中 2