通过 ndk-build编译ndk(二)

本文详细介绍了如何使用 Android NDK 进行 C/C++ 代码编译,包括定义 native 方法、生成 .so 文件、JNI 调用等步骤,并解决了常见错误问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:
NDK 编译的三种方式
Android Studio–NDK编译C代码为.so文件,JNI调用

我的demo地址

一、定义native方法:

    public native String getString();

二、编译生成字节码文件:

build、rebuild项目即可。

三、生成c头文件的方式:

javah命令主要用于在JNI开发的时,把java代码声明的JNI方法转化成(C、C++)头文件,以便进行JNI的C、C++端程序的开发。

方式一:

cd D:\Users\lenovo\Desktop\PonyMusic-master\MyNdkBuild\app\src\main

javah -d jni -classpath 
D:\Users\lenovo\Desktop\PonyMusic-master\MyNdkBuild\app\build\intermediates\classes\debug 
com.xq.myndkbuild.JniTest

注意 debug 后面是有个空格的

方式二:

cd D:\Users\lenovo\Desktop\PonyMusic-master\MyNdkBuild\app\build\intermediates\classes\debug

javah -d D:\Users\lenovo\Desktop\PonyMusic-master\MyNdkBuild\app\src\main\jni 
-jni com.xq.myndkbuild.JNIUtils

这两种方式的命令执行后会在 main 目录下(在哪个目录下执行就会在哪个目录下生成 .h 文件)自动生成 “jni” 文件夹,同时生成一个 .h 的文件

四、创建 Android.mk 、 Application.mk 和c/c++ 文件

在jni目录下添加 Android.mk 和 Application.mk 文件

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# 要生成的.so库名称,java代码System.loadLibrary("hello");加载的就是它
LOCAL_MODULE := hello
# c++文件
LOCAL_SRC_FILES := hello.cpp

include $(BUILD_SHARED_LIBRARY)

Application.mk

# APP_ABI := all
APP_ABI :=armeabi armeabi-v7a
APP_ABI := armeabi-v7a arm64-v8a
APP_PLATFORM := android-24
APP_CPPFLAGS := -fPIC -std=c++11 
APP_STL := c++_static
#APP_STL := c++_shared
APP_BUILD_SCRIPT := Android.mk

hello.cpp : (此文件名对应Android.mk的LOCAL_SRC_FILES )

#include "com_example_administrator_myndkdemo1_JniUtil.h"

extern "C"
JNIEXPORT jstring JNICALL Java_com_example_administrator_myndkdemo1_JniUtil_getString
        (JNIEnv *env, jobject ojb){
    return env->NewStringUTF("Hello, I'm from c++");
}

注意:
Java_com_example_administrator_myndkdemo1_JniUtil_getString名称要对应头文件里的名称。

五、编译

cmd 到 jni 目录下(先配置好NDK得环境变量)直接执行 ndk-build , 在lib中生成 .so 文件。

cd F:\2017122901_V1.1.8\2017122901_V1.1.8\MyNdkDemo1\app\src\main\jni

ndk-build

这里写图片描述

六、调用so库:

    static {
        System.loadLibrary("hello");
        //加载实现了native函数的动态库,只需要写动态库的名字
    }

问题一:

Error:Execution failed for task ':app:compileDebugNdk'.
> Error: Your project contains C++ files but it is not using a supported native build system.
Consider using CMake or ndk-build integration with the stable Android Gradle plugin:
 https://developer.android.com/studio/projects/add-native-code.html
or use the experimental plugin:
 https://developer.android.com/studio/build/experimental-plugin.html.

解决办法:

gradle.propertity中添加:

 android.useDeprecatedNdk=true

问题二:

Error:(81) Android NDK: Application targets deprecated ABI(s): mips64 armeabi mips    
Error:(82) Android NDK: Support for these ABIs will be removed in a future NDK release.    

解决办法:

删掉mips64的so文件夹。

