如何编译可以在Windows下运行的带有Python支持的ARM Linux GDB

如何编译可以在Windows下运行的带有Python支持的ARM Linux GDB,第1张

做这件事情的目的是为了在QtCreator里调试ARM Linux程序的时候,能看清楚QString、QList这些Qt特有的对象的内容,而不是一个完全看不懂的结构体。

目前(2014年8月)Linaro、CodeSourcery的GCC工具链里的GDB都不支持Python。想知道你用的GDB支持不支持,试一罩慧试就行,这样表示不支持:

(gdb) python

>print 'Hello GDB!'

>(按Ctrl+D)Python scripting is not supported in this copy of GDB.

这样表示支持:

(gdb) python

>print 'Hello GDB!'

>(按Ctrl+D)Hello GDB!

这件事情乍一看也很简单,只要把GDB源码下载下来,然后再配置,打开Python支持就行了。实际上会遇到的问题是,在MinGW下,又要与“\”和“:”这两个Windows路径里的刺头斗争了。我觉得我之前挺傻,编译MinGW下Qt的时候,就去硬磕源码和configure脚本去了。这次GDB的configure是自动生成的,不是给人看的,configure.ac看起来也很费劲,根本磕不下去,于是我换了个思路,在ubuntu下交叉编译吧,sudo apt-get install mingw32,这是Ubuntu下的MinGW交叉编译器。

然后是依赖,这样的GDB要依赖expat和python的开发版本。如果是ubuntu底下直接编译,apt-cache search一下他们的开发版本,然后sudo apt-get install一下就好了;给MinGW交叉编译就麻烦了。先说expat,这个好办,把http://downloads.sourceforge.net/project/expat/expat/2.1.0/expat-2.1.0.tar.gz下载下来,然后:

./configure --prefix=[安装目录,如/home/cdu/mingw-gdb/expat] --host=i586-mingw32msvc

make

make install

会提示一些警告,无碰闷橡视即可。

Python就无语了,目前的GDB貌似最高支持Python 2.7,而2.7版本的Python本身不支持MinGW…… 好在有高手做了Patch,也写了说明,可以参考这文章:http://mdqinc.com/blog/2011/10/cross-compiling-python-for-windows-with-mingw32/

但是,就算这样,编译也充满挑战,要修复很多问题,出来的Python还少“nt”模块。就在我觉得没办法的时候,突然发现Windows版Qt提供笑旁的MinGW居然内置了Python开发包,位置在Tools/mingw48_32/opt,赶紧把它拷贝到Linux下,比如/home/cdu/mingw-gdb/python。当然,你也必须确保ubuntu下有可用的python。

然后,给GDB打一个补丁:

--- gdb-7.8/gdb/configure 2014-07-29 20:37:42.000000000 +0800

+++ gdb-7.8-old/gdb/configure 2014-08-30 00:08:27.122042706 +0800

@@ -8263,21 +8263,22 @@

# We have a python program to use, but it may be too old.

# Don't flag an error for --with-python=auto (the default).

have_python_config=yes

-python_includes=`${python_prog} ${srcdir}/python/python-config.py --includes`

+python_config_tool=`echo ${python_prog} | sed "s#python.exe#python-config#g"`

+python_includes=`${python_config_tool} --includes`

if test $? != 0then

have_python_config=failed

if test "${with_python}" != autothen

as_fn_error "failure running python-config --includes" "$LINENO" 5

fi

fi

-python_libs=`${python_prog} ${srcdir}/python/python-config.py --ldflags`

+python_libs=`${python_config_tool} --ldflags`

if test $? != 0then

have_python_config=failed

if test "${with_python}" != autothen

as_fn_error "failure running python-config --ldflags" "$LINENO" 5

fi

fi

-python_prefix=`${python_prog} ${srcdir}/python/python-config.py --exec-prefix`

+python_prefix=`${python_config_tool} --exec-prefix`

if test $? != 0then

have_python_config=failed

if test "${with_python}" != autothen

@@ -8343,12 +8344,12 @@

return 0

}

_ACEOF

-if ac_fn_c_try_link "$LINENO"then :

+#if ac_fn_c_try_link "$LINENO"then :

