Qt5.9.1交叉编译源码并实现界面旋转功能

  • 环境介绍

主机操作系统:Ubuntu18.04 64位

目标平台:致远电子的M6708U     芯片:imx6

交叉工具:arm-poky-linux-gnueabi    版本gcc4.9.1

  • 解压并安装

把从官网下载的qt-everywhere-opensource-src-5.9.1.tar.xz,

放到Ubuntu18.04下的/opt

运行以下命令解压Qt5.9.1源码

/opt#  tar -xvf qt-everywhere-opensource-src-5.9.1.tar.xz

把致远电子提供的文件系统rootfs.tar.gz,放到Ubuntu18.04下的/opt,运行以下命令解压,并删除Qt相关文件库

/opt#  tar -xvf rootfs.tar.gz

/opt#  rm rootfs/usr/lib/libQt*

把致远电子提供的交叉编译工具链放在/opt下,执行以下命令安装

/opt#./poky-glibc-x86_64-meta-toolchain-qt5-cortexa9hf-vfp-neon-toolchain-1.7.sh

把文件系统rootfs下的相关库链接到Ubuntu的/lib和/usr/lib目录中:

/opt#  ln -s /opt/rootfs/lib/libpthread.so.0   /lib/libpthread.so.0

/opt#  ln -s /opt/rootfs/lib/libc.so.6   /lib/libc.so.6

/opt#  ln –s/opt/rootfs/usr/lib/libpthread_nonshared.a   /usr/lib/libpthread_nonshared.a

/opt#  ln-s /opt/rootfs/usr/lib/libc_nonshared.a   /usr/lib/libc_nonshared.a

/opt#  ln-s /opt/rootfs /lib/ld-2.20.so/lib/ld-linux-armhf.so.3

把致远电子提供的触摸驱动tslib-1.21-new.tar.gz放在/opt下,执行以下命令安装:

/opt#tar-xvf tslib-1.21-new.tar.gz

  • 修改源码实现界面可旋转显示的功能

把/qtbase/src/plugins/platforms/linuxfb目录下的qlinuxfbscreen.cpp和qlinuxfbscreen.h两个文件进行修改,修改的源码如下所示:

qlinuxfbscreen.h:

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

**

** Copyright (C) 2016 The Qt Company Ltd.

** Contact: https://www.qt.io/licensing/

**

** This file is part of the plugins of the Qt Toolkit.

**

** $QT_BEGIN_LICENSE:LGPL$

** Commercial License Usage

** Licensees holding valid commercial Qt licenses may use this file in

** accordance with the commercial license agreement provided with the

** Software or, alternatively, in accordance with the terms contained in

** a written agreement between you and The Qt Company. For licensing terms

** and conditions see https://www.qt.io/terms-conditions. For further

** information use the contact form at https://www.qt.io/contact-us.

**

** GNU Lesser General Public License Usage

** Alternatively, this file may be used under the terms of the GNU Lesser

** General Public License version 3 as published by the Free Software

** Foundation and appearing in the file LICENSE.LGPL3 included in the

** packaging of this file. Please review the following information to

** ensure the GNU Lesser General Public License version 3 requirements

** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.

**

** GNU General Public License Usage

** Alternatively, this file may be used under the terms of the GNU

** General Public License version 2.0 or (at your option) the GNU General

** Public license version 3 or any later version approved by the KDE Free

** Qt Foundation. The licenses are as published by the Free Software

** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3

** included in the packaging of this file. Please review the following

** information to ensure the GNU General Public License requirements will

** be met: https://www.gnu.org/licenses/gpl-2.0.html and

** https://www.gnu.org/licenses/gpl-3.0.html.

**

** $QT_END_LICENSE$

**

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



#ifndef QLINUXFBSCREEN_H

#define QLINUXFBSCREEN_H



#include 



QT_BEGIN_NAMESPACE



class QPainter;

class QFbCursor;



class QLinuxFbScreen : public QFbScreen

{

    Q_OBJECT

public:

QLinuxFbScreen(const QStringList &args);

    ~QLinuxFbScreen();



bool initialize() override;



    QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;



    QRegion doRedraw() override;



private:

    QStringList mArgs;

int mFbFd;

int mTtyFd;



int mRotation; //add by qingjie 20200424



    QImage mFbScreenImage;

int mBytesPerLine;

int mOldTtyMode;



struct {

uchar *data;

int offset, size;

    } mMmap;



    QPainter *mBlitter;

};



QT_END_NAMESPACE



#endif // QLINUXFBSCREEN_H

 

