交叉编译实践-Qt应用程序交叉编译【用cmake工具编译】

2023-10-27

/****************************************************************************************/

/*           获取更多干货技能,点击 [这里-小编文章列表] 主页左侧扫码关注公众号             */ 

/***************************************************************************************/


        上篇介绍了交叉编译的基本原理,以及交叉编译一个简单的HelloWorld程序,这篇将介绍如何交叉编译Qt程序。

由于Qt程序依赖的底层以及第三方的相关库太多(比如libGL.so库为OpenGL库,libX11.so库为系统图像库等等),因此在交叉编译时会出现各种问题,下面将其主要的问题归为如下三类:
1. 编译器所依赖的库,在编译链接过程中,找到了宿主机的库了,导致文件格式不对,编译链接不成功,比如Qt编译是依赖于libGL.so库,而这个库在宿主机上的/usr/lib/目录下也存在,导致交叉编译器aarch64-linux-gnu-gcc在找库时,找到了宿主机的x86_64的库,所以肯定是链接不成功的。这里要说明一点:交叉编译所依赖的库,必须是与目标机架构一致的库,即libGL.so必须是ARM aarch64架构的库,不能是宿主机上的库,否则在目标机上运行时怎么链接呢?

2. 编译器在编译链接时,没有找到相应的头文件和库,即头文件和对应库没有在交叉编译器的寻库路径中,导致报错找不到库,如下图所示:

解决方式是:一般将所依赖的相关库,放到安装交叉编译器时生成的/usr/aarch64-linux-gnu/目录中对应bin、include、lib的lib目录中,这种方式就保证了交叉编译器能万无一失的找到库和头文件。还有一种方式是如果Qt用的是cmake编译的,则可以通过如下方式设置其所使用的交叉编译器和寻库路径:
# this is required
SET(CMAKE_SYSTEM_NAME Linux)

# specify the cross compiler
SET(CMAKE_C_COMPILER   /opt/arm/usr/bin/aarch64-linux-gnu-gcc)
SET(CMAKE_CXX_COMPILER /opt/arm/usr/bin/aarch64-linux-gnu-g++)

# where is the target environment 
SET(CMAKE_FIND_ROOT_PATH  /opt/arm/lib /home/joven/lib)

# search for programs in the build host directories (not necessary)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# configure Boost and Qt
SET(QT_QMAKE_EXECUTABLE /usr/local/Qt5.6/bin/qmake)
以上牵扯到相关变量的设置,简单介绍解释如下:
    1.CMAKE_SYSTEM_NAME: 即你目标机target所在的操作系统名称,比如ARM或者Linux你就需要写"Linux",如果Windows平台你就写"Windows",如果你的嵌入式平台没有相关OS你即需要写成"Generic",只有当CMAKE_SYSTEM_NAME这个变量被设置了,CMake才认为此时正在交叉编译,它会额外设置一个变量CMAKE_CROSSCOMPILING为TRUE.

    2. CMAKE_C_COMPILER: 顾名思义,即C语言编译器,这里可以将变量设置成完整路径或者文件名,设置成完整路径有一个好处就是CMake会去这个路径下去寻找编译相关的其他工具比如linker,binutils等,如果你写的文件名带有arm-elf等等前缀,CMake会识别到并且去寻找相关的交叉编译器。

    3. CMAKE_CXX_COMPILER: 同上,此时代表的是C++编译器。

    4. CMAKE_FIND_ROOT_PATH: 代表了一系列的相关文件夹路径的根路径的变更,比如你设置了/opt/arm/,所有的Find_xxx.cmake都会优先根据这个路径下的/usr/lib,/lib等进行查找,然后才会去你自己的/usr/lib和/lib进行查找,如果你有一些库是不被包含在/opt/arm里面的,你也可以显示指定多个值给CMAKE_FIND_ROOT_PATH,比如

    5.  CMAKE_FIND_ROOT_PATH_MODE_PROGRAM: 对FIND_PROGRAM()起作用,有三种取值,NEVER,ONLY,BOTH,第一个表示不在你CMAKE_FIND_ROOT_PATH下进行查找,第二个表示只在这个路径下查找,第三个表示先查找这个路径,再查找全局路径,对于这个变量来说,一般都是调用宿主机的程序,所以一般都设置成NEVER

    6. CMAKE_FIND_ROOT_PATH_MODE_LIBRARY: 对FIND_LIBRARY()起作用,表示在链接的时候的库的相关选项,因此这里需要设置成ONLY来保证我们的库是在交叉环境中找的.

    7. CMAKE_FIND_ROOT_PATH_MODE_INCLUDE: 对FIND_PATH()和FIND_FILE()起作用,一般来说也是ONLY,如果你想改变,一般也是在相关的FIND命令中增加option来改变局部设置,有NO_CMAKE_FIND_ROOT_PATH,ONLY_CMAKE_FIND_ROOT_PATH,BOTH_CMAKE_FIND_ROOT_PATH

    8. QT_QMAKE_EXECUTABLE: 指定相应的qmake路径
