linux 交叉编译工具中没有libc和liblog库文件,NDK无法找到动态链接库;动态链接库找不到依赖的gcc库;JNI中无法找到要注册的类;and so on...
这是一篇头一次做NDK开发,记录了踩坑,杂乱无章的错误记录,仅供参考.
待解决Android运行NDK程序无法加载库,无法找到库,缺失库文件,找不到c库,导致我的Android NDK程序直接崩溃退出,,经过一番侦查发现,通过file获知,我们使用的gcc编译,搞错了编译工具链,使用arm工具链编译,OK,这个问题解决,然后由弹出找不到libgcc_s.so.1,好嘛,C库缺失,很显然,我拷贝一个C库过去就好了
首先从之前制作好的最小根文件系统中提取出libgcc_s.so.1这个库文件,然后使用ADB,
ADB shell
将文件推入
adb push ./libgcc_s.so.1 /system/lib/
``
这里,它提示我们这是只读文件系统
A:\Users\defenion\Desktop\ARM练习\FASTBOOT>adb push ./libgcc_s.so.1 /system/lib/
failed to copy './libgcc_s.so.1' to '/system/lib//libgcc_s.so.1': Read-only file system
我们通过重新挂载解决它
1|root@android:/ # mount -o remount,rw /dev/null /system
[ 1499.316842] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
Ok 看样子是挂载成功
然后重新将我们从linux根文件系统中提取出来的C库push进去
A:\Users\defenion\Desktop\ARM练习\FASTBOOT>adb push ./libgcc_s.so.1 /system/lib/
6792 KB/s (69371 bytes in 0.009s)
然后再次启动我们的Android APP,在Android Studio 的ADB信息中看到 错误依旧
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]: 1295 could not load needed library 'libgcc_s.so.1' for 'libhardcontrol.so' (link_image[1936]: 1295 could not load needed library 'libc.so.6' for 'libgcc_s.so.1' (load_library[1091]: Library 'libc.so.6' not found))
注意,这句是重点,是因为libc.so.6导致我们不能加载刚才导入的libgcc_s.so.1库文件,
could not load needed library 'libc.so.6' for 'libgcc_s.so.1'
看来还需要将 libc.so.6 导入 ,显然啊 ,这是C系的库都没有包含,,,,并且shell中还有很多常用的sh命令被删除了,
待解决~ ! 搁置 20200106 20:18
目前看来最简单的解决办法是将Linux最小根文件系统中的C库全部copy进来
这个也很是诡异,之前使用eclipse从未出现过这种问题,使用Android Studio.就遇见了缺少依赖的动态链接库.暂不探究.
对比下他们的文件信息
```
他们同为ARM交叉编译工具链编译出来的
root@ubuntu:/mnt/hgfs/ubuntu# file *.so
之前使用eclipse时使用的NDK库,没有任何问题
libled.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, stripped
这次出问题的NDK库,使用Android Studio
libnative.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, not stripped
有区别,( ′◔ ‸◔`),,我们再次找到了线索
> 探究 `stripped`与`not stripped` ,以及`将Linux最小根文件系统中的C库全部copy进来`这个方法.
正常版本是通过NDK编译工具链编译出来的,出错的版本是通过GCC手动指定参数进行编译的
NDK编译工具链
`root@ubuntu:/usr/local/ndk/android-ndk-r8b# vim ndk-build`这东西是一个脚本,本质上依然是调用ARM-GCC进行的交叉编译.
### 关于`stripped`与`not stripped`
用file命令查看文件信息的时候,显示如下:
libcom_err.so.2: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped
libcrypto.so.10: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped
libcrypt.so.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
libc.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
libdl.so.2: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
第一个最后显示的是stripped,第二个是not stripped。而且对于同样名字的动态库,带not stripped库会大很多。
参考`elf文件格式与动态链接库`博客
a.out和elf(Executable and Linking Format)。这两种格式中都有符号表(symbol table),其中包括所有的符号(程序的入口点还有变量的地址等等)。在elf格式中符号表的内容会比a.out格式的丰富的多。但是这些符号表可以用 strip工具去除,这样的话这个文件就无法让debug程序跟踪了,但是会生成比较小的可执行文件。a.out文件中的符号表可以被完全去除,但是 elf中的在加载运行时起着重要的作用,所以用strip永远不可能完全去除elf格式文件中的符号表。但是用strip命令不是完全安全的,比如对未连接的目标文件来说如果用strip去掉符号表的话,会导致连接器无法连接。
---
回过头来,我们接着尝试解决刚才提到的问题
* 尝试1
> 既然使用NDK编译工具链编译成功了,那我们也使用一下这个编译工具链,康康是否可行
参考以前的NDK笔记
需要编译的文件,在目录“ledtest\jni”中
–Android.mk(编译脚本)
–com_topeet_ledtest_led.c
–com_topeet_ledtest_led.h
•拷贝文件夹“jni”到Ubuntu系统,,,,(JNI文件夹为 调用底层驱动的接口)
进入jni目录执行 ndk-build编译
•编译完成后,在Ubuntu目录“../” -->“libs”-->“armeabi”中生成库文件“libled.so”,该文件就是安卓应用程序中需要的“.so”文件。
•将该文件拷贝到工程ledtest的“\libs\armeabi”目录下,库文件的编译就全部完成了。
注:这个NDK编译工具链是Android文件系统中自带的工具之一.
我们需要先建立Android.mk文件
在我们拷贝的jni文件中建立一个Andoird.mk文件 ,输入如下内容
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hardcontrol
LOCAL_SRC_FILES := native.c
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS +=-lm
include $(BUILD_SHARED_LIBRARY)
第三行是编译出来的文件的名称`libxxxx.so`,第四行是我们源文件名称
编译,
root@ubuntu:~/yizhi/jni# ndk-build
Compile thumb : hardcontrol <= native.c
SharedLibrary : libhardcontrol.so
Install : libhardcontrol.so => libs/armeabi/libhardcontrol.so
生成在上层libs目录中,`../libs/armeabi/libhardcontrol.so`
放入我们的工程中,然后用前面的方法push到android的`system/lib`目录下,我们在测试
libhardcontrol.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, stripped
这回这个和以前未出过依赖gcc库问题的库文件一样了都是剥离了符号表的stripped类型 测试!
在虚拟机上跑一下,不出所料,程序依旧崩溃退出.但是显然我们解决了这个问题,错误信息中没有提示找不到我们加载的库文件
报错信息:
Caused by: java.lang.NoClassDefFoundError: HardControl
Caused by: java.lang.ClassNotFoundException: HardControl
显然,我们的库文件成功的加载了,但是没有找到我们在C文件中指定注册的类.
使用其他的NDK库加载成功,可能是JAVA类和C指定的某些地方不匹配,暂定
static {
Log.d("AAA","AAAAAAAAA");
System.loadLibrary("adc");
}
使用其他的NDK测试成功,成功,成功的原因是这个C库中没有尝试使用
` cls = (*env)->FindClass(env, "HardControl");`这句代码
暂定 20200107 21:09
在自用的安卓手机,Android 7上测试 ,提示出了稍有区别的错误,但是本质上是一样的问题,都是找不到类
01-08 13:45:05.447 29811-29811/? A/DEBUG: Abort message: 'art/runtime/java_vm_ext.cc:470] JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.ClassNotFoundException: Didn't find class "HardControl" on path: DexPathList[[zip file "/data/app/com.example.ratherdog.app_addons_0001_message-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.ratherdog.app_addons_0001_message-1/lib/arm, /system/fake-libs, /data/app/com.example.ratherdog.app_addons_0001_message-1/base.apk!/lib/armeabi, /system/lib, /vendor/
试了直接指定其他类也不行,加上包名,OKay,可以找到我们需要的类HardControl了
JNI注册类是这么写就OK
jclass cls = (*env)->FindClass(env, "com/thisway/hardlibrary/HardControl");
一定要指定包名 ,
接下来,继续报错
java.lang.NoSuchMethodError: no static or non-static method "Lcom/thisway/hardlibrary/HardControl;.ledCtrl(I)I"
错误的地点java
public class HardControl{
public static native int ledCtrl(int which,int status);
public static native int ledOpen();
public static native void ledClose();
//加载hardcontrol这个名字的C库,这种静态写法是加载C库的标准写法,因为static内的代码只能被执行一次,并且在类创建实例的时候最先执行
//static方法只执行一次,最先执行,适合用于加载库,
static {
try {
System.loadLibrary("hardcontrol");
} catch (Exception e) {
e.printStackTrace();
}
}
}
找不到这样的方法是把`ledCtrl(I)I`c
static const JNINativeMethod methods[] = {
{"ledOpen", "()I", (void )ledOpen},
{"ledClose", "()V", (void)ledClose},
{"ledCtrl", "(I)I", (void *)ledCtrl},
};
显然这里面写的不匹配.` {"ledCtrl", "(I)I", (void *)ledCtrl},`这里一个参数,java中两个参数
改为
{"ledCtrl", "(II)I", (void *)ledCtrl},
```
测试
在KindleFire HD 10中测试,Android4.4.4,通过,在虚拟机中测试通过,在魅蓝Note6,Andoird中测试通过,
完美解决 !
linux 交叉编译工具中没有libc和liblog库文件,NDK无法找到动态链接库;动态链接库找不到依赖的gcc库;JNI中无法找到要注册的类;and so on...相关推荐
- linux top交叉编译_ARM Linux交叉编译工具链的制作
本次是在VMWare虚拟机里安装了CentOS5.2操作系统,并在上面编译自己的ARM交叉编译工具链,下面是相应的步骤: 首先下载crosstool0.43源码包(crosstool-0.43.tar ...
- ubuntu linux 交叉编译工具安装以方便查看
ps该方法是正点原子的教程,相关资料可以去正点原子官方下载. 1.在linux下创建文件目录 mkdir tool 2`.H:\linux\[正点原子]阿尔法Linux开发板(A盘)-基础资料\[正点 ...
- arm hisiv100 linux,hisiv100交叉编译工具链安装
hisi交叉编译工具链安装 一. 摘要: 交叉编译简单的说,就是A机器上编译生成,运行在B机器上.那么在A机器上的编译工具安装,就是本文所要描述的内容. 工欲善其事必先利其器,所以交叉 ...
- hisi linux nptl.tar,hisiv100交叉编译工具链安装
hisi交叉编译工具链安装 一. 摘要: 交叉编译简单的说,就是A机器上编译生成,运行在B机器上.那么在A机器上的编译工具安装,就是本文所要描述的内容. 工欲善其事必先利其器,所以交叉 ...
- linux搭建交叉编译器,手把手教你一步一步搭建mips-linux-gcc-4.4.0交叉编译工具
一.准备工作: 工作环境:宿主机:ubuntu10.04 linux-2.6.32-24-generic i686 gcc-4.4.3 目标机:mips32 软件包版本:binutils-2.19.1 ...
- 搭建powerpc交叉编译工具链
参考文档:http://blog.sina.com.cn/s/blog_70dd16910100y7vj.html 安装环境:fedora-31 1.下载安装包 1.1 GCC软件包:http://f ...
- Linux 交叉编译简介
Linux 交叉编译简介 主机,目标,交叉编译器 主机与目标 编译器是将源代码转换为可执行代码的程序.像所有程序一样,编译器运行在特定类型的计算机上,输出的新程序也运行在特定类型的计算机上. 运行编译 ...
- 使用 Android NDK 的交叉编译工具链移植 C/C++ 项目到安卓平台
什么是 NDK? Android NDK 是一套可以让开发者在安卓应用开发中使用 C/C++ 实现特定模块的工具集,不是所有应用都需要用到,但是正确地使用可以有效提高应用运行效率和安全性. 为什么要在 ...
- linux 编译工具链,Linux工具链for TKStudio下载_Linux工具链for TKStudio官方下载-太平洋下载中心...
Linux工具链for TKStudio是一款支持TKStudio IDE集成开发环境的辅助LINUX交叉编译工具链软件,交叉编译就是跨架构编译,编译出来的程序不能在本机执行(当然有例外情况).所以这 ...
最新文章
- 技术人生:本周改进计划
- 华为云携手秒拍,云+AI助力短视频加速发展
- 匹兹堡大学申请条件计算机科学,匹兹堡大学cs
- 伦敦大学金史密斯学院计算机专业,伦敦大学金史密斯学院 Goldsmiths, University of London...
- html 元素的属性
- 大学物理实验长度的测量实验报告_大学物理实验教案长度和质量的测量两篇
- 关于字节对齐以及内存占用
- iLogtail使用入门-K8S环境日志采集到SLS
- mGBA-0.9.2 免费开源的gba模拟器
- matlab匹配滤波器的仿真
- Java获取压缩包内文件数_java获取递归获取嵌套压缩包(zip和rar)中的所有文件
- jQuery获取屏幕宽度和高度
- Go的WaitGroup源码分析
- 苹果M1 Mac 如何卸载 iPhone 和 iPad 应用程序?
- Oracle select表要带双引号的原因
- GreenPlum 大数据平台--segment 失效问题恢复
- 一种与生活周旋的能力
- 考研《软件工程--面向对象和传统的方法》复习笔记
- layui框架入门篇
- 如何使用ChatGPT帮助孩子辅导作业?