qlinuxfbscreen.cpp:

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

**

** Copyright (C) 2016 The Qt Company Ltd.

** Contact: https://www.qt.io/licensing/

**

** This file is part of the plugins of the Qt Toolkit.

**

** $QT_BEGIN_LICENSE:LGPL$

** Commercial License Usage

** Licensees holding valid commercial Qt licenses may use this file in

** accordance with the commercial license agreement provided with the

** Software or, alternatively, in accordance with the terms contained in

** a written agreement between you and The Qt Company. For licensing terms

** and conditions see https://www.qt.io/terms-conditions. For further

** information use the contact form at https://www.qt.io/contact-us.

**

** GNU Lesser General Public License Usage

** Alternatively, this file may be used under the terms of the GNU Lesser

** General Public License version 3 as published by the Free Software

** Foundation and appearing in the file LICENSE.LGPL3 included in the

** packaging of this file. Please review the following information to

** ensure the GNU Lesser General Public License version 3 requirements

** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.

**

** GNU General Public License Usage

** Alternatively, this file may be used under the terms of the GNU

** General Public License version 2.0 or (at your option) the GNU General

** Public license version 3 or any later version approved by the KDE Free

** Qt Foundation. The licenses are as published by the Free Software

** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3

** included in the packaging of this file. Please review the following

** information to ensure the GNU General Public License requirements will

** be met: https://www.gnu.org/licenses/gpl-2.0.html and

** https://www.gnu.org/licenses/gpl-3.0.html.

**

** $QT_END_LICENSE$

**

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



#include "qlinuxfbscreen.h"

#include 

#include 

#include 

#include 

#include 



#include  // overrides QT_OPEN

#include 

#include 



#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 



#include 



QT_BEGIN_NAMESPACE



static int openFramebufferDevice(const QString &dev)

{

int fd = -1;



if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)

fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);



if (fd == -1) {

if (access(dev.toLatin1().constData(), R_OK) == 0)

fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);

    }



return fd;

}



static int determineDepth(const fb_var_screeninfo &vinfo)

{

int depth = vinfo.bits_per_pixel;

if (depth== 24) {

depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;

if (depth <= 0)

depth = 24; // reset if color component lengths are not reported

    } else if (depth == 16) {

depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;

if (depth <= 0)

depth = 16;

    }

return depth;

}



static QRect determineGeometry(const fb_var_screeninfo &vinfo, const QRect &userGeometry)

{

int xoff = vinfo.xoffset;

int yoff = vinfo.yoffset;

int w, h;

if (userGeometry.isValid()) {

        w = userGeometry.width();

        h = userGeometry.height();

if ((uint)w > vinfo.xres)

            w = vinfo.xres;

if ((uint)h > vinfo.yres)

            h = vinfo.yres;



int xxoff = userGeometry.x(), yyoff = userGeometry.y();

if (xxoff != 0 || yyoff != 0) {

if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))

xxoff = vinfo.xres - w;

if (yyoff < 0 || yyoff + h > (int)(vinfo.yres))

yyoff = vinfo.yres - h;

xoff += xxoff;

yoff += yyoff;

        } else {

xoff += (vinfo.xres - w)/2;

yoff += (vinfo.yres - h)/2;

        }

    } else {

        w = vinfo.xres;

        h = vinfo.yres;

    }



if (w == 0 || h == 0) {

qWarning("Unable to find screen geometry, using 320x240");

        w = 320;

        h = 240;

    }



return QRect(xoff, yoff, w, h);

}



static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize &mmSize, const QSize &res)

{

int mmWidth = mmSize.width(), mmHeight = mmSize.height();



if (mmWidth <= 0 && mmHeight <= 0) {

if (vinfo.width != 0 && vinfo.height != 0

&&vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {

mmWidth = vinfo.width;

mmHeight = vinfo.height;

        } else {

const int dpi = 100;

mmWidth = qRound(res.width() * 25.4 / dpi);

mmHeight = qRound(res.height() * 25.4 / dpi);

        }

    } else if (mmWidth > 0 && mmHeight <= 0) {

mmHeight = res.height() * mmWidth/res.width();

    } else if (mmHeight > 0 && mmWidth <= 0) {

mmWidth = res.width() * mmHeight/res.height();

    }



return QSize(mmWidth, mmHeight);

}



static QImage::Format 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;



switch (depth) {

case 32: {

const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},

                                         {0, 8, 0}, {24, 8, 0}};

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;

        } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {

format = QImage::Format_RGB32;

        } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {

format = QImage::Format_RGB32;

            // pixeltype = BGRPixel;

        }

