1. 版本说明
操作系统:Ubuntu20.04 64位
交叉工具链:gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi
Qt版本:qt-everywhere-opensource-src-4.8.7
2. Ubuntu20.04 交叉编译 qt4.8.7 版本大致过程
2.1. 交叉编译 openssl1.0.1q
2.1.1. 配置
$ CC=arm-linux-gnueabi-gcc ./config no-asm no-async shared --prefix=/opt/imx6/openssl1.0.1q
2.1.2. make & install
打开Makefile文件删除-m64字样。
$ make -j4
$ make install
2.2. 交叉编译 tslib1.21
2.2.1. 安装依赖
tslib 依赖
$ sudo apt-get install autoconf
$ sudo apt-get install automake
$ sudo apt-get install libtool
$ sudo apt-get install g++
qt 依赖
$ sudo apt-get install libc6-dev:i386
$ sudo apt-get install build-essential
$ sudo apt-get install gcc-multilib
2.2.2. 解压后编译安装
$ ./configure --prefix=/opt/imx6dl/tslib1.4 --host=arm-linux-gnueabi CC=arm-linux-gcc --enable-shared --enable-static
$ make && make install
2.3. 交叉编译 qt4.8.7
2.3.1. 提取Qt4.8.7源代码
$ tar -zxvf qt-everywhere-opensource-src-4.8.7.tar.gz
2.3.2. 修改 mkspeces/qws/linux-arm-gnueabi-g++/qmake.conf
#
# qmake configuration for building with arm-linux-gnueabi-g++
#
include(../../common/linux.conf)
include(../../common/gcc-base-unix.conf)
include(../../common/g++-unix.conf)
include(../../common/qws.conf)
# modifications to g++.conf
QMAKE_CC = arm-linux-gnueabi-gcc -lts -lssl -lcrypto # 此四项去掉none再增加参数
QMAKE_CXX = arm-linux-gnueabi-g++ -lts -lssl -lcrypto
QMAKE_LINK = arm-linux-gnueabi-g++ -lts -lssl -lcrypto
QMAKE_LINK_SHLIB = arm-linux-gnueabi-g++ -lts -lssl -lcrypto
# modifications to linux.conf
QMAKE_AR = arm-linux-gnueabi-ar cqs # 此三项去掉none
QMAKE_OBJCOPY = arm-linux-gnueabi-objcopy
QMAKE_STRIP = arm-linux-gnueabi-strip
QMAKE_INCDIR +=/opt/imx6/tslib1.21/include ## 此四项增加
QMAKE_INCDIR +=/opt/imx6/openssl1.0.1q/include
QMAKE_LIBDIR +=/opt/imx6/tslib1.21/lib
QMAKE_LIBDIR +=/opt/imx6/openssl1.0.1q/lib
load(qt_config)
2.3.3. 新增 autoConfigure.sh 脚本并执行
#!/usr/bin/env bash
./configure -opensource -v \
-confirm-license \
-embedded arm \
-release -shared \
-depths 16,18,24,32 \
-optimized-qmake \
-no-pch \
-qt-sql-sqlite \
-qt-libjpeg \
-qt-zlib \
-qt-libpng \
-fontconfig \
-qt-freetype \
-little-endian \
-no-qt3support \
-no-libtiff -no-libmng \
-no-opengl \
-no-mmx -no-sse -no-sse2 \
-no-3dnow \
-no-webkit \
-no-qvfb \
-no-cups \
-nomake examples \
-nomake demos \
-nomake docs \
-qt-mouse-tslib \
-qt-mouse-pc \
-qt-gfx-transformed \
-openssl-linked \
-xplatform qws/linux-arm-gnueabi-g++ \
-prefix /opt/imx6dl/qt-4.8.7-arm \
-I /opt/imx6dl/openssl1.0.1q/include \
-L /opt/imx6dl/openssl1.0.1q/lib \
-I /opt/imx6dl/tslib1.21/include \
-L /opt/imx6dl/tslib1.21/lib
2.3.4. make -j12 && make install
注意:编译过程出现 has no member named
错误,依据 3 进行处理后编译。
3. has no member named 报错处理
make时编译错误如下:
dialogs/qpagesetupdialog_unix.cpp:276:12: 错误: ‘class Ui::QPageSetupWidget’ has no member named ‘topMargin’
widget.topMargin->setSuffix(suffix);
^
dialogs/qpagesetupdialog_unix.cpp:277:12: 错误: ‘class Ui::QPageSetupWidget’ has no member named ‘bottomMargin’
widget.bottomMargin->setSuffix(suffix);
^
dialogs/qpagesetupdialog_unix.cpp:278:12: 错误: ‘class Ui::QPageSetupWidget’ has no member named ‘leftMargin’
widget.leftMargin->setSuffix(suffix);
^
... ...
make[1]: *** [Makefile:133419:.obj/release-shared-emb-arm/qpagesetupdialog_unix.o] 错误 1
make[1]: *** 正在等待未完成的任务....
dialogs/qfiledialog.cpp: 在成员函数‘QByteArray QFileDialog::saveState() const’中:
dialogs/qfiledialog.cpp:431:33: 错误: ‘class Ui_QFileDialog’ has no member named ‘treeView’
stream << d->qFileDialogUi->treeView->header()->saveState();
^
dialogs/qfiledialog.cpp: 在成员函数‘bool QFileDialog::restoreState(const QByteArray&)’中:
dialogs/qfiledialog.cpp:487:49: 错误: ‘class Ui_QFileDialog’ has no member named ‘treeView’
QHeaderView *headerView = d->qFileDialogUi->treeView->header();
^
dialogs/qfiledialog.cpp: 在成员函数‘void QFileDialogPrivate::retranslateStrings()’中:
dialogs/qfiledialog.cpp:578:46: 错误: ‘class Ui_QFileDialog’ has no member named ‘treeView’
QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
^
... ...
dialogs/qfiledialog.cpp: 在成员函数‘QModelIndex QFileDialogPrivate::rootIndex() const’中:
dialogs/qfiledialog.cpp:1412:39: 错误: ‘class Ui_QFileDialog’ has no member named ‘listView’
return mapToSource(qFileDialogUi->listView->rootIndex());
^
dialogs/qfiledialog.cpp: 在成员函数‘QAbstractItemView* QFileDialogPrivate::currentView() const’中:
dialogs/qfiledialog.cpp:1418:73: 错误: ‘class Ui_QFileDialog’ has no member named ‘listView’
if (qFileDialogUi->stackedWidget->currentWidget() == qFileDialogUi->listView->parent())
^
dialogs/qfiledialog.cpp:1419:31: 错误: ‘class Ui_QFileDialog’ has no member named ‘listView’
return qFileDialogUi->listView;
^
dialogs/qfiledialog.cpp:1420:27: 错误: ‘class Ui_QFileDialog’ has no member named ‘treeView’
return qFileDialogUi->treeView;
^
... ...
make[1]: *** [Makefile:135520:.obj/release-shared-emb-arm/qfiledialog.o] 错误 1
make[1]: 离开目录“/opt/imx6dl/tool/qt-everywhere-opensource-src-4.8.7/src/gui”
make: *** [Makefile:381:sub-gui-make_default-ordered] 错误 2
3.1. 报错分析
查看 src/gui/dialogs/qpagesetupdialog_unix.cpp 文件
报错处:
276 widget.topMargin->setSuffix(suffix);
277 widget.bottomMargin->setSuffix(suffix);
278 widget.leftMargin->setSuffix(suffix);
widget 创建处:
239 void QPageSetupDialogPrivate::init()
240 {
241 Q_Q(QPageSetupDialog);
242
243 widget = new QPageSetupWidget(q);
查看 src/gui/dialogs/qpagesetupwidget.ui 文件(QPageSetupWidget对应ui文件)
查找到 topMargin 位置
190 <widget class="QDoubleSpinBox" name="topMargin" >
191 <property name="toolTip" >
192 <string>top margin</string>
193 </property>
查看 src/gui/.uic/release-shared-emb-arm/ui_qpagesetupwidget.h 文件(QPageSetupWidget对应头文件)
未查找到 topMargin 成员变量
应该是 ui 文件转换成头文件时出了问题。
查看 qpagesetupwidget.ui 文件的处理
$ grep -rn "qpagesetupwidget.ui" *
src/gui/Makefile:52073: /opt/imx6dl/tool/qt-everywhere-opensource-src-4.8.7/bin/uic dialogs/qpagesetupwidget.ui -o .uic/release-shared-emb-arm/ui_qpagesetupwidget.h
依据 Makefile 中处理方式,用 uic 命令处理两个 ui 文件。
发现 uic 处理文件,有告警。且告警的 成员变量 未生成到对应的头文件。
$ ./qt-everywhere-opensource-src-4.8.7/bin/uic qpagesetupwidget.ui -o ui_qpagesetupwidget.h
qpagesetupwidget.ui: Warning: Buddy assignment: 'paperSize' is not a valid widget.
qpagesetupwidget.ui: Warning: Buddy assignment: 'paperWidth' is not a valid widget.
qpagesetupwidget.ui: Warning: Buddy assignment: 'paperHeight' is not a valid widget.
qpagesetupwidget.ui: Warning: Buddy assignment: 'paperSource' is not a valid widget.
$ ./qt-everywhere-opensource-src-4.8.7/bin/uic qfiledialog.ui -o ui_qfiledialog.h
qfiledialog.ui: Warning: Tab-stop assignment: 'lookInCombo' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'backButton' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'forwardButton' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'toParentButton' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'newFolderButton' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'listModeButton' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'detailModeButton' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'listView' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'fileNameEdit' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'fileTypeCombo' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'buttonBox' is not a valid widget.
qfiledialog.ui: Warning: Tab-stop assignment: 'treeView' is not a valid widget.
3.2. qt uic
$ ./qt-everywhere-opensource-src-4.8.7/bin/uic -help
Qt User Interface Compiler version 4.8.7
Usage: /opt/imx6dl/tool/qt-everywhere-opensource-src-4.8.7/bin/uic [options] <uifile>
-h, -help display this help and exit
-v, -version display version
-d, -dependencies display the dependencies
-o <file> place the output into <file>
-tr <func> use func() for i18n
-p, -no-protection disable header protection
-n, -no-implicit-includes disable generation of #include-directives
for forms generated by uic3
-g <name> change generator
QT设计器设计的窗口部件,通过 uic 工具转换成C++代码。
对比 Ubuntu16.04 能正常编译的情况。再查找资料后,发现可能是Ubuntu20.04 自带GCC版本过高的问题。
3.3. 修改 ubuntu20.04 的 gcc、g++ 版本
3.3.1. 查看当前gcc版本
$ gcc -v
$ g++ -v
查看当前gcc命令的软链接
$ ls -liat /usr/bin/g++
531095 lrwxrwxrwx 1 root root 5 3月 20 2020 /usr/bin/gcc -> gcc-9
$ ls -liat /usr/bin/g++
531095 lrwxrwxrwx 1 root root 5 3月 20 2020 /usr/bin/g++ -> g++-9
ubuntu20.04 默认安装的 gcc9.4。
3.3.2. 安装gcc7并切换版本
sudo apt-get install gcc-7 g++-7
使用update-alternatives进行版本切换,输入以下命令:
# update-alternatives: --install 需要 <链接> <名称> <路径> <优先级>
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 100
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 50
查看gcc的默认版本,可以看到当前默认gcc版本为7,即切换成功。
sudo update-alternatives --config gcc
查看当前gcc命令的软链接
$ ls -liat /usr/bin/gcc
528697 lrwxrwxrwx 1 root root 21 3月 10 13:45 /usr/bin/gcc -> /etc/alternatives/gcc
$ ls -liat /usr/bin/g++
528698 lrwxrwxrwx 1 root root 21 3月 10 13:48 /usr/bin/g++ -> /etc/alternatives/g++