问题三:

 FATAL EXCEPTION: main
 Process: com.example.administrator.myndkdemo1, PID: 5472
 java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[
	[zip file "/data/app/com.example.administrator.myndkdemo1-1/base.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_dependencies_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_0_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_1_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_2_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_3_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_4_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_5_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_6_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_7_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_8_apk.apk", 
	 zip file "/data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_9_apk.apk"],
	 nativeLibraryDirectories=[/data/app/com.example.administrator.myndkdemo1-1/lib/arm64,
	 /data/app/com.example.administrator.myndkdemo1-1/base.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_dependencies_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_0_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_1_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_2_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_3_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_4_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_5_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_6_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_7_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_8_apk.apk!/lib/arm64-v8a, 
	 /data/app/com.example.administrator.myndkdemo1-1/split_lib_slice_9_apk.apk!/lib/arm64-v8a, 
	 /system/lib64, /vendor/lib64, /system/vendor/lib64, /product/lib64]]] couldn't find "libhello.so"
	 at java.lang.Runtime.loadLibrary0(Runtime.java:989)
	 at java.lang.System.loadLibrary(System.java:1533)
	 at com.example.administrator.myndkdemo1.JniUtil.<clinit>(JniUtil.java:12)
	 at com.example.administrator.myndkdemo1.MainActivity.onCreate(MainActivity.java:14)
	 at android.app.Activity.performCreate(Activity.java:6910)
	 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
	 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2757)
	 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2875)
	 at android.app.ActivityThread.-wrap12(ActivityThread.java)
	 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1578)
	 at android.os.Handler.dispatchMessage(Handler.java:105)
	 at android.os.Looper.loop(Looper.java:156)
	 at android.app.ActivityThread.main(ActivityThread.java:6623)
	 at java.lang.reflect.Method.invoke(Native Method)
	 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
	 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

解决办法:

    sourceSets {
        main {
            //so文件放在libs时才使用
//            jniLibs.srcDirs = ['libs']	//没效果
			  jniLibs.srcDirs  'src/main/libs'	//使用这句
        }
    }
