Orangepi3-lts 编译Qt源码

Qt源码编译

  • 环境选择
  • 编译器说明
  • Qt源码版本与下载
  • configure选项
  • make编译
  • 测试编译结果
  • 问题记录

环境选择

这里说的环境包括开发板环境和编译系统环境。我用的是orangepi3-lts的板子。可以运行的桌面系统官方提供了几个ubuntu的。有linux4.9,linux5.10和linux5.16几个版本的镜像。下表是一个版本对应关系。

发行板类型内核版本
Ubuntu 18.04 Bioniclinux4.9
Ubuntu 20.04 Focallinux4.9
Ubuntu 20.04 Focallinux5.10
Ubuntu 20.04 Focallinux5.16
Ubuntu 22.04 Jammylinux5.16

系统中确认ldd版本一致,如果不一致最好在虚拟机中装一个对应版本的系统。我的orangepi3-lts原来装的ubuntu20.04,ldd版本是2.31。用ubuntu22.04中的编译工具编译出来提示GLIBC的版本不一样,用不了。没办法把orangepi3-lts也换成22.04才可以的。

# 查看ldd版本
ldd --version
ldd (Ubuntu GLIBC 2.35-0ubuntu9.9) 2.35
# 第一行就是版本信息
# 开发板和编译主系统的GLIBC版本一定要一样不然没有办法运行的

# 也可以通过lsb_release -a查看ubuntu版本
lsb_release -a

编译器说明

orangepi的官方也是提供了编译工具链,如下:

gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu
gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf
gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi
gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabihf
gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu
gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi
gcc-linaro-aarch64-none-elf-4.8-2013.11_linux
gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux
gcc-linaro-arm-none-eabi-4.8-2014.04_linux

这里主要就用前面两个就可以了,后面有些低版本的有的是用于编译u-boot的。
也可以通过ubuntu自带的软件管理安装。

sudo apt install gcc-10-aarch64-linux-gnu g++-10-aarch64-linux-gnu
# gcc和g++都要安装,有可能装后没有aarch64-linux-gnu-gcc命令,需要用ln链接一下
ln -s /bin/aarch64-linux-gnu-gcc-10 /bin/aarch64-linux-gnu-gcc
# g++也是一样的

由于我的板子是orangepi3-lts用的Allwinner H6的芯片。是一个64位芯片所以用aarch64的编译工具。如果你的开发板芯片是32位的就安装gcc-arm-linux-gnueabi和g+±arm-linux-gnueabi工具链。
为保险起见可以用一个简单的"hello world"测试一下编译工具链和编译系统环境。

// 文件名字main.c
#include <stdio.h>

int main(void){
    printf("Hello world/n");
    return 0;
}

使用方法:

# 编译
aarch64-linux-gnu-gcc -o main main.c
# 用U盘或者nc命令传到开发板

# 开发板上开启端口,接收main文件
nc -l 开启端口号,1024以上 > main
# 主机上传过去
nc -w 1 开发板IP 开发板端口 < main

# 开发板上运行
chmod +x main
./main 
# 正确输出下面内容就没有问题
Hello world

源码版本与下载

Qt官网下载Qt的源码。目录为archive - qt - 选择一个版本 - 再选择一个小版本 - single - 选择.xz结尾的文件下载。
这里的版本我选择的是5.15下面的版本,怕太新的版本编译器会出问题。一般不同版本不同的编译器也会有不同的问题。

make编译

先将源码文件解压,建立几个必要的文件或文件夹

  xz -d  qt-everywhere-opensource-src-5.15.5.tar.xz
  tar xvf  qt-everywhere-opensource-src-5.15.5.tar
# 建立一个保存编译文件的目录
  mkdir qt-build
  cd qt-build
# 创建一个保存编译好后安装Qt的目录
  mkdir qt_install_path
  touch auto_compile.sh

写配置脚本

  vi auto_compile.sh
#将下面的内容写入到auto_compile.sh
#!/bin/bash

../qt-everywhere-src-5.15.5/configure \
  -xplatform linux-aarch64-gnu-g++ \
  -prefix ./qt_install_path \       
  -release -opensource -confirm-license \
  -make libs \
  -pch \
  -qt-libjpeg \
  -qt-libpng \
  -sql-sqlite \
  -qt-zlib \
  -no-opengl \
  -no-sse2 \
  -no-openssl \
  -no-cups \
  -no-glib \
  -no-dbus \
  -no-xcb \
  -no-pch \
  -no-iconv \
  -no-xcb-xlib \
  -no-separate-debug-info \
  -nomake examples -nomake tools \
  -no-pkg-config \
  -c++std c++17 \