以上也可以将设置相关变量的代码写到一个toolChain.cmake文件中,这样在执行cmake是带上参数 -DCMAKE_TOOLCHAIN_FILE=./toolChain.cmake 即可(cmake -DCMAKE_TOOLCHAIN_FILE=./toolChain.cmake -DCMAKE_BUILD_TYPE=Release ./)。

3. 报错“/usr/aarch64-linux-gnu/lib/libGL.so.1:对‘XGetVisualInfo’未定义的引用” 等一系列未定义的引用,如下图所示:

从整体报错来看,报错归结为如下图所示:

这些未定义的引用就是上面第一种或第二种错误导致的,找到正确的引用库后,就不会报错了。

搞定以上问题后,基本上编译、链接完成,可执行文件就会生成,交叉编译Qt程序就算大功告成了!!!
编译链接成功截图如下:


但是,好多人可能都没有到编译阶段就已经报错了。。。。。。,可能原因如下:
1. 交叉编译Qt程序的原理没理清
2. Qt的库和Qt的qmake、rcc、moc等工具没有设置好
3. Qt的版本宿主机和目标机不一致
针对以上问题1:Qt应用程序的交叉编译,其原理是通过宿主机上可执行的Qt相关工具程序(比如moc、rcc等),在编译时生成中间文件和资源文件,最终打包成Qt应用程序,但是该应用程序所依赖的Qt动态库又必须是目标机的(动态库必须是ARM aarch64架构的)。
针对以上问题2:给环境变量PATH中必须设置本地Qt可执行文件的路径(也就是Qt的bin目录),这样才能找到moc、rcc等执行相关的操作,也就是说qmake、moc、rcc等在交叉编译是用的工具,必须是x86_64架构的。
针对以上问题3:由于在交叉编译Qt应用程序是,用到了本地的Qt相关工具程序,所以在链接时,最好保持本地的Qt版本和目标机的Qt版本一直(也就是编译时的Qt版本和运行时的Qt版本保持一致)。
总结以上问题:如果在cmake中设置了找库路径,则需要将目标机的Qt的lib库拷贝到设置的路径中,如果在cmake中没有设置找库路径,则有个粗暴的方法,就是将本地的Qt中lib目录换成目标机的lib,确保本地的Qt的bin目录中可执行文件都是x86_64架构,lib目录中的库文件都是ARM aarch64架构的。

这样就基本搞定了Qt应用程序的交叉编译了^_^.



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

交叉编译实践-Qt应用程序交叉编译【用cmake工具编译】 的相关文章