break;

    }

case 24: {

const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},

                                       {0, 8, 0}, {0, 0, 0}};

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;

        } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {

format = QImage::Format_RGB888;

            // pixeltype = BGRPixel;

        }

break;

    }

case 18: {

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;

break;

    }

case 16: {

const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},

                                       {0, 5, 0}, {0, 0, 0}};

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;

        } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {

format = QImage::Format_RGB16;

            // pixeltype = BGRPixel;

        }

break;

    }

case 15: {

const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},

                                        {0, 5, 0}, {15, 1, 0}};

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;

        } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {

format = QImage::Format_RGB555;

            // pixeltype = BGRPixel;

        }

break;

    }

case 12: {

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;

break;

    }

case 8:

break;

case 1:

format = QImage::Format_Mono; //###: LSB???

break;

default:

break;

    }



return format;

}



static int openTtyDevice(const QString &device)

{

const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };



int fd = -1;

if (device.isEmpty()) {

for (const char * const *dev = devs; *dev; ++dev) {

fd = QT_OPEN(*dev, O_RDWR);

if (fd != -1)

break;

        }

    } else {

fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);

    }



return fd;

}



static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode)

{

    // Do not warn if the switch fails: the ioctl fails when launching from a

    // remote console and there is nothing we can do about it.  The matching

    // call in resetTty should at least fail then, too, so we do no harm.

if (ioctl(ttyfd, KDGETMODE, oldMode) == 0) {

if (doSwitch && *oldMode != KD_GRAPHICS)

ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);

    }

}



static void resetTty(int ttyfd, int oldMode)

{

ioctl(ttyfd, KDSETMODE, oldMode);



    QT_CLOSE(ttyfd);

}



static void blankScreen(int fd, bool on)

{

ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);

}



QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)

    : mArgs(args), mFbFd(-1),mTtyFd(-1), mRotation(0),mBlitter(0)//add qingjie 20200424

{

    mMmap.data = 0;

}



QLinuxFbScreen::~QLinuxFbScreen()

{

if (mFbFd != -1) {

if (mMmap.data)

munmap(mMmap.data - mMmap.offset, mMmap.size);

close(mFbFd);

    }



if (mTtyFd != -1)

resetTty(mTtyFd, mOldTtyMode);



delete mBlitter;

}



bool QLinuxFbScreen::initialize()

{

    QRegularExpression ttyRx(QLatin1String("tty=(.*)"));

    QRegularExpression fbRx(QLatin1String("fb=(.*)"));

    QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));

    QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));

    QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));



    QRegularExpression rotationRx(QLatin1String("roration=(0|90|180|270)"));//add qingjie 20200424



    QString fbDevice, ttyDevice;

    QSize userMmSize;

    QRect userGeometry;

bool doSwitchToGraphicsMode = true;



    // Parse arguments

for (const QString &arg : qAsConst(mArgs)) {

        QRegularExpressionMatch match;

if (arg == QLatin1String("nographicsmodeswitch"))

doSwitchToGraphicsMode = false;

else if (arg.contains(mmSizeRx, &match))

userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());

else if (arg.contains(sizeRx, &match))

userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));

else if (arg.contains(offsetRx, &match))

userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));

else if (arg.contains(ttyRx, &match))

ttyDevice = match.captured(1);

else if (arg.contains(fbRx, &match))

fbDevice = match.captured(1);

         else if (arg.contains(rotationRx,&match))//add qingjie 20200424

         mRotation = match.captured(1).toInt();//add qingjie 20200424

    }



if (fbDevice.isEmpty()) {

fbDevice = QLatin1String("/dev/fb0");

if (!QFile::exists(fbDevice))

fbDevice = QLatin1String("/dev/graphics/fb0");

if (!QFile::exists(fbDevice)) {

qWarning("Unable to figure out framebuffer device. Specify it manually.");

return false;

        }

    }



    // Open the device

mFbFd = openFramebufferDevice(fbDevice);

if (mFbFd == -1) {

qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));

return false;

    }



    // Read the fixed and variable screen information

fb_fix_screeninfo finfo;

fb_var_screeninfo vinfo;

memset(&vinfo, 0, sizeof(vinfo));

memset(&finfo, 0, sizeof(finfo));



if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {

qErrnoWarning(errno, "Error reading fixed information");

return false;

    }



if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {

qErrnoWarning(errno, "Error reading variable information");

return false;

    }



