交叉编译Qt5.5.1

准备

  • 主机平台:Ubuntu 16.04 LTS(x64)
  • 目标平台:ARM40-A5D3
  • Qt版本:Qt5.5.1
  • tslib github
  • sqlite3
  • ARM-GCC编译工具链:gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi

1、下载Qt5.5.1源代码

在Qt官网上下载Qt5.5.1源代码qt-everywhere-opensource-src-5.5.1.tar.xz

2、 编辑qmake.conf

解压源代码包,并编辑qmake.conf文件。
默认ARM GCC环境已经搭建完毕,参考ARM40-A5 GCC交叉编译环境搭建;
tslib,sqlite3也都已经预编译完毕,参考移植TSLIB到ARM40-A5和移植SQLite3到ARM40-A5。

$ cd ~  
$ xz -d  qt-everywhere-opensource-src-5.5.1.tar.xz         #解压文件      
$ tar xvf qt-everywhere-opensource-src-5.5.1.tar
$ cd qt-everywhere-opensource-src-5.5.1/
$ vim  ./qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf   #编辑qmake.conf

qmake.conf文件内容:

#
# qmake configuration for building with arm-linux-gnueabi-g++
#

MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental
QMAKE_INCREMENTAL_STYLE = sublib

QT_QPA_DEFAULT_PLATFORM = linuxfb                 #指定Qt显示驱动方式
QMAKE_CFLAGS_RELEASE   += -O2 -march=armv7-a      #指定处理器架构
QMAKE_CXXFLAGS_RELEASE += -O2 -march=armv7-a      

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

QMAKE_INCDIR += /opt/tslib/include /opt/sqlite3/include   #指定头文件,需预编译
QMAKE_LIBDIR += /opt/tslib/lib /opt/sqlite3/lib           #指定库文件,需预编译


# modifications to g++.conf
QMAKE_CC                = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc -lts
QMAKE_CXX               = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-g++ -lts
QMAKE_LINK              = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-g++ -lts
QMAKE_LINK_SHLIB        = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-g++ -lts

# modifications to linux.conf
QMAKE_AR                = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-ar cqs
QMAKE_OBJCOPY           = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-objcopy
QMAKE_NM                = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-nm -P
QMAKE_STRIP             = /opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-strip

load(qt_config)
~

3、打补丁

经过试验发现Qt5在ARM40-A5(Atmel-A5D3)上RGB颜色显示异常,R与B调换了。
需要打上补丁linuxfb_swapRGB_2.patch,该补丁仅适用于Qt5.5.1和它之前的版本,不适用Qt5.6以后版本。

$ cd ~  
$ cd qt-everywhere-opensource-src-5.5.1/
$ cd  ./qtbase/
$ cp ~/linuxfb_swapRGB_2.patch ./              #复制补丁文件到当前目录下
$ sudo patch -p1 < linuxfb_swapRGB_2.patch     #成功打上补丁文件
>>>>
Hunk #1 succeeded at 58 (offset -11 lines).
Hunk #2 succeeded at 155 (offset -11 lines).
Hunk #3 succeeded at 171 (offset -11 lines).
Hunk #4 succeeded at 187 (offset -11 lines).
Hunk #5 succeeded at 199 (offset -11 lines).
Hunk #6 succeeded at 208 (offset -11 lines).
Hunk #7 succeeded at 222 (offset -11 lines).
Hunk #8 succeeded at 234 (offset -11 lines).
Hunk #9 succeeded at 291 (offset -18 lines).
Hunk #10 succeeded at 377 (offset -18 lines).
Hunk #11 succeeded at 423 (offset -33 lines).
patching file src/plugins/platforms/linuxfb/qlinuxfbscreen.h
Hunk #1 succeeded at 69 (offset -7 lines).
<<<<

4、configure编译配置

Qt5.5.1 configure编译选项,在这里不再介绍。
配置生成make文件时不报错,就可以make了。