随机推荐

  • zxing设置条码两边空白(EncodeHintType.MARGIN)无效的分析

    最新项目需要使用到zxing生成条码 条码格式为CODE128 CODE128的规则可参考 点击打开链接 当调用 MultiFormatWriter encode str BarcodeFormat CODE 128 mwidth mHei
  • 对CocosCreatorr的Draw call的理解

    Draw call比较直观的描述应该是 在CPU不改变渲染数据的情况下 openGL的一次渲染 opengGL的一次渲染 CPU调用图形绘制接口来使GPU执行渲染操作 渲染流程是CPU和GPU并行工作的过程 CPU和GPU之间通过一系列的缓
  • 小米便签开源项目本地环境搭建

    基于Android Studio 和Gradle 的小米便签配置和安装 一 Android Studio的中文社区 官网 下载最新的Android Studio 点击开始传送http www android studio org 可参考下文
  • 让异步的多个ajax顺序执行的方法

    就是说等第一个ajax传回来后再执行第二个ajax跟其他的js代码 ajax type POST url http xxx xxx aspx data success function msg 试了几次 除了在 那里 执行接下来的代码外 要
  • CSDN 编程竞赛第15期题解

    CSDN 编程竞赛第15期题解 1 求并集 由小到大输出两个单向有序链表的并集 如链表 A 1 gt 2 gt 5 gt 7 链表 B 3 gt 5 gt 7 gt 8 输出 1 gt 2 gt 3 gt 5 gt 7 gt 8 inclu
  • day01Git

    1 Git介绍 1 1版本控制 理解 无论是代码编写 还是文档编写 我们都会遇到对文档内容反复修改的情况 1 2开发中存在的问题 理解 程序员小明负责的模块就要完成了 就在即将提交发布之前的一瞬间 电脑突然蓝屏 硬盘光荣下岗 几个月来的努力
  • 【前端】Vue项目:旅游App-(16)home+hooks:窗口滚动到底部动态加载新数据、抽取到hook

    文章目录 目标 过程与代码 监听窗口的滚动 窗口上事件监听的移除 封装到一个hook 回调函数法 不推荐 返回值法 推荐 效果 总代码 修改或添加的文件 hooks的useScroll home content 参考 本项目博客总结 前端
  • C++QT入门

    C QT 文章目录 C QT 1 QT概述 1 1 什么是QT 1 2 QT的发展史 1 3 支持的平台 1 4 QT版本 1 5 Qt 的下载与安装 1 6 QT的优点 1 7 成功案例 2 创建QT项目 2 1 使用向导创建 2 2 手
  • vue2尚品汇学到得新知识

    vue滚动条 写到router路由中 回到最顶部 scrollBehavior to from savedPosition return y 0 2 引入一个模块后 先在路由router中 import然后再在注册路由写信息 path后看看
  • 【dev on wsl2】wsl2 with vscode简单配置

    wsl2 with vscode简单配置 正文开始 Assassin 目录 wsl2 with vscode简单配置 1 安装wsl2 1 1 安装方式选择 1 2 命令行安装 2 搭配vscode 2 1 新建用户 远程连接vscode
  • C++,类中的构造函数、拷贝构造函数、拷贝赋值函数、析构函数

    类的简介 类是一种将抽象转换为用户定义类型的C 工具 它将数据表示和操纵数据的方法组合成一个整洁的包 一般来说 类规范由两个部分组成 类声明 以数据成员 成员属性 的方式描述数据部分 以成员函数 被称为方法 的方式描述公有接口 类方法定义
  • element-ui嵌套弹框遮罩层解决

    1 element ui嵌套弹框遮罩层解决
  • QNX 如何制作目标系统,制作系统镜像,烧写系统文件

    如果你认为本系列文章对你有所帮助 请大家有钱的捧个钱场 点击此处赞助 赞助额1元起步 多少随意 author 锋影 e mail 174176320 qq com 制作目标系统的方法如下 以CF卡为例 1 格式化CF卡 2 用dinit传系
  • JenKins + Svn + Maven 自动化构建部署

    也许很多小伙伴会疑问 什么是Jenkins Jenkins是一个功能强大的应用程序 允许持续集成和持续交付项目 无论用的是什么平台 这是一个免费的源代码 可以处理任何类型的构建或持续集成 集成Jenkins可以用于一些测试和部署技术 Jen
  • Python __name__属性和 dir() 函数

    name 属性 一个模块被另一个程序第一次引入时 其主程序将运行 如果我们想在模块被引入时 模块中的某一程序块不执行 我们可以用 name 属性来使该程序块仅在该模块自身运行时执行 if name main print 程序自身在运行 el
  • SpringBoot笔记

    目录 开发准备 导出 常用注解 导出excel到指定位置 导出excel到指定web 导入 将指定位置Excel导入并显示至web 使用ExcelWriter基于模板导出 开发准备 1 导入依赖
  • (记录贴)Docker日志位置及docker日志日期时间精确查询

    docker logs since 2020 07 30T10 14 00 until 2020 07 30T10 15 00 tomcat80 这条代码可以通过2个时间来查询指定范围的时间日志 since起始时间 你要从什么时候开始查询
  • 华为机试---路灯

    题目描述 一条长l的笔直的街道上有n个路灯 若这条街的起点为0 终点为l 第i个路灯坐标为a i 每盏灯可以覆盖到的最远距离为d 为了照明需求 所有灯的灯光必须覆盖整条街 但是为了省电 要是这个d最小 请找到这个最小的d 输入描述
  • tensorflow运行出错 ERROR:root:Internal Python error in the inspect module

    导入模块 运行出现以下错误 使用pip install tensorflow 默认安装的是tensorflow 2 0 往下拉可以看到各种 ImportError DLL load failed 找不到指定的模块 查看官网可以看到相关说明
  • 交叉编译实践-Qt应用程序交叉编译【用cmake工具编译】

    获取更多干货技能 点击 这里 小编文章列表 主页左侧扫码关注公众号 上篇介绍了交叉编译的基本原理 以及交叉编译一个简单的HelloWorld程序 这篇将介绍如何交叉编译Qt程序 由于Qt程序依赖的底层以及第三方的相关库太多