mDepth = determineDepth(vinfo);

mBytesPerLine = finfo.line_length;

    QRect geometry = determineGeometry(vinfo, userGeometry);



         //add qingjie 20200424 start

    QRect originalGeometry = geometry;

if(90 == mRotation ||270==mRotation)

    {

         int tmp = geometry.width();

         geometry.setWidth(geometry.height());

         geometry.setHeight(tmp);

    }

         //add qingjie 20200424 end







mGeometry = QRect(QPoint(0, 0), geometry.size());

mFormat = determineFormat(vinfo, mDepth);



    //mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size()); //modify qingjie 20200424

mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());   //modify qingjie 20200424



    // mmap the framebuffer

    mMmap.size = finfo.smem_len;

uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);

if ((long)data == -1) {

qErrnoWarning(errno, "Failed to mmap framebuffer");

return false;

    }



    //mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8; //modify qingjie 20200424

    mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8; //modify qingjie 20200424



    mMmap.data = data + mMmap.offset;



    QFbScreen::initializeCompositor();

    //mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat); //modify qingjie 20200424

mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);//modify qingjie 20200424



mCursor = new QFbCursor(this);



mTtyFd = openTtyDevice(ttyDevice);

if (mTtyFd == -1)

qErrnoWarning(errno, "Failed to open tty");



switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);

blankScreen(mFbFd, false);



return true;

}



QRegion QLinuxFbScreen::doRedraw()

{

    QRegion touched = QFbScreen::doRedraw();



if (touched.isEmpty())

return touched;



if (!mBlitter)

mBlitter = new QPainter(&mFbScreenImage);



mBlitter->setCompositionMode(QPainter::CompositionMode_Source);



    //for (const QRect &rect : touched)                      //modify qingjie 20200424

    //    mBlitter->drawImage(rect, mScreenImage, rect);        //modify qingjie 20200424





const QVector rects = touched.rects();

    //add qingjie 20200424 start

for (int i = 0; i < rects.size(); ++i)  

    {

         if( 90 == mRotation || 270 == mRotation )

        {

         mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);



         qDebug()<<"mRotation:"<<90;

        }

         else if(180 == mRotation)

         {

         mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);

         qDebug()<<"mRotation:"<<180;

         }

if( mRotation != 0 )

        {

mBlitter->rotate(mRotation);

mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);

        }

mBlitter->drawImage(rects[i], mScreenImage, rects[i]);

         mBlitter->resetTransform();



    }

   //add qingjie 20200424 end









return touched;

}



// grabWindow() grabs "from the screen" not from the backingstores.

// In linuxfb's case it will also include the mouse cursor.

QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const

{

if (!wid) {

if (width < 0)

width = mFbScreenImage.width() - x;

if (height < 0)

height = mFbScreenImage.height() - y;

return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);

    }



    QFbWindow *window = windowForId(wid);

if (window) {

const QRect geom = window->geometry();

if (width < 0)

width = geom.width() - x;

if (height < 0)

height = geom.height() - y;

        QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));

rect&= window->geometry();

return QPixmap::fromImage(mFbScreenImage).copy(rect);

    }



return QPixmap();

}



QT_END_NAMESPACE
  • 配置编译文件

把qt5.9.1中的qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf文件修改为以下内容:

#
# qmake configuration for building with arm-linux-gnueabi-g++
#
MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE = sublib

#QT_QPA_DEFAULT_PLATFORM = eglfs #linuxfb
IMX6_CFLAGS = -march=armv7-a -mfpu=neon -DLINUX=1 -DEGL_API_FB=1
IMX6_CFLAGS_RELEASE = -O2 $$IMX6_CFLAGS
QMAKE_CFLAGS_RELEASE += $$IMX6_CFLAGS_RELEASE
QMAKE_CXXFLAGS_RELEASE += $$IMX6_CFLAGS_RELEASE
QMAKE_CFLAGS_DEBUG += $$IMX6_CFLAGS
QMAKE_CXXFLAGS_DEBUG += $$IMX6_CFLAGS
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)

# modifications to g++.conf
QMAKE_CC = /opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc -mthumb-interwork -mfloat-abi=hard -mtune=cortex-a9
QMAKE_CXX = /opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++
-mthumb-interwork -mfloat-abi=hard -mtune=cortex-a9
QMAKE_LINK = /opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++ -mthumb-interwork -mfloat-abi=hard -mtune=cortex-a9
QMAKE_LINK_SHLIB = /opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++ -mthumb-interwork -mfloat-abi=hard -mtune=cortex-a9