$ cd qt-everywhere-opensource-src-5.5.1/
$ sudo ./configure \
    -prefix /opt/qte5.5.1 \
    -confirm-license \
    -opensource \
      -shared \
    -release  \
    -make libs \
    -xplatform linux-arm-gnueabi-g++ \
    -optimized-qmake \
    -pch \
    -qt-sql-sqlite \
    -qt-libjpeg \
    -qt-libpng \
    -qt-zlib \
    -no-opengl \
    -no-sse2 \
    -no-openssl \
    -no-cups \
    -no-glib \
    -no-dbus \
    -no-xcb \
    -no-xcursor -no-xfixes -no-xrandr -no-xrender \
    -no-separate-debug-info \
    -no-fontconfig \
    -nomake examples -nomake tools -nomake tests -no-iconv \
    -tslib \
    -I/opt/tslib/include \
    -L/opt/tslib/lib   

5、 编译安装Qt

$ sudo mkdir /opt/qte5.5.1   #在主机/opt目录下创建qte5.5.1目录
$ make -j4                  #-j 4 表示4个线程同时编译,减少编译时间
$ sudo make install          #安装Qt
$ cd /opt/qte5.5.1/bin
$ ./qmake -v                 #查看Qt,编译成功
>>>>
QMake version 3.0
Using Qt version 5.5.1 in /opt/qte5.5.1/lib
<<<<

6、 解决错误

1、
Makefile:46934: recipe for target '.obj/qpdf.o' failed
make[3]: *** [.obj/qpdf.o] Error 1

解决:去掉-qreal float选项。

2、
make[3]: Leaving directory '/home/jonny/qt/qt-everywhere-opensource-src-5.5.1/qtbase/src/gui'
Makefile:392: recipe for target 'sub-gui-make_first' failed
make[2]: *** [sub-gui-make_first] Error 2
make[2]: Leaving directory '/home/jonny/qt/qt-everywhere-opensource-src-5.5.1/qtbase/src'
Makefile:45: recipe for target 'sub-src-make_first' failed
make[1]: *** [sub-src-make_first] Error 2
make[1]: Leaving directory '/home/jonny/qt/qt-everywhere-opensource-src-5.5.1/qtbase'
Makefile:72: recipe for target 'module-qtbase-make_first' failed
make: *** [module-qtbase-make_first] Error 2

解决:此错误是找不到 -lqtpcre,这是Qt5.5.1的QTBUG-60496,
删掉qt5源代码,重新解压编译,即可编译通过。

3、大多数的报错都是编译器路径有问题导致的,检查qmake.conf文件。

至此,Qt5.5.1交叉编译完成。

附录


补丁文件linuxfb_swapRGB_2.patch

>>>>
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
index 72d5833..5654e5f 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
@@ -69,6 +69,11 @@

 QT_BEGIN_NAMESPACE

+typedef struct {
+    QImage::Format format;
+    bool swapRgb;
+} FbFormat;
+
 static int openFramebufferDevice(const QString &dev)
 {
     int fd = -1;
@@ -161,12 +166,14 @@ static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize
     return QSize(mmWidth, mmHeight);
 }

-static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
+static FbFormat determineFormat(const fb_var_screeninfo &info, int depth)
 {
     const fb_bitfield rgba[4] = { info.red, info.green,
                                   info.blue, info.transp };

-    QImage::Format format = QImage::Format_Invalid;
+    FbFormat fbFormat;
+    fbFormat.format = QImage::Format_Invalid;
+    fbFormat.swapRgb = false;

     switch (depth) {
     case 32: {
@@ -175,11 +182,12 @@ static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
         const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},
                                          {16, 8, 0}, {24, 8, 0}};
         if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_ARGB32;
+            fbFormat.format = QImage::Format_ARGB32;
         } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB32;
+            fbFormat.format = QImage::Format_RGB32;
         } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB32;
+            fbFormat.format = QImage::Format_RGB32;
+            fbFormat.swapRgb = true;
             // pixeltype = BGRPixel;
         }
         break;
@@ -190,9 +198,10 @@ static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
         const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},
                                        {16, 8, 0}, {0, 0, 0}};
         if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB888;