<think>我们正在解决在NDK编译过程中出现的`fatalerror:'cstddef'filenotfound`问题。根据用户描述和之前的引用,这个问题是在使用`ndk-build`编译时发生的。从引用[1]和引用[5]中可以看出,类似的头文件缺失问题(如`EGL/egl.h`或`iostream`)通常与NDK配置或标准库选择有关。##问题分析`cstddef`是C++标准库头文件,包含`std::size_t`等定义。该错误表明编译器在默认包含路径中找不到此文件。可能的原因包括:1.**NDK版本过旧**:旧版本可能不完整或配置错误。2.**标准库配置错误**:NDK支持多种C++标准库(如`system`、`gabi++`、`gnustl`、`libc++`),若未正确配置可能导致头文件缺失。3.**构建脚本配置错误**:`Android.mk`或`Application.mk`中未正确设置C++标准库或头文件路径。##解决方案###步骤1:确认NDK版本并更新使用较新NDK版本(如r21以上)以避免已知问题。检查NDK路径:```bashecho$ANDROID_NDK_HOME```或```bashndk-build--version```###步骤2:配置Application.mk选择标准库在`Application.mk`中明确指定使用`libc++`(推荐):```APP_STL:=c++_shared#或c++_staticAPP_CPPFLAGS:=-std=c++11#或更高标准```>`libc++`是NDKr18后唯一支持的C++标准库[^5][^4]。###步骤3:在Android.mk中添加标准库依赖确保`Android.mk`中链接了标准库:```makefileLOCAL_PATH:=$(callmy-dir)include$(CLEAR_VARS)LOCAL_MODULE:=mymoduleLOCAL_SRC_FILES:=main.cppLOCAL_CPP_FEATURES:=rttiexceptionsLOCAL_CPPFLAGS:=-std=c++11LOCAL_STATIC_LIBRARIES:=c++_static#若使用静态库#或LOCAL_SHARED_LIBRARIES:=c++_sharedinclude$(BUILD_SHARED_LIBRARY)$(callimport-module,cxx-stl/llvm-libc++/static)#静态库示例```###步骤4:检查头文件包含路径查询`cstddef`在NDK中的位置(假设NDK路径为`~/Android/Sdk/ndk/21.0.6113669`):```bashfind~/Android/Sdk/ndk/21.0.6113669-namecstddef```输出应类似:```~/Android/Sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/c++/v1/cstddef```###步骤5:若路径缺失,手动添加包含路径在`Android.mk`中显式添加标准库路径:```makefileLOCAL_C_INCLUDES+=$(NDK_ROOT)/sources/cxx-stl/llvm-libc++/includeLOCAL_C_INCLUDES+=$(NDK_ROOT)/sources/cxx-stl/llvm-libc++abi/include```###步骤6:清理并重新构建```bashndk-buildcleanndk-buildNDK_DEBUG=1V=1#输出详细日志```##验证修复创建测试文件`main.cpp`:```cpp#include<cstddef>intmain(){returnsizeof(std::size_t);}```编译:```bashndk-buildAPP_ABI=armeabi-v7a```##常见问题排查1.**多NDK版本冲突**:确保`ndk-build`命令来自正确版本。2.**构建脚本路径错误**:确保`Android.mk`在`jni`目录下(或通过`NDK_PROJECT_PATH`指定)[^3]。3.**标准库兼容性**:确保所有依赖库使用相同标准库(如避免混用`gnustl`和`libc++`)[^5]。##相关问题§§相关问题§§1.NDK中如何切换不同版本的C++标准库?2.使用CMake构建NDK项目时如何指定`libc++`?3.NDK编译出现`undefinedreferenceto`std::__ndk1::xxx`错误如何解决?</think> 针对 NDK (`ndk-build`) 编译时出现的 **`fatal error: 'cstddef' file not found`** 错误,以下是系统化的解决方案,结合 NDK 开发特性和您的引用信息整理: --- ### 🔧 核心解决方案(分三步操作) #### ✅ 步骤 1:检查 NDK 标准库配置 在 `Application.mk` 中明确指定 **C++ 标准库**(如 `libc++`): ```bash # Application.mk APP_STL := c++_shared # 推荐动态库(或 c++_static) APP_CPPFLAGS := -std=c++17 # 明确 C++ 标准版本 ``` > 📌 **关键点**: > - NDK r18+ 后默认移除 `gnustl`,必须使用 `libc++`(引用 [5] 中 `gnustl_static` 已过时) > - 若未配置 `APP_STL`,默认使用残缺的 `system` 库导致头文件缺失 #### ✅ 步骤 2:验证 NDK 路径与完整性 通过终端检查 NDK 是否包含 `cstddef` 头文件: ```bash # Linux/Mac find $ANDROID_NDK_HOME -name 'cstddef' # Windows(Powershell) Get-ChildItem -Path $env:ANDROID_NDK_HOME -Recurse -Filter 'cstddef' ``` ➤ **预期输出示例**: `.../toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/c++/v1/cstddef` 若未找到,说明 NDK 安装不完整或版本过低(需升级到 **NDK r21+**)。 #### ✅ 步骤 3:在 `Android.mk` 中显式添加库路径 在 `Android.mk` 添加标准库头文件路径: ```makefile # Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := mylib LOCAL_SRC_FILES := main.cpp LOCAL_CFLAGS += -I$(NDK_ROOT)/sysroot/usr/include/c++/v1 # ✅ 关键:添加 libc++ 路径 LOCAL_LDLIBS += -lc++_shared # 链接动态库 include $(BUILD_SHARED_LIBRARY) ``` --- ### 🛠 进阶修复(当基础步骤无效时) #### 🔄 场景 1:NDK 版本兼容性问题 ```bash # 查看当前 NDK 版本 ndk-build --version # 升级到最新 NDK(使用 sdkmanager) sdkmanager --install "ndk;25.1.8937393" ``` #### 🔄 场景 2:头文件被错误覆盖(如 AOSP 冲突) 若项目包含 AOSP 本地代码(如 `frameworks/native`),在 `Android.mk` 中添加优先级路径: ```makefile LOCAL_CFLAGS += \ -I$(NDK_ROOT)/sysroot/usr/include/c++/v1 \ # NDK 路径在前 -Ipath/to/aosp/frameworks/native/include # AOSP 路径在后 ``` #### 🔄 场景 3:CMake 混合编译配置错误 在 `build.gradle` 中为 CMake 添加标志: ```gradle android { externalNativeBuild { cmake { cppFlags "-I${NDK_PATH}/sysroot/usr/include/c++/v1" # ✅ 路径替换为实际值 arguments "-DANDROID_STL=c++_shared" } } } ``` > 注:CMake 与 `ndk-build` 选一(引用 [2] 中者不能共存) --- ### 🧪 验证修复效果 创建测试文件 `test.cpp`: ```cpp #include <cstddef> // 必须无报错 #include <iostream> // 验证其他标准库 int main() { std::cout << sizeof(std::size_t); } ``` 编译命令: ```bash ndk-build APP_ABI=arm64-v8a V=1 # 输出详细日志 ``` ✅ **成功标志**:生成 `obj/local/arm64-v8a/*.so` 且无编译错误。 --- ### ⚠️ 注意事项 1. **NDK 路径规范**: Linux/Mac 用 `$ANDROID_NDK_HOME`,Windows 用 `%ANDROID_NDK_HOME%` 2. **清理缓存**:每次修改配置后执行: ```bash ndk-build clean && rm -rf obj/ libs/ ``` 3. **Gradle 同步**:Android Studio 中点击 **File > Sync Project with Gradle Files** --- ### 🔍 相关扩展问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值