# modifications to linux.conf
QMAKE_AR = /opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-ar cqs
QMAKE_OBJCOPY = /opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-objcopy
QMAKE_NM = /opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-nm -P
QMAKE_INCDIR = /opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include
QMAKE_INCDIR += /opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include/dbus-1.0
QMAKE_INCDIR += /home/vmuser/rootfs/usr/lib/dbus-1.0/include
#QMAKE_LIBDIR = /home/vmuser/rootfs/usr/lib/*.so
QMAKE_LIBDIR = /home/vmuser/rootfs/lib
QMAKE_LIBDIR += /home/vmuser/rootfs/usr/lib
#QMAKE_LIBDIR += /home/vmuser/rootfs/usr/lib
QMAKE_INCDIR_OPENGL_ES2 = /opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include
QMAKE_LIBDIR_OPENGL_ES2 = /home/vmuser/rootfs/usr/lib
QMAKE_INCDIR_EGL = /opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include
QMAKE_LIBDIR_EGL = /home/vmuser/rootfs/usr/lib
QMAKE_LIBS_OPENGL_ES1 += -lGLESv1_CM -lEGL -lGAL
QMAKE_LIBS_OPENGL_ES1CL += -lGLES_CL -lEGL -lGAL
QMAKE_LIBS_EGL += -lEGL -lGAL
QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL -lGAL
QMAKE_LIBS_OPENVG += -lOpenVG -lEGL -lGAL
QMAKE_LIBS += -ljpeg -ldbus-1 -lrt -lpthread #编译选项
#DISTRO_OPTS += hard-float #浮点运算使用软件不使用硬件
# Preferred eglfs backend
EGLFS_DEVICE_INTEGRATION = eglfs_viv
# /opt/rootfs/为解压固件 rootfs.tar.gz 所得目录
#/opt/poky/1.7/sysroots/ 为安装交叉工具链所得目录
load(qt_config)

在 qt 源码顶层目录中新建配置脚本build.sh,将相应内容填入,其中prefix为编译完成后的安装路径,xplatform后面带的参数为mkspec所在位置:

#########################################################################
# File Name: build.sh
# Author: hegaozhi
# mail: [email protected]
# 以下为脚本内容
#########################################################################
#!/bin/bash
export PATH=$PATH:/opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi:/opt/poky/1.7/sysroots/x86_64-pokysdk-linux/usr/bin
export C_INCLUDE_PATH=XXXX:$C_INCLUDE_PATH
#export CPLUS_INCLUDE_PATH=/opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include:$CPLUS_INCLUDE_PATH
#export LD_LIBRARY_PATH=/opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include:$LD_LIBRARY_PATH
#export LIBRARY_PATH=/opt/rootfs/lib:/opt/rootfs/usr/lib:$LIBRARY_PATH
#export LD_LIBRARY_PATH=/opt/rootfs/lib:/opt/rootfs/usr/lib:$LD_LIBRARY_PATH
./configure -release \
-xplatform linux-arm-gnueabi-g++ \
-opengl es2 \
-no-dbus \
-no-use-gold-linker \
-prefix /opt/qt5.9.1-arm-release \
-opensource -confirm-license -make libs \
-nomake tools -nomake examples -nomake tests \
-skip qt3d -skip qtandroidextras -skip qtcanvas3d \
-skip qtconnectivity -skip qtdatavis3d -skip qtdoc \
-skip qtgamepad -skip qtimageformats -skip qtlocation \
-skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtsensors \
-skip qtserialbus -skip qtspeech -skip qtsvg -skip qttools -skip qtwebchannel \
-skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtwinextras \
-skip qtx11extras -no-feature-iconv -no-feature-gestures -no-qml-debug \
-I/opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/include \
-I/opt/tslib-1.21-new /include \
-L/opt/tslib-1.21-new /lib \
-L/opt/rootfs/usr/lib \
-L/opt/rootfs/lib

完成以上设置后在 qt 源码顶层目录中执行以下命令

/opt/qt5.9.1-src#  ./build.sh

/opt/qt5.9.1-src#  make-j4

/opt/qt5.9.1-src#  make install -j4

执行以上三个命令后,将完成源码的编译和安装的工作,安装在/opt/qt5.9.1-arm-release目录下

在Ubuntu中的QtCreator配置交叉编译器

第一步:打开Tools->Options->Build&Run下的Compilers界面,如下图所示:

点击界面中Add->Linux ICC->C++

第二步:打开Tools->Options->Build&Run下的Qt Versions界面,如下图所示:

