交叉编译windows库
1. 在WINDOWS下交叉编译linux程序运行不了是为什么
交叉编译出来的文件在目标机上无法运行大多由两个原因造成:
1 交叉编译工具链与目标机架构不匹配,也就是选错了编译工具;
2 缺少依赖库,这种情况可使用ldd命令查看依赖项,检查一下是否缺少依赖库文件
2. 什么是交叉编译为什么要使用交叉编译
就是指编译器在某一个平台下能够编译出另外一个平台下运行的程序
主要是为了多平台应用程序使用的
比如某一个程序,在windows下和linux和MacOS下都有相应的运行版本,使用交叉编译就可以在一个平台下全部完成,而不用切换到对应的平台再去编译
3. windows7下搭建eclipse对stm32的交叉编译环境,ECLIPSE(C/C++ JUNO)+yagarto+mingw+gunplugin gcc版本
JRE的版本问题,导致插件不能使用,导致不能连接到有效的库文件,所以,重装吧。一定要选对版本
4. linux mount windows共享目录 交叉编译安卓动态库传输错误
那就是软件问题了
5. gcc -arm这个交叉编译工具。有没有可以再window上使用的
yagarto和codesourcery都是在windows下用的,官方已经编译打包好的
EXE文件
cygwin下可以自己编译源代码,做出GNU工具链
mingw也可以实现
还有一些在windows下用的IDE,专门针对GNU工具链的,code::blocks,emide等
我在用emIDE,arm-none-eabi-gdb调试ARM
6. 如何在windows上用ndk交叉编译其他平台程序
目标 :编译arm64的.so库
编译方法:理论上应该有两种交叉编译方法,法一,在Linux服务器上安装交叉工具链,直接用交叉工具链进行编译链接;法二,使用ndk完成交叉编译,因为
ndk已经安装好交叉编译工具链,以及相关的系统库和系统头文件了。这两种方法的区别在于,linux服务器上的编译使用的makefile和ndk使用的.mk
文件显然不同。原因是ndk作为一个集成编译环境,制定了一套特定的规则用于生成最终的编译脚本。
这里简单总结下,如何在windows用ndk进行交叉编译arm64目标平台的.so库:
step1:找到ndk开发工具包,官网之类的都可以下载,Android-ndk64-r10-windows-x86_64.rar文件
step2:解压上述ndk工具包,将包含程序源文件和头文件的文件夹testProject都放入android-ndk-r10下的samples目录下。
放在其他地方当然也可以,但是后续相对路径之类的不太好加,既然其他例子都放这,把代码放这编译是最保险的了。
step3:在testProject中增加一个jni的文件夹,必须要添加!!!!!!
step4:在jni文件夹中,添加一个Android.mk的文件,必须要添加!!!!!
step5:在jni文件夹中,添加一个Application.mk的文件与Android.mk并列,必须要添加!!!!!
step6:Android.mk和Application.mk合起来就类似于linux环境下的makefile编译文件。
如何写Android.mk,可以参考例子helllo-jni中jni文件夹下的Android.mk。
LOCAL_PATH:=$(call my-dir) #必须要写的
include $(CLEAR_VARS) #必须要写的
LOCAL_MODULE:=hello-jni #编译出来的模块名称
LOCAL_SRC_FILES:=hello-jni.c #制定编译的源文件名称
include $(BUILD_SHARED_LIBRARY)#放在最后
除了上述变量之外,还有其他的指定的变量,
LOCAL_CFLAGS,用于指定编译选项,这个和makefile中是完全一样的,可以指定编译选项-g,也可以指定编译宏及宏值
LOCAL_LDLIBS,用于指定链接的依赖库,这个可以makefile也是完全一样的,可以指定链接库用-l库名,以及指定库搜索路径用_L路径名
LOCAL_STATIC_LIBRARIES,指定链接的静态库名,makefile中没有
LOCAL_C_INCLUDES,用于指定编译头文件的路径,和makefile中不同,路径前不需要加-I,直接写路径即可,可以是相对路径或绝对路径,
多个路径之间用空格隔开。
编写上述Android.mk碰到的问题有,
(1)使用默认的系统自动加载stl库头文件总是出错,只好手动在LOCAL_STATIC_LIBRARIES指定sources/cxx-stl/stlport/stlport来完成对#include<string>这种c++形式的头文件加载
(2)使用$(SYSROOT)/usr/include来完成对系统库头文件的加载,结果找不到sem_t符号,只好指定platforms/android-L/arch-arm64/usr/include
step7:Application.mk编写
APP_STL指定使用的stl移植库,动态或者静态都行
APP_CPPFLAGS,指定app编译的编译选项
APP_ABI指定abi规范类型,例如arm64-v8a,也可以写成ALL就是把所有的类型全部编一编
APP_PLATFORM指定编译的platform名称,这里可以写成android-L或者不指定全编。
step8:编译完成后,运行。
启动cmd,使用cd /D进行到testProject的jni目录下
step9:将android-ndk-r10下的ndk-build.cmd直接拖拽到cmd中,此时直接敲回车,就可以编译了。当然也可以加一个 clean,清除编译中间文件。
step10:检查下编译结果,编译成功后在testProject中多了两个文件夹与jni并列的,libs和obj。
编译链接后的结果就在libs中!
7. 如何搭建交叉编译环境
交叉编译环境就是在Windows下的东西拿到Linux下编译运行吧,我个人是在Linux启动了samba服务器,然后将文件夹映射到Windows下,在Windows下使用vc 6.0编程序然后到Linux下编译的。不知道能不能对你有些帮助。
下载的rpm包,可以使用rpm -ivh 包路径进行安装
8. 如何在windows平台下交叉编译gcc-C/C++
我怎么记得回答过呢? cygwin + 交叉编译器(这个必须是 for cygwin 的) Colinux + 交叉编译器(这个直接可以用 Linux 下面的) 虚拟机 + 交叉编译器(同上,虚拟机里就是一个 Linux) 双引导进 Linux + 交叉编译器
9. 如何在Windows下构建ARM Linux QT开发环境
准备工作:
首先,最不可思议的,是要在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-obj
-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-obj
+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
qtHaveMole(qmldevtools-private) {
接下来开始配置:
其中-extprefix定义安装位置,在编译完以后可以改,一会儿说;-prefix、-plugindir、-importdir、-qmldir定义的位置是目标板上的位置,加双斜杠是为了防止MSYS翻译这些路径成MSYS的路径,其他的设定与Linux下的编译没有不同。Linux下编译的sysroot可以拷贝到例如:E:/MinGW/opt/sysroot-arm。
然后编译
make mole-qtbase
make mole-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删掉。
10. 如何构建交叉编译环境。
你说的是我下面的回答吗?下面就一些问题作一个说明,以期抛砖引玉。
基于Linux操作系统的应用开发环境一般是由目标系统硬件(开发板)和宿主PC机所构成。目标硬件开发板用于运行操作系统和系统应用软件,而目标板所用到的操作系统的内核编译、应用程序的开发和调试则需要通过宿主PC机来完成(所以称为交叉编译)。双方之间一般通过串口,并口或以太网接口建立连接关系。
但在此我建议构建如下的交叉编译环境,适合个人或研发小组使用:单独拿出一台PC机(PII以上即可,就用以前淘汰的旧机器就可以),在该PC上安装桌面的Linux操作系统(如Red Hat Linux 8.0及以上),可以采用默认的安装选项(注意要包含FTP服务),这台PC作为Linux服务器,除管理员以外,一般不直接让其他人去操作。
将该Linux服务器接入局域网,并新建一些合法用户,以便其他的PC机(在此我们将其称为工作站)的合法用户能访问到Linux服务器。而其他的PC机(工作站)仍然使用Windows操作系统,原来干啥继续干啥。
需要的软件工具包括:
1、FTP客户端程序(如Cuteftp,可到网上下载)。
2、Telnet工具(如SecureCRT,可到网上下载)。
3、移植到某一特定ARM平台的Linux操作系统内核源码(一般由销售商整理提供)。
4、GNU编译工具,可由相关网站下载,或由销售商整理提供。
在工作站安装:
在某工作站PC上安装FTP客户端程序和Telnet工具,安装完毕后应该可以在该工作站PC和Linux服务器之间进行文件的传输,并在工作站PC可以通过Telnet登陆到Linux服务器(可能需要将Linux服务器的防火墙服务关闭才能完成)。
在Linux服务器安装:
将工作站PC上的Linux操作系统内核源码压缩包和GNU编译工具通过FTP传送到Linux服务器的某个目录(如合法的用户目录),然后在该目录下解压,并将GNU编译工具安装到默认的工作目录即可,以上工作通过在工作站PC使用Telnet工具完成,而不需要在Linux服务器上进行。
Linux操作系统内核的编译:
Linux操作系统内核的编译一般有一个比较固定的步骤,会根据MakeFile文件的不同而略有差异,可参考相关文档,编译的工作在工作站PC使用Telnet工具完成。