移植QT5.6到嵌入式开发板(史上最详细的QT移植教程)

    xiaoxiao2024-12-20  4

    转载地址:http://blog.csdn.net/lizuobin2/article/details/52673494

      目前网上的大多数 QT 移植教程还都停留在 qt4.8 版本,或者还有更老的 Qtopia ,但是目前 Qt 已经发展到最新的 5.7 版本了,我个人也已经使用了很长一段时间的 qt5.6 for windows ,本文就来介绍一下QT在嵌入式环境的搭建。

      移植以到 JZ2440 为例,使用韦老大提供的 ubuntu9.10 虚拟机作为移植环境。当然,其它虚拟机也是可以的,我同样在 ubuntu14.04 移植成功,只不过需要额外装一些库,后面我会简单提及。   此外,我尝试使用 4.3.2 版本的交叉编译工具编译 Qt5.6 ,编译过成功很多错误,编译成功之后使用 qt 编译应用程序时也存在问题,因此我是用的是友善提供的 4.4.3 版本的交叉编译工具。建议新手使用与我相同的编译环境。   因为我们更换了编译工具,因此,我们有接下来的4个工作。     1、重新编译内核     2、制作文件系统     3、移植tslib

        4、移植qt

    教程涉及的资料: 1、交叉编译器   arm-linux-gcc-4.4.3.tar.gz        .链接:http://pan.baidu.com/s/1nvJF8ud 密码:oi57 2、针对于 JZ2440 的内核补丁以及源码   linux-2.6.22.6.tar.bz2           .链接:http://pan.baidu.com/s/1gf0oZn1 密码:jrp6   linux-2.6.22.6_jz2440.patch        链接:http://pan.baidu.com/s/1c1CWgTE 密码:uwuu   4.3寸LCD_mach-smdk2440.c          链接:http://pan.baidu.com/s/1boZsKwf 密码:1xml 3、busybox   busybox-1.22.1.tar.bz2           .链接:http://pan.baidu.com/s/1cee6CI .密码:lv81 4、tslib                      .   tslib-1.4.tar.gz  5、qt5.6 源码                      链接:http://pan.baidu.com/s/1jINj3IQ 密码:6kkc   qt-everywhere-opensource-src-5.6.0.tar.gz 链接:http://pan.baidu.com/s/1kVnV9oN 密码:r7cm

    一、更换交叉编译器

      首先,将下载好的文件全部放在 /work 目录下1、解压交叉编译器  sudo tar zxvf arm-linux-gcc-4.4.3.tar.gz -C /     #展开在根目录  ls /opt/FriendlyARM/toolschain/4.4.3/bin        #检查是否生成了编译目录2、设置环境变量  sudo vi /etc/environment  将现在原有的交叉编译器路径替换为我们新解压的交叉编译器,举例:

    [cpp] view plain copy #PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/work/tools/gcc-3.4.5-glibc-2.3.6/bin"//注释  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.4.3/bin" //增加  

      后期测试时我发现这里是有问题的,由于我的安装目录都指定的是 usr 目录,需要 root 权限,然而在 environment 中设置的环境变量导致使用 root 权限 make install 过程中出现了个别的 command not found ,于是我将环境变量放到了 /etc/profile 中,这个文件是对所有用户生效的。至于environment 百度了一下是系统环境变量按说应该没问题,但是的确出现了问题。索性还是大家还是直接搞到 profile 中吧。

    3、重启虚拟机

    4、检查是否更换成功

      arm-linux-gcc -v

      如图,更换完毕,我们的编译器就变为 4.4.3 版本了。

    二、重新编译内核

      如果你不是jz2440也没关系,使用你曾经移植好的内核,重新编译即可,注意内核需要开启EABI的支持,如果你是jz2440,按照下面的步骤操作即可。

    1、解压   tar jxvf linux-2.6.22.6.tar.bz2 2、打补丁   cd linux-2.6.22.6   patch -p1 < ../linux-2.6.22.6_jz2440.patch   如果你是 4.3 寸的 JZ2440 ,替换 LCD 驱动,3.5寸跳过此步   mv ../4.3寸LCD_mach-smdk2440.c arch/arm/mach-s3c2440/mach-smdk2440.c  3、配置内核支持 EABI   make menuconfig   kernel features->     <*>use the arm eabi to .... //选中这一项 4、修改 makefile ,不改的话 4.4.3 编译器编译时会报错   vi Makefile

      由于友善在制作这款交叉编译工具时指定了最低内核版本(2.6.32.2)的限制,所以我们如果不加修改直接编译启动内核时会出现 kernel too old 的错误信息,无法启动。这里使用一个投机取巧的办法,强制对 2.6.22.6 内核的版本进行修改,更改内核版本号对内核编译是有影响的,真正移植的时候还是建议选择高版本内核。

      Makefile 最开始的地方就是版本号:     VERSION = 2     PATCHLEVEL = 6     SUBLEVEL = 22     EXTRAVERSION = .6   中的 SUBLEVEL = 22 改为 SUBLEVEL = 32   //找到一下几行 ,这里是因为 4.4.3 的编译器不支持 gdwarf2 这个选项     ifdef CONFIG_DEBUG_INFO     CFLAGS += -g     AFLAGS += -gdwarf2     endif   //注释掉 AFLAGS += -gdwarf2 5、编译   make uImage -j4   编译完的uImage 在 /arch/arm/boot 目录下三、制作文件系统

    1、解压   tar jxvf busybox-1.22.1.tar.bz2 2、配置   make menuconfig   Busybox Settings ->    general configuration ->     [*] don't use /usr                   //选中它 否则会破坏虚拟机   build options->     cross comliler prefix = arm-linux-        //选择交叉编译工具   installtion options->     busybox installation prefix = /work/my_rootfs //指定安装路径 3、编译&安装   mkdir -p /work/my_rootfs                 //安装路径   make   make install   cd /work/my_rootfs   ls                 //查看是否安装成功   编译安装完毕之后,我们的文件系统就生成在 /work/my_roofs 目录下了 4、创建 /etc/inittab   mkdir -p /work/my_rootfs/etc   vi /work/my_rootfs/etc/inittab   # /etc/inittab   # 启动脚本/etc/init.d/rcS   ::sysinit:/etc/init.d/rcS   # 启动 shell   ::askfirst:-/bin/sh   # 重启关机前 卸载文件系统   ::ctrlaltdel:/sbin/reboot   ::shutdown:/bin/umount -a -r 5、创建 /etc/init.d/rcS   mkdir -p /work/my_rootfs/etc/init.d   vi /work/my_rootfs/etc/init.d/rcS   # 这是一个脚本文件,用/bin/sh解析   #!/bin/sh   # 挂载文件系统   mount -a   # 使用内存文件系统   mkdir /dev/pts   mount -t devpts devpts /dev/pts   echo /sbin/mdev > /proc/sys/kernel/hotplug   mdev -s   # 设置IP   #/sbin/ifconfig eth0 192.168.1.17 #nfs不需要   # 挂载 /etc/fstab 中的文件系统   mount -a   exec /etc/rc.local 6、创建rc.local   vi /work/my_rootfs/etc/rc.local   #!/bin/sh   . /etc/profile //注意.后边有个空格! 7、创建/etc/fstab   vi /work/my_rootfs/etc/fstab   # device mount-point type options dump fsck order   proc  /proc proc defaults 0 0   sysfs  /sys sysfs defaults 0 0   tmpfs /tmp tmpfs defaults 0 0   tmpfs /dev tmpfs defaults 0 0 8、构建 /dev 目录   mkdir -p /work/my_rootfs/dev   cd /work/my_rootfs/dev   sudo mknod console c 5 1   sudo mknod null   c 1 3 9、创建其它目录   mkdir proc mnt tmp sys root usr 10、拷贝Lib   cd /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib   cp *.so* /work/my_rootfs/lib -d   cd /opt/FriendlyARM/toolschain/4.4.3/lib   cp *.so* /work/my_rootfs/lib -d四、移植 tslib

    1、解压&配置&编译   如果不是使用的韦老大的虚拟机可能还需要安装一下几个包 autoconf automake libtool   #sudo apt-get install autoconf automake libtool   tar zxvf tslib-1.4.tar.gz   sudo mkdir -p /usr/local/tslib   cd tslib   ./autogen.sh   ./configure --host=arm-linux ac_cv_func_malloc_0_nonnull=yes CC=arm-none-linux-gnueabi-gcc CXX=arm-none-linux-gnueabi-g++ -prefix=/usr/local/tslib   make   sudo make install

      如果编译过程中遇到 undefined reference to 'rpl_malloc',前面配置完成之后修改 config.h.in 文件,注释掉文件最后的 #undef malloc ,重新 make 即可。   安装完成之后,tslib 就安装在虚拟机 /usr/local/tslib 目录下 2、更改 tslib 配置文件   cd /usr/local/tslib/etc/   sudo vi ts.conf    去掉# module_raw input 前面的 “#” 和空格 3、将制作好的 tslib 移动到我们制作的文件系统   cd /usr/local   sudo tar zcvf tslib.tar.gz tslib   mkdir -p /work/my_rootfs/usr/local   cp tslib.tar.gz /work/my_rootfs/usr/local   tar zxvf tslib.tar.gz    rm tslib.tar.gz  4、添加 tslib 环境变量   vi /work/my_rootfs/etc/profile

      #!/bin/sh   export T_ROOT=/usr/local/tslib   export LD_LIBRARY_PATH=/usr/local/tslib/lib:$LD_LIBRARY_PATH   export TSLIB_CONSOLEDEVICE=none   export TSLIB_FBDEVICE=/dev/fb0   export TSLIB_TSDEVICE=/dev/input/event0   export TSLIB_PLUGINDIR=$T_ROOT/lib/ts   export TSLIB_CONFFILE=$T_ROOT/etc/ts.conf   export POINTERCAL_FILE=/etc/pointercal   export TSLIB_CALIBFILE=/etc/pointercal   此时,tslib 就已经移植好了,你可以挂载 nfs 文件系统启动,cd /usr/local/tslib/bin

      ./ts_test 来测试   按照教程制作应该没有问题,我在使用高版本内核的时候遇到“selected device is not a touchscreen I understand”错误,百度了一下,是由于内核和编译器的一个宏定义不一致导致的,vi include/Linux/input.h  EV_VERSION 为 0x0100000 ,从新编译内核特别是触摸驱动。

    五、移植 qt5.6

    1、解压   tar zxvf qt-everywhere-opensource-src-5.6.0.tar 2、修改编译配置   cd /work/qt-everywhere-opensource-src-5.6.0/qtbase/mkspecs/linux-arm-gnueabi-g++   vi qmake.conf 针对于 2440 增加:   QT_QPA_DEFAULT_PLATFORM = linuxfb   QMAKE_CFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv4t -mtune=arm920t   QMAKE_CXXFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv4t -mtune=arm920t   march 指的 cpu 架构,针对 2440 来说是 armv4t   mtune 指的 cpu 名字,针对 2440 来说是 arm920t   如果你是 A8 的板子 ,可以参考下边的配置   QT_QPA_DEFAULT_PLATFORM = linuxfb   QMAKE_CFLAGS  += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a8   QMAKE_CXXFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a8   如果你是 A9 的板子 ,可以参考下边的配置   QT_QPA_DEFAULT_PLATFORM = linuxfb    QMAKE_CFLAGS  += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a9   QMAKE_CXXFLAGS += -msoft-float -D__GCC_FLOAT_NOT_NEEDED -march=armv7-a -mtune=cortex-a9 将以下部分   # modifications to g++.conf   QMAKE_CC = arm-linux-gnueabi-gcc   QMAKE_CXX = arm-linux-gnueabi-g++   QMAKE_LINK = arm-linux-gnueabi-g++   QMAKE_LINK_SHLIB = arm-linux-gnueabi-g++   # modifications to linux.conf   QMAKE_AR = arm-linux-gnueabi-ar cqs   QMAKE_OBJCOPY = arm-linux-gnueabi-objcopy   QMAKE_NM = arm-linux-gnueabi-nm -P   QMAKE_STRIP = arm-linux-gnueabi-strip 修改为:-lts 是指在链接时链接 tslib 库   # modifications to g++.conf   QMAKE_CC = arm-none-linux-gnueabi-gcc -lts   QMAKE_CXX = arm-none-linux-gnueabi-g++ -lts   QMAKE_LINK = arm-none-linux-gnueabi-g++ -lts   QMAKE_LINK_SHLIB = arm-none-linux-gnueabi-g++ -lts   # modifications to linux.conf   QMAKE_AR = arm-none-linux-gnueabi-ar cqs    QMAKE_OBJCOPY = arm-none-linux-gnueabi-objcopy    QMAKE_NM = arm-none-linux-gnueabi-nm -P   QMAKE_STRIP = arm-none-linux-gnueabi-strip  3、配置编译   sudo mkdir -p /usr/local/Qt5.6   cd ../../../   ./configure  -prefix /usr/local/Qt5.6 \   -opensource \   -release \   -confirm-license \   -xplatform linux-arm-gnueabi-g++ \   -shared \   -qt-zlib \   -no-gif \   -qt-libjpeg \   -no-nis \   -no-opengl \   -no-cups \   -no-glib \   -no-dbus \   -no-rpath \   -no-sse2 -no-sse3 -no-ssse3 -no-sse4.1 -no-sse4.2 \   -no-avx  \   -no-openssl \   -nomake tools \   -qreal float \   -qt-libpng \   -tslib \   -nomake examples \   -I /usr/local/tslib/include \   -L /usr/local/tslib/lib

      make -j4   sudo make install

      如果使用的不是韦老大的虚拟机编译过程中可能报关于libxcb的错误,查看 qtbase/src/plugins/platforms/xcb 底下的 readme 安装相应的库就可以了。 4、将移植好的 qt 打包到开发板   cd /usr/local   sudo tar zcvf Qt5.6.tar.gz Qt5.6   cp Qt5.6.tar.gz /work/my_rootfs/usr/local/   tar zxvf Qt5.6.tar.gz   rm Qt5.6.tar.gz    rm -r doc include bin mkspecs qml translations 5、设置qt相关的环境变量   此部分可以参考qt官方问文档:http://doc.qt.io/qt-5/embedded-linux.html ,这我这仅仅是设置支持了触摸屏,你可以参考官方设置支持键盘,鼠标等等。

      在文件系统 /etc/profile 里添加   export QTEDIR=/usr/local/Qt5.6   export LD_LIBRARY_PATH=/usr/local/Qt5.6/lib:$LD_LIBRARY_PATH   export QT_QPA_GENERIC_PLUGINS=tslib   export QT_QPA_FONTDIR=$QTEDIR/lib/fonts    export QT_QPA_PLATFORM_PLUGIN_PATH=$QTEDIR/plugins    export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:size=480x272:mmSize=480x272:offset=0x0:tty=/dev/tty1

      export QT_QPA_FB_TSLIB=1

      红色部分请根据自己的开发板进行修改,我手头的开发板是 3.5 寸 320*240 的 LCD,JZ2440 V3 用上面的参数即可。

      此时,qt 已经移植完毕,你可以打包放入你的 nfs 目录启动进行测试了,至于制作 yaffs2 jffs2 等文件系统请参考:http://blog.csdn.net/lizuobin2/article/details/52589215 ,qt库比较大,烧录的时候可能比较困难,可以先将QT去除,打包成文件系统大约之后20M不到,烧录到开发板之后,启动内核,通过nfs tftp等工具,再将打包好的Qt传到板子上展开即可。

    六、测试Qt应用程序

      我个人习惯先用 windows 版本的 qt 写好程序,调试没问题之后直接拿到虚拟机上编译,windows 版本的 qt 安装非常简单,就跟安装个QQ一样毫不费力,这里就不再赘述了。

      将windows下编辑好的源码拷贝到虚拟机上,切换到源码目录

      /usr/local/Qt5.6/bin/qmake

      make

      即可生成可执行文件,拿到开发板测试即可。

      嫌费事的话,将 qmake 添加到环境变量里。

      在测试过程中我发现程序跑起来没问题,但是有以下两条错误信息:

      QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed   QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed

      大概是缺少 libiconv 

      下载 链接:http://pan.baidu.com/s/1c22xb4O 密码:pbld

      mkdir -p /usr/local/libiconv

      ./configure --host=arm-none-linux-gnueabi --prefix=/usr/local/libiconv CC=arm-none-linux-gnueabi-gcc LDFLAGS="-L/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/lib" --enable-static

      make

      sudo make install

      把安装目录/lib 下的 preloadable_libiconv.so 文件系统的 /lib 下, 在 /etc/profile 中添加    export LD_PRELOAD=/lib/preloadable_libiconv.so

    7、使Qt支持中文

      在测试过程中很悲剧的发现移植好的qt不支持中文,强大度娘给了我答案。

      下载字库 链接:http://pan.baidu.com/s/1bp9QFQv 密码:2u81

      将DroidSansFallback.ttf 放到文件系统 /usr/local/Qt5.6/lib/fonts 目录下,虽然Qt自带了很多字库了,但是都没有中文的。

     然后在使用qt creator 开发qt应用程序时,在项目中添加

      QT       += gui

      包含头文件 #include <QFontDatabase>

      代码中设置使用的字体。

    int id = QFontDatabase::addApplicationFont("/usr/local/Qt5.6/lib/fonts/DroidSansFallback.ttf"); QString msyh = QFontDatabase::applicationFontFamilies (id).at(0); QFont font(msyh,10); font.setPointSize(20); this->setFont(font); 8、制作好的文件系统&内核   8.1 简单的qt例子,代码中Ui尺寸写死为 320*240 ,如果不适合你的板子请修改。    链接:http://pan.baidu.com/s/1qXV4C1Y 密码:908q   8.2 jz2440 内核(包含3.5和4.3)    链接:http://pan.baidu.com/s/1qYMrxmc 密码:qsk0   8.3 文件系统    链接:http://pan.baidu.com/s/1skLtj3J 密码:lbo2    改文件系统没有打包成镜像,请使用nfs启动,解压之后在 dev 目录创建 console null 设备节点。    此外,/etc/profile 环境变量中的参数请修改成符合自己开发板的参数,默认为3.5寸。    解压缩之后80多M,制作成 yaffs 恐怕会过 100 M,qt的库文件没有进行剪裁,需要制作镜像的同学可以进行剪裁(查看你的app依赖于哪些库,其余的都可以去掉)。   8.4 编译好的Qt    链接:http://pan.baidu.com/s/1pLCznr9 密码:l6pz 9、最新的uboot、内核、文件系统      文章写了很久了,感谢有众多朋友的信任,参考本文进行了一系列的尝试,在此过程中也发现了文章中的不足,以及网盘中文件系统中的一些不足,恰巧最近有机会,重新做了一份内核,文件系统,以及配套的 uboot,并将它们放在了github上持续更新。如有需要,请下载:      注意:编译器版本:4.4.3       rootfs:           https://github.com/lizuobin/rootfs_jz2440.git          注意:git 下来之后 /dev目录没有 console 和 null 节点,请参考前面创建这两个设备节点           这个文件系统相对完善,开机会自动校准(第一次),然后运行一个简单的Qt桌面程序,暂时没有放其它应用程序。文件系统中已经带有ftpserver工具,大家可以使用filezila进行文件传输,加密方式选择(仅ftp...不安全),端口21,用户root,没有密码。文件系统庞大,还是建议先将qt等一些东西拷贝出来再传进去。       内核:https://github.com/lizuobin/linux-3.4.2-jz2440.git   记得:cp config_ok .config              uboot:https://github.com/lizuobin/uboot-2012.04.01-jz2440.git           

    如果你想让你的开发板支持 ssh 请参考:

      http://blog.csdn.net/lizuobin2/article/details/52664339

    如果你想让你的开发板支持串口(rz)传输文件请参考:

      http://blog.csdn.net/lizuobin2/article/details/52601617

    如果你想让你的开发板想虚拟机一样在命令行显示用户名请参考:

      http://blog.csdn.net/lizuobin2/article/details/52664657

     

    最新回复(0)