如何在windows上用ndk交叉编译其他平台程序

如何在windows上用ndk交叉编译其他平台程序,第1张

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

在jni的c/c++层创建一个新的线程只需要3步:

1.导入库

#include<pthread.h>

2.写好线程要做的事

void* run_1(void*)

void* run_1(void* args){

...

}

3.调用方法

pthread_t thread_1

pthread_create(&thread_1,NULL,run_1,args)

NDK错误发生时,我们能拿到什么信息?

利用Android

NDK开发本地应用的时候,几乎所有的程序员都遇到过程序崩溃的问题,但它的崩溃会在logcat中打印一堆看起来类似天书的堆栈信息,让人举足无措。单靠添加一行行的打印信息来定位错误代码做在的行数,无疑是一件令人崩溃的事情。在网上搜索“Android

NDK崩溃”,可以搜索到很多文章来介绍如何通过Android提供的工具来查找和定位NDK的错误,但大都晦涩难懂。下面以一个实际的例子来说明,首先生成一个错误,然后演示如何通过两种不同的方法,来定位错误的函数名和代码行。

首先,看我们在hello-jni程序的代码中做了什么(有关如何创建或导入工程,此处略),看下图:在JNI_OnLoad()的函数中,即so加载时,调用willCrash()函数,而在willCrash()函数中, std::string的这种赋值方法会产生一个空指针错误。这样,在hello-jni程序加载时就会闪退。我们记一下这两个行数:在61行调用了willCrash()函数;在69行发生了崩溃。

下面来看看发生崩溃(闪退)时系统打印的logcat日志:

[plain] view

plain copy

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

Build fingerprint: 'vivo/bbk89_cmcc_jb2/bbk89_cmcc_jb2:4.2.1/JOP40D/1372668680:user/test-keys'

pid: 32607, tid: 32607, name: xample.hellojni >>>com.example.hellojni <<<

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000

r0 00000000 r1 beb123a8 r2 80808080 r3 00000000

r4 5d635f68 r5 5cdc3198 r6 41efcb18 r7 5d62df44

r8 4121b0c0 r9 00000001 sl 00000000 fp beb1238c

ip 5d635f7c sp beb12380 lr 5d62ddec pc 400e7438 cpsr 60000010

backtrace:

#00 pc 00023438 /system/lib/libc.so

#01 pc 00004de8 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#02 pc 000056c8 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#03 pc 00004fb4 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#04 pc 00004f58 /data/app-lib/com.example.hellojni-2/libhello-jni.so

#05 pc 000505b9 /system/lib/libdvm.so

#06 pc 00068005 /system/lib/libdvm.so

#07 pc 000278a0 /system/lib/libdvm.so

#08 pc 0002b7fc /system/lib/libdvm.so

#09 pc 00060fe1 /system/lib/libdvm.so

#10 pc 0006100b /system/lib/libdvm.so

#11 pc 0006c6eb /system/lib/libdvm.so

#12 pc 00067a1f /system/lib/libdvm.so

#13 pc 000278a0 /system/lib/libdvm.so

#14 pc 0002b7fc /system/lib/libdvm.so

#15 pc 00061307 /system/lib/libdvm.so

#16 pc 0006912d /system/lib/libdvm.so

#17 pc 000278a0 /system/lib/libdvm.so

#18 pc 0002b7fc /system/lib/libdvm.so

#19 pc 00060fe1 /system/lib/libdvm.so

#20 pc 00049ff9 /system/lib/libdvm.so

#21 pc 0004d419 /system/lib/libandroid_runtime.so

#22 pc 0004e1bd /system/lib/libandroid_runtime.so

#23 pc 00001d37 /system/bin/app_process

#24 pc 0001bd98 /system/lib/libc.so

#25 pc 00001904 /system/bin/app_process

stack:

beb12340 012153f8

beb12344 00054290

beb12348 00000035

beb1234c beb123c0 [stack]

……

如果看过logcat打印的NDK错误时的日志就会知道,省略了后面很多的内容,很多人看到这么多密密麻麻的日志就已经头晕脑胀了,即使是很多资深的Android开发者,在面对NDK日志时也大都默默的选择了无视。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/175178.html

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

发表评论

登录后才能评论

评论列表(0条)

    保存