# 这里的选项可以通过Qt源码下 ./configure --help查看。也可以直接网上搜索下这些选项的意义

这里还是简单说下编译选项,第一行是配置脚本文件,位于源码文件目录下,这个一定不能错,错了就没有然后了。
第二行的-xplatform是指定编译主机平台的编译器的,这里面必须要有gcc和g++几个编译器。它是一个目录名称,位置位于Qt源码/qtbase/mkspecs/。这个目录下面有很多平台和编译器版本。之前说过我用的开发板是armv8的64位,所以用的编译器就是aarch64-linux-gnu-gcc。如果你用的编译器不是aarch64-linux-gnu-gcc而是aarch64-none-linux-gnu-gcc,或者是其它32位的交叉编译工具就要在这里更改编译器工具。
比如上面的配置脚本指定的目录就是linux-aarch64-gnu-g++,所以进入这个目录,然后更改qmake.conf

  cd linux-aarch64-gnu-g++
  vi qmake.conf
# 将最后几行改为自己的编译器,开发板芯片是32位的可以用linux-arm-gnueabi-g++目录
# 下面就是qmake.conf内容,将aarch64-linux-gnu的几行改为自己的编译器,但这里一定要确认此编译器,编译出来的程序可以在你的开发板上运行,不然就白忙活了

#
# qmake configuration for building with aarch64-linux-gnu-g++
#

MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental
QMAKE_INCREMENTAL_STYLE = sublib

include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)

# modifications to g++.conf
QMAKE_CC                = aarch64-linux-gnu-gcc
QMAKE_CXX               = aarch64-linux-gnu-g++
QMAKE_LINK              = aarch64-linux-gnu-g++
QMAKE_LINK_SHLIB        = aarch64-linux-gnu-g++

# modifications to linux.conf
QMAKE_AR                = aarch64-linux-gnu-ar cqs
QMAKE_OBJCOPY           = aarch64-linux-gnu-objcopy
QMAKE_NM                = aarch64-linux-gnu-nm -P
QMAKE_STRIP             = aarch64-linux-gnu-strip
load(qt_config)

开始编译

# 进入上面建立的qt-build目录
cd ~/qt-build
# 运行配置脚本
./auto_compile.sh
# 开始编译
make -j 12
# 安装
make install 

如果没有出现红色的error就表示运行成功,但往往事与愿违,一般都会出现点错误。我在编译过程中也有遇到几个问题,已经记录在问题记录中。

测试编译结果

进入刚编译好的Qt目录,将Qt安装文件打包,传递到开发板。配置开发板Qt环境。

  cd ~/qt-build
  tar zcvf qt.tar.gz qt_install_path 
  # 开发板上开启nc服务器
  nc -l 2222 > qt.tar.gz
  # 主机上直接将文件传递过去
  nc -w 1 192.168.1.101 2222 < qt.tar.gz
  # 登录开发板,解压文件
  tar zxvf qt.tar.gz 
  # 配置开发板Qt环境
  mv qt_install_path /opt
  cd /opt
  mv qt_install_path qt5.15.5 
  vi ~/.bashrc
  # 将下面内容加入用户配置文件
export QTDIR=/opt/qt-5.15.5
export QT_QPA_FONTDIR=/usr/share/fonts/truetype/freefont
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTDIR/plugins/
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
export QT_QPA_PLATFORM=linuxfb
  # 生效配置
  . ~/.bashrc