have_libpython=${version}

found_usable_python=yes

PYTHON_CPPFLAGS=$new_CPPFLAGS

PYTHON_LIBS=$new_LIBS

-fi

+#fi

rm -f core conftest.err conftest.$ac_objext \

conftest$ac_exeext conftest.$ac_ext

CPPFLAGS=$save_CPPFLAGS

这个补丁的目的是强制为检测到python。

然后给拷贝到Linux下的python开发包打一个补丁:

--- python-old/bin/python-config 2013-04-18 02:43:01.000000000 +0800

+++ python/bin/python-config 2014-08-30 00:53:16.630060288 +0800

@@ -1,4 +1,4 @@

-#!/temp/x32-480-posix-dwarf-r2/mingw32/opt/bin/python2.7.exe

+#!/usr/bin/python

import sys

import os

@@ -31,26 +31,23 @@

for opt in opt_flags:

if opt == '--prefix':

-print sysconfig.PREFIX

+print '../python'

elif opt == '--exec-prefix':

-print sysconfig.EXEC_PREFIX

+print '../python'

elif opt in ('--includes', '--cflags'):

-flags = ['-I' + sysconfig.get_python_inc(),

- '-I' + sysconfig.get_python_inc(plat_specific=True)]

+flags = ['-I' + os.path.split(os.path.realpath(__file__))[0] + '/../include/python2.7']

if opt == '--cflags':

-flags.extend(getvar('CFLAGS').split())

+flags += ['-fno-strict-aliasing -DMS_WIN32 -DMS_WINDOWS -DHAVE_USABLE_WCHAR_T -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes']

print ' '.join(flags)

elif opt in ('--libs', '--ldflags'):

-libs = getvar('LIBS').split() + getvar('SYSLIBS').split()

-libs.append('-lpython'+pyver)

+libs = ['-lm -lpython2.7 -Wl,--out-implib=libpython2.7.dll.a']

# add the prefix/lib/pythonX.Y/config dir, but only if there is no

# shared library in prefix/lib/.

if opt == '--ldflags':

if not getvar('Py_ENABLE_SHARED'):

-libs.insert(0, '-L' + getvar('LIBPL'))

-libs.extend(getvar('LINKFORSHARED').split())

+libs.insert(0, '-L' + os.path.split(os.path.realpath(__file__))[0] + '/../lib/python2.7/config')

print ' '.join(libs)

因为Linux下是无法运行开发包中的python.exe的,所以这个补丁借用了ubuntu的python。里面的cflags和ldflags都是在Windows底下运行原始python-config获得的。prefix和exec-prefix设成“../python”,可以在编译完以后,把python开发包拷贝到gdb安装目录里面的python子目录,这样运行GDB的时候就不需要设定PYTHONHOME环境变量了。

最后一个事情,确保你的Linux下有arm交叉编译器,我的是arm-linux-gnueabihf,是啥target就写啥。

准备工作做完了,开始配置和编译:

./configure --with-expat --host=i586-mingw32msvc --target=arm-linux-gnueabihf --with-libexpat-prefix=[expat安装位置] --with-python=[python开发包安装位置/bin/python.exe]

make

make DESTDIR=[GDB安装位置] install

然后把GDB安装位置下面的所有文件拷贝到Windows下,再把python开发包拷贝到同目录下的python子目录,大功告成。

如果提示没找到libpython2.7.dll,那就把GDB安装目录的python/bin下的拷贝到bin下。

如果发现生成的exe文件太大了,那就strip一下。

2015年9月12日追加:

在windows下调试时,一般会提示说加载不了共享库,让你用"set sysroot"或"set solib-search-path"之类设定路径的。这个问题可以通过.gdbinit文件,用上面这两条命令来设定路径解决,如果想一劳永逸,可以在编译的时候加上host_configargs环境变量来解决这个问题:

host_configargs=--with-sysroot=E:\MinGW\opt\sysroot-arm ./configure ...

或者

export host_configargs=--with-sysroot=E:\MinGW\opt\sysroot-arm

./configure ...

后面的路径是你放在windows下的sysroot的位置。

目标 :编译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中!


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12380241.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存