点击界面中Add选择qmake所在的路径;

Qt5.9.1交叉编译源码并实现界面旋转功能_第1张图片

第三步:打开Tools->Options->Build&Run下的Kits界面,如下图所示:

点击界面中Add,填写相关信息如下图所示

完成以上三步的QtCreator配置后,就可以对Qt应用程序交叉编译。

在嵌入式linux中部署qt5.9.1并配置运行脚本

1、由于编译安装后的目录下没有带字库,在qt5.9.1-arm-release/lib/下新建fonts目录用于存放字库

把Ubuntu下的/opt/qt5.9.1-arm-release目录全部拷贝到开发板的/opt目录下

把Ubuntu下的/opt/tslib-1.21-new目录全部拷贝到开发板的/usr/local目录下

2、开发板中的 QT 运行环境变量,在/etc/profile 文件中添加如下内容

#Qt

export QT_ROOT=/opt/qt5.9.1-arm-release

export PATH=$QTDIR/bin:$PATH

export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:$QT_ROOT/lib

export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_ROOT/plugins

export QT_QPA_FONTDIR=$QT_ROOT/lib/fonts

export QML2_IMPORT_PATH=$QT_ROOT/qml

export QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER=2

export QT_QPA_GENERIC_PLUGINS="tslib:/dev/input/touchscreen0"

export QT_QPA_EGLFS_PHYSICAL_WIDTH=245

export QT_QPA_EGLFS_PHYSICAL_HEIGHT=184

export QT_QPA_FB_TSLIB=1

export QT_QPA_EGLFS_TSLIB=1

export QT_QPA_PLATFORM=eglfs     #重要实现界面旋转显示

export QT_QPA_EGLFS_ROTATION=90  #重要 实现界面旋转90度显示





#tslib

export TSLIB_ROOT=/usr/local/tslib-1.21-new

export PATH=$TSLIB_ROOT/bin:$PATH

export TSLIB_TSDEVICE=/dev/input/touchscreen0

#export TSLIB_TSDEVICE=/dev/input/event1

export TSLIB_CALIBFILE=/etc/pointercal

export POINTERCAL_FILE=/etc/pointercal

export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSLIB_ROOT/lib

export TSLIB_PLUGINDIR=/usr/local/tslib-1.21-new/lib/ts

export TSLIB_FBDEVICE=/dev/fb0

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSLIB_ROOT/lib

3、若是界面旋转90度显示后,触摸同样需旋转90度,在开发板中的/usr/local/tslib-1.21-new/bin下执行

/usr/local/tslib-1.21-new/bin# ./ts_calibrate --help

可看到如下信息:

-r --rotate

0 ... no rotation; 0 degree (default)

                       1 ... clockwise orientation; 90 degrees

                       2 ... upside down orientation; 180 degrees

                       3 ... counterclockwise orientation; 270 degrees

因此需重新执行

/usr/local/tslib-1.21-new/bin#./ts_calibrate –r 1

重新校正屏幕即可实现和屏幕同样的选择。

遇到的问题

1、在运行./build.sh中出现“cannot  find /lib/ld-linux-armhf.so.3”,需要把嵌入式linux文件系统中的rootfs/lib/ld-2.20.so下链接到Ubuntu下的/lib/ld-linux-armhf.so.3执行以下命令

/opt#  ln-s /opt/rootfs/lib/ld-2.20.so   /lib/ld-linux-armhf.so.3

2、在make过程中出现“ collect2:fatal error:cannot find ‘ld’”在build.sh中添加-no-use-gold-linker 配置项即可。

3、在Ubuntu中交叉编译成功的应用程序放到开发板执行时出现“No such file or directory”;在在build.sh中配置中增加以下两句配置,链接到嵌入式的文件系统中

-L /opt/rootfs/usr/lib \

-L /opt/rootfs/lib

4、编译Qt5的版本时,选用编译器的版本很关键,可以先查看

/opt/qt5.9.1-src/qtbase/mkspecs/目录下的qconfig.pri文件下的推荐的gcc版本,如下所示:

QT_GCC_MAJOR_VERSION = 4

QT_GCC_MINOR_VERSION = 9

QT_GCC_PATCH_VERSION = 1

编译时交叉编译链最好比这个版本高,像Qt5.9.1选择的gcc版本至少得gcc4.9.1以上。

5、编程时Ubuntu可能会报缺失依赖库,缺失的库用apt-get install安装即可。

你可能感兴趣的:(技术杂记,嵌入式,linux,ubuntu)