+            fbFormat.format = QImage::Format_RGB888;
         } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB888;
+            fbFormat.format = QImage::Format_RGB888;
+            fbFormat.swapRgb = true;
             // pixeltype = BGRPixel;
         }
         break;
@@ -201,7 +210,7 @@ static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
         const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},
                                        {0, 6, 0}, {0, 0, 0}};
         if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0)
-            format = QImage::Format_RGB666;
+            fbFormat.format = QImage::Format_RGB666;
         break;
     }
     case 16: {
@@ -210,9 +219,10 @@ static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
         const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},
                                        {11, 5, 0}, {0, 0, 0}};
         if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB16;
+            fbFormat.format = QImage::Format_RGB16;
         } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB16;
+            fbFormat.format = QImage::Format_RGB16;
+            fbFormat.swapRgb = true;
             // pixeltype = BGRPixel;
         }
         break;
@@ -223,9 +233,10 @@ static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
         const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},
                                         {10, 5, 0}, {15, 1, 0}};
         if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB555;
+            fbFormat.format = QImage::Format_RGB555;
         } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {
-            format = QImage::Format_RGB555;
+            fbFormat.format = QImage::Format_RGB555;
+            fbFormat.swapRgb = true;
             // pixeltype = BGRPixel;
         }
         break;
@@ -234,19 +245,19 @@ static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
         const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},
                                        {0, 4, 0}, {0, 0, 0}};
         if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0)
-            format = QImage::Format_RGB444;
+            fbFormat.format = QImage::Format_RGB444;
         break;
     }
     case 8:
         break;
     case 1:
-        format = QImage::Format_Mono; //###: LSB???
+        fbFormat.format = QImage::Format_Mono; //###: LSB???
         break;
     default:
         break;
     }

-    return format;
+    return fbFormat;
 }

 static int openTtyDevice(const QString &device)
@@ -298,7 +309,7 @@ static void blankScreen(int fd, bool on)
 }

 QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
-    : mArgs(args), mFbFd(-1), mBlitter(0)
+    : mArgs(args), mFbFd(-1), mBlitter(0), mSwapRgb(false)
 {
 }

@@ -384,7 +395,9 @@ bool QLinuxFbScreen::initialize()
     mBytesPerLine = finfo.line_length;
     QRect geometry = determineGeometry(vinfo, userGeometry);
     mGeometry = QRect(QPoint(0, 0), geometry.size());
-    mFormat = determineFormat(vinfo, mDepth);
+    FbFormat fbFormat = determineFormat(vinfo, mDepth);
+    mFormat = fbFormat.format;
+    mSwapRgb = fbFormat.swapRgb;
     mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());

     // mmap the framebuffer
@@ -443,8 +456,15 @@ QRegion QLinuxFbScreen::doRedraw()
         mBlitter = new QPainter(&mFbScreenImage);

     QVector rects = touched.rects();
-    for (int i = 0; i < rects.size(); i++)
-        mBlitter->drawImage(rects[i], *mScreenImage, rects[i]);
+    for (int i = 0; i < rects.size(); i++) {
+        if (mSwapRgb) {
+            mBlitter->drawImage(rects[i], mScreenImage->rgbSwapped(), rects[i]);
+        }
+        else {
+            mBlitter->drawImage(rects[i], *mScreenImage, rects[i]);
+        }
+
+    }
     return touched;
 }

diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
index 32cd263..3a149a5 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
@@ -76,6 +76,7 @@ private:
     } mMmap;

     QPainter *mBlitter;
+    bool mSwapRgb;
 };

 QT_END_NAMESPACE

<<<<

参考引用

  • 米尔技术社区
  • veryARM
  • Qt for Embedded Linux Environment Variables
  • QTBUG-60496
  • Cross-compile Qt5 (Mingw) with MySQL driver issue
  • QTBUG-40527
  • linuxfb_swapRGB_2.patch

你可能感兴趣的:(Qt,嵌入式,Ubuntu,Linux,ARM40)