2、其备桥型次,将C/C++代码复制到arm架构路径下,并在消冲该路径下创建Android.mk和Application.mk文件。
3、最后,点击运行,不报错,即可解决问题。
准备工作:首先,最不可思议的,是要在Linux下把QT编译一遍,因为库都是一样的,需要的就是一些Windows下的qmake、moc、uic之类的工具而已。因为QT源码很多地方不能在Windows下面交叉编译通过,虽然我改了一些代码和配置(一会儿我贴出补丁来),但我只用它编译了qtbase、qtdeclarative这两个模块和qttools模块中的一部分。
Linux下的编译可以参照我之前写的这篇文章。参考配置:
开发包:
./configure -extprefix /opt/qt/5.2.1/arm -prefix /usr -plugindir /usr/lib/qt/plugins -importdir /usr/lib/qt/imports -qmldir /usr/lib/qt/qml -make libs -xplatform linux-arm-gnueabi-g++ -opengl es2 -confirm-license -opensource -xcb -xinput2 -nomake examples -nomake tests -qt-zlib -qt-xcb -dbus -largefile -cups -no-fontconfig -glib -gtkstyle -qt-freetype -sysroot /opt/sysroot-arm -mysql_config /opt/sysroot-arm/usr/bin/mysql_config -v
运行库:
./configure -prefix /usr -plugindir /usr/lib/qt/plugins -importdir /usr/lib/qt/imports -qmldir /usr/lib/qt/qml -make libs -xplatform linux-arm-gnueabi-g++ -opengl es2 -confirm-license -opensource -xcb -xinput2 -nomake examples -nomake tests -qt-zlib -qt-xcb -dbus -largefile -cups -no-fontconfig -glib -gtkstyle -qt-freetype -sysroot /opt/sysroot-arm -mysql_config /opt/sysroot-arm/usr/bin/mysql_config -v
做完这一步,你获得两样东西,sysroot和linux下的ARM QT开发文件。sysroot是编译QT之前,用Buildroot做的开发用根目录。这两个东西都要拷贝到Windows里,因为Windows不支持符号连接谨吵,拷贝需要需要去掉这些连接,这么做:
cp [源目录] [目标目录] -Lr
第二,需要一个Windows下模拟Linux环境的东西和编译器,我用的是MSYS和MinGW,因为他们编译出来的程序比Cygwin快。在这里可以找到:http://www.mingw.org/。
第三,悔游需要Linaro ARM GCC编译器,Windows版本的。在这里可以找到:http://www.linaro.org/downloads/
第四祥前侍,需要Python,Windows版本的。在这里可以找到:https://www.python.org/downloads/
下载、安装,然后在MSYS根目录的/etc/profile里面export PATH=$PATH:[Python安装目录]
第五,需要pkg-config,Windows版本的,这个比较麻烦,需要下载以下三个文件,并提取出我们需要的东西:
http://ftp.acc.umu.se/pub/gnome/binaries/win32/dependencies/pkg-config_0.26-1_win32.zip
(提取pkg-config.exe)
http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.28/glib_2.28.8-1_win32.zip
(提取libglib-2.0-0.dll)
http://ftp.acc.umu.se/pub/gnome/binaries/win32/dependencies/gettext-runtime_0.18.1.1-2_win32.zip (提取intl.dll)
把他们都放到MSYS的bin目录下,然后给pkg-config.exe做一个脚本pkg-config,因为下载的pkg-config.exe比较蠢,在同时指定PKG_CONFIG_SYSROOT_DIR和PKG_CONFIG_LIBDIR这两个环境变量的时候,第一个cflags会输出两次PKG_CONFIG_SYSROOT_DIR。这么做这个脚本:
#!/bin/sh
pushd / >/dev/null
ROOTDIR=`pwd -W 2>/dev/null`
popd >/dev/null
SYSROOT=$PKG_CONFIG_SYSROOT_DIR
pkg-config.exe "$@" | sed "s#$SYSROOT$SYSROOT#$SYSROOT#g" | sed "s#$ROOTDIR##g"
最后去掉$ROOTDIR前缀是为了和Linux Makefile兼容,同时也不会影响在make中的地址转换,最后,QT源码和我的补丁。
我的补丁如下:
diff -Naur qt-everywhere-opensource-src-5.2.1-old/qtbase/configure qt-everywhere-opensource-src-5.2.1/qtbase/configure
--- qt-everywhere-opensource-src-5.2.1-old/qtbase/configure 2014-02-02 04:37:23 +0800
+++ qt-everywhere-opensource-src-5.2.1/qtbase/configure 2014-08-27 22:34:47 +0800
@@ -4022,6 +4022,10 @@
done
(cd "$outpath/qmake""$MAKE") || exit 2
+if [ -e "$outpath/bin/qmake.exe" ]then
+ echo '#!/bin/sh' >"$outpath/bin/qmake"
+ echo "$outpath/bin/qmake.exe" '"$@"' "-unix" >>"$outpath/bin/qmake"
+fi
fi # Build qmake
echo "Running configuration tests..."
@@ -4091,9 +4095,9 @@
# when xcompiling, check environment to see if it's actually usable
if [ -z "$PKG_CONFIG_LIBDIR" ]then
if [ -n "$CFG_SYSROOT" ] &&[ -d "$CFG_SYSROOT/usr/lib/pkgconfig" ]then
-PKG_CONFIG_LIBDIR=$CFG_SYSROOT/usr/lib/pkgconfig:$CFG_SYSROOT/usr/share/pkgconfig
+PKG_CONFIG_LIBDIR=$CFG_SYSROOT/usr/lib/pkgconfig\$CFG_SYSROOT/usr/share/pkgconfig
if [ -n "$GCC_MACHINE_DUMP" ]then
-PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR:$CFG_SYSROOT/usr/lib/$GCC_MACHINE_DUMP/pkgconfig
+PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR\$CFG_SYSROOT/usr/lib/$GCC_MACHINE_DUMP/pkgconfig
fi
export PKG_CONFIG_LIBDIR
echo >&2 "Note: PKG_CONFIG_LIBDIR automatically set to $PKG_CONFIG_LIBDIR"
diff -Naur qt-everywhere-opensource-src-5.2.1-old/qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf qt-everywhere-opensource-src-5.2.1/qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
--- qt-everywhere-opensource-src-5.2.1-old/qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf 2014-02-02 04:37:37 +0800
+++ qt-everywhere-opensource-src-5.2.1/qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf 2014-08-28 00:08:34 +0800
@@ -11,14 +11,21 @@
include(../common/g++-unix.conf)
# 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++
+QMAKE_CC= arm-linux-gnueabihf-gcc
+QMAKE_CXX = arm-linux-gnueabihf-g++
+QMAKE_LINK = arm-linux-gnueabihf-g++
+QMAKE_LINK_SHLIB= arm-linux-gnueabihf-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
+QMAKE_AR= arm-linux-gnueabihf-ar cqs
+QMAKE_OBJCOPY = arm-linux-gnueabihf-objcopy
+QMAKE_NM= arm-linux-gnueabihf-nm -P
+QMAKE_STRIP = arm-linux-gnueabihf-strip
+
+# support for OpenGL
+QMAKE_LIBS_EGL = -lEGL
+QMAKE_LIBS_OPENGL_ES1 = -lGLES_CM
+QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
+#QMAKE_LIBS +=
+
load(qt_config)
diff -Naur qt-everywhere-opensource-src-5.2.1-old/qtbase/qmake/generators/makefile.cpp qt-everywhere-opensource-src-5.2.1/qtbase/qmake/generators/makefile.cpp
--- qt-everywhere-opensource-src-5.2.1-old/qtbase/qmake/generators/makefile.cpp 2014-02-02 04:37:29 +0800
+++ qt-everywhere-opensource-src-5.2.1/qtbase/qmake/generators/makefile.cpp 2014-08-26 13:53:15 +0800
@@ -1161,8 +1161,8 @@
QString srcf = (*sit).toQString()
QString dstf = (*oit).toQString()
-t <<escapeDependencyPath(dstf) <<": " <<escapeDependencyPath(srcf)
- <<" " <<escapeDependencyPaths(findDependencies(srcf)).join(" \\\n\t\t")
+t <<escapeDependencyPath(dstf).replace(QRegExp("\\\\"), "/") <<": " <<escapeDependencyPath(srcf).replace(QRegExp("\\\\"), "/")
+ <<" " <<escapeDependencyPaths(findDependencies(srcf)).replaceInStrings(QRegExp("\\\\"), "/").join(" \\\n\t\t")
ProKey comp, cimp
for(QStringList::Iterator cppit = Option::cpp_ext.begin()cppit != Option::cpp_ext.end()++cppit) {
@@ -3346,6 +3346,8 @@
QString MakefileGenerator::installMetaFile(const ProKey &replace_rule, const QString &src, const QString &dst)
{
QString ret
+ QString src_p = src
+ QString dst_p = dst
if (project->isEmpty(replace_rule)
|| project->isActiveConfig("no_sed_meta_install")) {
ret += "-$(INSTALL_FILE) \"" + src + "\" \"" + dst + "\""
@@ -3362,7 +3364,7 @@
+ "," + windowsifyPath(replace.toQString()) + ",gi")
}
}
-ret += " \"" + src + "\" >\"" + dst + "\""
+ret += " \"" + src_p.replace(QRegExp("\\\\"), "/") + "\" >\"" + dst_p.replace(QRegExp("\\\\"), "/") + "\""
}
return ret
}
struct TermChain {
TermChain(PatternTerm term)
diff -Naur qt-everywhere-opensource-src-5.2.1-old/qttools/src/linguist/lrelease/lrelease.pro qt-everywhere-opensource-src-5.2.1/qttools/src/linguist/lrelease/lrelease.pro
--- qt-everywhere-opensource-src-5.2.1-old/qttools/src/linguist/lrelease/lrelease.pro 2014-02-02 04:37:57 +0800
+++ qt-everywhere-opensource-src-5.2.1/qttools/src/linguist/lrelease/lrelease.pro 2014-08-28 10:42:55 +0800
@@ -1,4 +1,7 @@
option(host_build)
+
+win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
+
QT = core-private
DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
diff -Naur qt-everywhere-opensource-src-5.2.1-old/qttools/src/linguist/lupdate/lupdate.pro qt-everywhere-opensource-src-5.2.1/qttools/src/linguist/lupdate/lupdate.pro
--- qt-everywhere-opensource-src-5.2.1-old/qttools/src/linguist/lupdate/lupdate.pro 2014-02-02 04:37:57 +0800
+++ qt-everywhere-opensource-src-5.2.1/qttools/src/linguist/lupdate/lupdate.pro 2014-08-28 10:46:59 +0800
@@ -1,4 +1,7 @@
option(host_build)
+
+win32-g++*:QMAKE_CXXFLAGS_CXX11 = -std=gnu++0x
+
QT = core-private
qtHaveModule(qmldevtools-private) {
接下来开始配置:
其中-extprefix定义安装位置,在编译完以后可以改,一会儿说;-prefix、-plugindir、-importdir、-qmldir定义的位置是目标板上的位置,加双斜杠是为了防止MSYS翻译这些路径成MSYS的路径,其他的设定与Linux下的编译没有不同。Linux下编译的sysroot可以拷贝到例如:E:/MinGW/opt/sysroot-arm。
然后编译
make module-qtbase
make module-qtdeclarative
cd qttools/src/linguist
../../../qtbase/bin/qmake.exe -unix linguist.pro
make
编译的时候可能会有几个库有链接错误,找不到一大堆gl、egl打头的函数,这是因为相应的Makefile里面的LIBS没有自动加上-lEGL -lGLES_CM -lGLESv2;但是正式使用qmake的时候不会,很奇怪;因为也就几个地方,出问题了手工加一下吧,我没去查原因改代码。
编译linguist的时候可能会遇到这个问题:http://qt-project.org/forums/viewthread/33370,按里面说的处理。
编译完了以后,把下列文件拷贝到Linux下编译的ARM QT开发包的bin目录中去:
然后,删掉对应的ARM QT开发包的bin目录中没有exe后缀的文件,那些是Linux下的。
最后一步,确保安装路径正确,也就是说,如果配置Windows下QT的时候设定-extprefix E:/MinGW/opt/qt/5.2.1/arm,那就要把替换过exe文件的ARM QT开发包放到这个位置,如果路径改了,可以用二进制搜索工具去qmake.exe中替换这个字串。
补充一下关于调试的问题,其实不是很关键。
在使用Debug模式编译的时候,最后会出现如下提示:
warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB. Attempting to continue with the default i386 settings.
这是因为在mkspecs/features/unix/gdb_dwarf_index.prf中,有这样一段:
QMAKE_GDB_INDEX += \
test \$\$(gdb --version | sed -e \'s,[^0-9][^0-9]*\\([0-9]\\)\\.\\([0-9]\\).*,\\1\\2,q\') -gt 72 &&\
gdb --nx --batch --quiet -ex \'set confirm off\' -ex \"save gdb-index $$QMAKE_GDB_DIR\" -ex quit \'$(TARGET)\' &&\
test -f $(TARGET).gdb-index &&\
$$QMAKE_OBJCOPY --add-section \'.gdb_index=$(TARGET).gdb-index\' --set-section-flags \'.gdb_index=readonly\' \'$(TARGET)\' \'$(TARGET)\' &&\
$$QMAKE_DEL_FILE $(TARGET).gdb-index || true
很显然,这段代码把调试用的GDB默认为“gdb”了,所以应该改成你用的gdb,比如arm-linux-gnueabihf-gdb。另外,这里的sed对GDB版本的判断,无法识别像“GNU gdb (Sourcery CodeBench Lite 2014.05-29) 7.7.50.20140217-cvs”这样的版本信息的,只能识别像“GNU gdb (GDB) 7.6.1”这样的版本信息,所以你有可能看不到刚才那段提示。想解决,要么重新写一段sed的正则表达式,要么直接就把这个test ... -gt 72删掉。
在嵌入式产品大行其道的今天,Linux经过裁剪和优化而成的uClinux在嵌入式领域众多的 *** 作系统中占有一席之地。从uClinux字面上就可以看出它的含义,即“微控制器领域中的Linux系统”。uClinux从Linux 2.0/2.4内核派生而来,沿袭了Linux的绝大部分特性。它是专门针对没有MMU(内存管理单元)的CPU,并且为嵌入式系统做了许多小型化的工作。它通常用于具有很少内存或Flash的嵌入式 *** 作系统。在GNU通用许可证的保证下,运行uClinux *** 作系统的用户可以使用几乎所有的Linux API函数。由于经过了裁剪和优化,它形成了一个高度优化,代码紧凑的嵌入式Linux。它具有体积小、稳定、良好的移植性、优秀的网络功能、完备的对各种文件系统的支持,以及丰富的API函数等优点。uClinux与Linux在兼容性方面表现出色,uClinux除了不能实现fork()外,其余uClinux的API函数与标准Linux完全相同。
uClinux的基本架构
Boot Loader:负责Linux内核的启动,用于初始化系统资源。这部分代码用于建立Linux内核运行环境和从Flash中装载初始化Ramdisk。
内核初始化:Linux内核的入口点是start kernel()函数。它初始化内核的其它部分,包括捕获、IRQ通道、调度、设备驱动、标定延迟循环,最重要的是能够fork“init”进程,以启动整个多任务环境。
系统调用函数/捕获函数:在执行完“init”程序后,内核对程序流不再有直接地控制权。此后,它的作用仅仅是处理异步事件(例如硬件中断)和为系统调用提供进程。
设备驱动:设备驱动占据了Linux内核很大部分。同其它 *** 作系统一样,设备驱动为它们所控制的硬件设备和 *** 作系统提供接口。
文件系统:Linux最重要的特性之一就是对多种文件系统的支持。这种特性使得Linux很容易地同其它 *** 作系统共存。文件系统的概念使得用户能够查看存储设备上的文件和路径而无须考虑实际物理设备的文件系统类型。
交叉编译环境
uClinux是一个出色的开发平台,但是在我们能在电脑上编写自己的嵌入式应用程序之前,还必须做的一件事,就是给uClinux建立完稿局带善的编译环境。关于交叉编译,简单地讲是指在一个平台( *** 作系统)上可以生成能在另一个平台上执行的代码。
但是对于有些不是很懂Linux环境的人来讲,用uClinux开发程序会感到诸多不便。这里提供了在装有Windows系统的宿主机(开发时所用的机器)上建立交叉编译环境的方法。
为了在Windows下开发嵌入式 *** 作系统应用程序,可以在Windows环境下装上Cygwin软件。Cygwin是一个在Windows平台上运行的Unix模拟环境,是Cygnus Solutions公司开发的自由软件。它对于学习掌握Unix/Linux *** 作环境,或者进行某些特殊的开发工作,尤其是使用GNU工具集在Windows上进行嵌入式系统开发,非常有用。
Cygnus首先把gcc、gdb等开发工具进行键芦了改进,使它们能够生成并解释WIN32的目标文件。然后,把这些工具移植到Windows平台上去。一种方案是基于WIN32 APl对这些工具的源代码进行大幅修改,这样做显然需要大量工作。因此,Cygnus采取了一种不同的方法——他们写了一个共享库(就是cygwinl.d11),把WIN32 API中没有的Unix风格的调用(如fork、spawn、signals、select、sockets等)封装在里面。也就是说,他们基于WIN32 APl写了一个Unix系统库的模拟层。这样,只要把这些工具的源代码和这个共享库连接到一起,就可以使用Unix主机上的交叉编译器来生成可以在Windows平台上运行的工具集。以这些移植到Windows平台上的开发工具为基础,Cygnus又逐步把其它的工具(几乎不需腊敬要对源代码进行修改,只需要修改他们的配置脚本)软件移植到Windows上来。这样,在Windows平台上运行bash和开发工具、用户工具,感觉好像在Unix上工作。
生成交叉编译器
Cygwin软件目前最新版本是Cygwin DLL 1.5.9-1。它的网址是http:// Cygwin.com,上面就有该程序的压缩包,下载后解压安装就ok了。
在自己生成交叉编译器之前,首先对Cygwin进行一些设置。假设Cygwin安装在e目录下,在打开Cygwin窗口之前,进入到E:\Cygwin目录。在这个目录下,有一个文件名为Cygwin.bat的批处理文件,编辑该文件,在第一行后加入setCYGWIN--titlentea,这是因为Cygwin的启动批处理文件需要启动Unix文件系统模拟。修改完毕且保存后退出。双击桌面上的Cygwin图标,打开后默认用户为在Windows中登录的用户名(这里所使用的 *** 作系统是Windows 2000 Professsional),在根目录(即E:\cygwin)下输入:
cd bin
mV Sh.exe Sh—original.exe
n —S bash.exe Sh.Exe
做上述几步的原因是大多数Linux系统把sh符号链接到bash,而Cygwin上的sh.exe和bash.exe是不同的,因此必须用bash代替sh。
从网站上下载生成工具链的各种源码,根据脚本文件build-ucLinux-tools.sh建立可在Windows下编译用户应用程序的交叉编译器,生成的交叉编译器最终被打包为arm-elf-tools-cygwin-yyyymmdd.tar.gz的文件,其中YYYY为生成交叉编译器的年,mm为生成交叉编译器的月份,dd为日期。
这里,需要注意的是在生成交叉编译器的过程中,可能会遇到多次错误,读者应该根据给出的出错信息,进行相应文件的修改。由于习惯上的原因,Linux下的压缩文件一般都是以.tar.gz或者.tgz结尾的。虽然用Windows下的解压软件,比如winzip或者winrar也可以解压这些文件,但是不推荐使用这类解压软件,因为可能会造成某些信息的丢失。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)