然后就是在主机上安装qtcreator,并设置好gcc和g++工具,这里的gcc和g++就是之前的aarch64-linux-gnu-gcc和aarch64-linux-gnu-g++。再配置好Qt的版本,就是指定qmake位置。本文中应当位于~/qt-build/qt_install_path/bin/目录下面。然后就是建立一个新的Qt项目,编译后将可执行程序传递到开发板运行。出现界面就表示成功了。
这里只是简单说下qtcreator配置。qtcreator安装就很简单了,直接在上面的qt官方ftp服务器上下载qtcreator的程序,以.run结尾的就是用于linux的。加上执行权限就可以安装了,唯一特别的是要一个Qt官网的账号。

  1. 打开qtcreator
  2. 选Tools
  3. 再选Options,左边选Kits,右边选Compilers
  4. 点Add,名字写AARCH64-GCC,编译路径写/bin/aarch64-linux-gnu-gcc
  5. 同样的方法加入一个叫AARCH64-G++的g++交叉编译器
  6. 再切换到Qt Versions选项,类似的方法加入一个Qt版本。qmake location写~/qt-build/qt_install_path/bin/qmake
  7. 最后切换到Kits选项,加入一项。名字随便。Device type: Generic Linux Device, Compiler C: AARCH64-GCC, Compiler C++:AARCH64-G++, Qt Version: Qt 5.15.5(qt_install_path)

之后就可以新建立一个项目的,可以在这个项目的.ui文件中加点标签或按钮。左下的绿色三角形图形上方,可以选择Release版本。点左下角最下面的铁锤图标编译。在项目同一个目录中生成编译后的文件。将生成项目同名的可执行文件传递到开发板,加入执行权限就可以看到自己画的界面了。

问题记录

  1. ubuntu系统中有的版本在进行./configure配置时提示找不到max:啥的,在那个文件的中加入limits头文件就可以了。#include <limits>
  2. ubuntu中编译qt5.15.5源码make过程中出现下面提示:
mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/src/corelib/thread/qatomic.cpp:1624:4: error: #error "Q_ATOMIC_INT64_IS_SUPPORTED must be defined on a 64-bit platform"
 #  error "Q_ATOMIC_INT64_IS_SUPPORTED must be defined on a 64-bit platform"
    ^~~~~
In file included from /home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/qglobal.h:1:0,
                 from /home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/src/corelib/global/qt_pch.h:56:
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/thread/qbasicatomic.h: In instantiation of ‘class QBasicAtomicInteger<long int>’:
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/thread/qatomic.h:55:7:   required from ‘class QAtomicInteger<long int>’
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/src/corelib/thread/qatomic.cpp:1631:1:   required from here
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/global/qglobal.h:121:49: error: static assertion failed: template parameter is an integral of a size not supported on this platform
 #  define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
                                                 ^
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/thread/qbasicatomic.h:97:5: note: in expansion of macro ‘Q_STATIC_ASSERT_X’
     Q_STATIC_ASSERT_X(QAtomicOpsSupport<sizeof(T)>::IsSupported, "template parameter is an integral of a size not supported on this platform");
     ^~~~~~~~~~~~~~~~~
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/thread/qbasicatomic.h: In instantiation of ‘class QBasicAtomicInteger<long unsigned int>’:
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/thread/qatomic.h:55:7:   required from ‘class QAtomicInteger<long unsigned int>’
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/src/corelib/thread/qatomic.cpp:1632:1:   required from here
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/global/qglobal.h:121:49: error: static assertion failed: template parameter is an integral of a size not supported on this platform
 #  define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
                                                 ^
/home/mmm/dev/tools/qt-everywhere-src-5.12.6/qtbase/include/QtCore/../../src/corelib/thread/qbasicatomic.h:97:5: note: in expansion of macro ‘Q_STATIC_ASSERT_X’
     Q_STATIC_ASSERT_X(QAtomicOpsSupport<sizeof(T)>::IsSupported, "template parameter is an integral of a size not supported on this platform");

可以看到有2个问题,第一个问题是提示有一个宏没有定义所以打开qt-everywhere-src-5.15.5/qtbase/src/corelib/thread/qatomic.cpp文件。在其中加入一个宏#define Q_ATOMIC_INT64_IS_SUPPORTED
第2个问题是说C++11中的一个静态断言出错了。一旦一个断言出错就不能继续下去。试了几下,只有最粗暴的方式能搞定。将# define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)中的Condition直接改成1,不可能再出错。有没有后续问题我就不知道了。改后的样子# define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(1), Message)。文件位置差点忘记说了qt-everywhere-src-5.15.5/qtbase/include/QtCore/../../src/corelib/global/qglobal.h
3. Windows中的ububtu子系统编译5.15.7的源码提示找不到qBound(double, float, double)。网上找到是因为Armv8 的float是32位,double是64位。所以在编译时加入选项-qreal double选项。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值