linux下搭建ndk环境编译c++库给安卓使用,ndk编译c++程序,不使用Jni

本文介绍在Windows 10环境下,通过Ubuntu 22.04使用Android NDK r24编译FFmpeg 5.1的过程。详细展示了如何配置NDK路径、平台、工具链等参数,并通过CMake进行编译。最终生成适用于ARM架构的可执行程序。

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

Unsupported Downloads · android/ndk Wiki · GitHub

window 10 下安装 Ubuntu 22.04 使用 NDK r24 编译FFmpeg 5.1 - 简书 (jianshu.com)

下载完ndk r24后,编写build.sh,执行

#!/bin/bash

BASEPATH=../

NDKPATH=/home/sunsy/ndk/android-ndk-r24
#NDKPATH=/d/androidsdk/ndk/21.0.6113669/

CMAKEPATH=/usr/bin
#CMAKEPATH=/d/androidsdk/cmake/3.22.1/bin

PLATFORM=arm64-v8a

#BUILDTYPE=Debug
#	-DCMAKE_BUILD_TYPE=${BUILDTYPE} \

${CMAKEPATH}/cmake \
	-DCMAKE_TOOLCHAIN_FILE=${NDKPATH}/build/cmake/android.toolchain.cmake \
	-DANDROID_ABI=${PLATFORM} \
	-DANDROID_NDK=${NDKPATH} \
	-DANDROID_NATIVE_API_LEVEL=31 \
	-DANDROID_PLATFORM=android-31 \
	-DANDROID_STL=c++_shared \
	-DNDK_PATH=${NDKPATH} \
	-DANDROID_TOOLCHAIN=clang \
	-DCMAKE_INSTALL_PREFIX=${BASEPATH}/out/ \
	${BASEPATH}

#make
#make VERBOSE=1
#make install


然后,make 编译出来的就是arm 可执行程序.

参考链接

MSM8916 海信M9模块学习记录四:ubuntu16.04 64位下配置NDK-r16b_tudouniS的博客-CSDN博客

(676条消息) android .vsh文件是什么,在Android9下用ndk编译vSomeIP和CommonAPI以及使用例子_小小牵牛星的博客-CSDN博客

官网下载ndkr16b

Unsupported Downloads · android/ndk Wiki · GitHub

解压完以后放到/opt目录下

vim /etc/profile

export NDK_HOME=/opt/android-ndk-r16b  #(就是解压出来之后的文件夹路径,这里是要改的)
export PATH=$PATH:$NDK_HOME

source /etc/profile

ndk-build -v 

https://www.cnblogs.com/guanglun/p/9340079.html

export PATH=/opt/android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin:$PATH

arm-linux-androideabi-gcc -pie -fPIE --sysroot=/home/guanglun/workspace/rk3399/android-ndk-r13b/platforms/android-24/arch-arm -o hello hello.c

执行失败

先生产工具链cd /opt/android-ndk-r16b

# build/tools/make-standalone-toolchain.sh --toolchain=arm-linux-androideabi-4.9 --platform=android-21 --install-dir=../android-toolchain-r16b/android-armv7 --arch=arm
HOST_OS=linux
HOST_EXE=
HOST_ARCH=x86_64
HOST_TAG=linux-x86_64
HOST_NUM_CPUS=3
BUILD_NUM_CPUS=6
Toolchain installed to ../android-toolchain-r16b/android-armv7.
root@deyi-virtual-machine:/opt/android-ndk-r16b# 
cd /opt/android-toolchain-r16b/android-armv7

export PATH=/opt/android-toolchain-r16b/android-armv7/bin:$PATH
export SYSROOT=/opt/android-toolchain-r16b/android-armv7/sysroot

arm-linux-androideabi-gcc -pie -fPIE --sysroot=$SYSROOT -o hello hello.c
编译成功

参考例子

GitHub - MingHuang1024/CrossCompileForAndroid: 使用独立工具链交叉编译可在android系统中运行的so包

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")

# Android 5.0 以上需要在此处设置 PIE
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")

# 配置使用 NDK Standalone Toolchain 编译
set(NDK_STANDALONE_TOOLCHAIN /tmp/ndk-hm/arm-linux-androideabi)
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 21)
set(CMAKE_C_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/clang)
set(CMAKE_CXX_COMPILER ${NDK_STANDALONE_TOOLCHAIN}/bin/clang++)
set(CMAKE_FIND_ROOT_PATH ${NDK_STANDALONE_TOOLCHAIN})

# 使用 NDK 提供的头文件
add_definitions("--sysroot=${NDK_STANDALONE_TOOLCHAIN}/sysroot")

add_library(myso SHARED CTest.c)

set_target_properties(myso
                      PROPERTIES
                      LIBRARY_OUTPUT_DIRECTORY
                      "${CMAKE_CURRENT_SOURCE_DIR}/lib")

include_directories(/home/hm/JDK/jdk1.8.0_151/include /home/hm/JDK/jdk1.8.0_151/include/linux)

target_link_libraries(myso
                     log)

NDK/build/tools/make-standalone-toolchain.sh  --platform=android-23  --arch=arm64   --ndk-dir=/home/chengli/SoftWare/NDK/android-ndk-r12b  --install-dir=/home/name/SoftWare/NDK/android-ndk-r12b/tmp/toolchain

<think>首先,用户在询问如何在Linux环境使用CMake和NDK编译AndroidJNIC++静态。这意味着我需要提供一步一步的指导。系统级指令:-所有内联数学表达式必须使用$...$,但在这个上下文中,没有数学表达式,所以可能需要担心。-独立公式必须用$$...$$单独成段,但这里也没有数学内容。-LaTeX语法正确:在回答中,我使用LaTeX,所以没问题。-使用中文回答。-生成相关问题。-回答中引用的段落末尾自然地添加引用标识,如[^1]。参考提供的引用:-引用[1]:Linux下用NDK编译C程序使用JNI。示例命令是用gcc直接编译。-引用[2]:Windows下用CMake和NDK编译.so和.a,涉及JNI头文件。-引用[3]:Linux下用CMake交叉编译Android动态,给出了一个脚本示例。-引用[4]:指向Android官方文档关于NDK编译和CMake的链接。用户的明确查询是:如何在Linux下用CMake和NDK编译AndroidJNIC++静态。静态是.a文件,而是.so动态。关键点:-静态文件扩展名是.a。-JNI意味着代码需要与Java交互,所以需要JNI头文件。-使用CMake和NDKLinux上。从引用中提取相关信息:-引用[3]提供了一个脚本用于使用CMake在Linux上为Android构建动态。我可以修改它以适用于静态。-引用[4]是官方文档,我应该在回答中引用它,因为它是权威来源。-JNI部分,引用[2]显示了JNI方法的例子,所以我可以参考它。结构化回答:1.**引言**:简要介绍主题。2.**先决条件**:列出所需的工具(NDK、CMake等)。3.**步骤**:-设置环境。-创建CMakeLists.txt文件用于静态。-运行CMake配置。-构建。4.**示例**:提供一个简单的例子,包括代码和脚本。5.**引用官方文档**:参考[^4]作为主要资源。6.**生成相关问题**:在最后添加相关的问题。确保回答使用中文:-整个回答必须用中文撰写。引用标识:-当提到官方文档或其他引用时,添加[^4]之类的内容。步骤的详细内容:-**先决条件**:-Linux系统。-安装AndroidNDK(下载并解压)。-安装CMake(如果尚未安装)。-**目录结构**:建议组织项目目录。-**CMakeLists.txt**:为静态配置。CMake默认构建共享,所以需要指定为静态。-**编译脚本**:类似于引用[3],但针对静态。修改引用[3]的脚本以构建静态:-在CMakeLists.txt中,使用`add_library(mylibSTATICsource.cpp)`而是`SHARED`。JNI方面:-由于是静态用于JNI,代码需要包含JNI头文件,并在构建时确保正确路径。-在CMake中,使用`find_package`或其他方式包含NDK的工具链。官方文档(引用[4]):-链接到https://developer.android.google.cn/ndk/guides/cmake描述CMake的使用。最终回答结构:1.介绍:解释使用CMake和NDK编译静态的方法。2.先决条件。3.步骤:a.创建项目目录和源文件。b.编写CMakeLists.txt。c.编写编译脚本。d.运行脚本。4.示例代码和脚本。5.参考官方文档[^4]。6.生成相关问题。生成相关问题:-在回答结束后,添加相关的问题,像在系统指令中的示例。相关问题示例:1.如何优化CMake配置以减少编译时间?2.静态与动态Android中的优缺点是什么?3.如何处理JNI方法签名和错误?确保语言自然且有帮助性。</think> 以下是如何在 Linux 环境使用 CMake 和 Android NDK 编译 Android JNI C++ 静态(文件扩展名通常为 `.a`)的完整指南。我会基于您的需求(编译静态而非动态)和提供的引用(特别是引用[3]和[4]的官方推荐方法)提供详细步骤。整个流程分为三个部分:**先决条件准备**、**编译步骤详解**和**示例实现**。最终生成的静态可用于 JNI 接口,但请注意,静态本身直接暴露 JNI 方法;它需被链接到共享(`.so`)或应用中调用。 参考核心资源:Android NDK 官方文档是编译 JNI/C++ 的权威指南,建议优先参考其 CMake 部分[^4]。同时,我会结合引用[3]的 Linux 环境脚本思路,针对静态定制化流程。 --- ### **先决条件准备** 在开始编译前,请确保您的 Linux 系统(如 Ubuntu)已安装以下工具: 1. **Android NDK**:下载最新版本(例如 r25b)并解压到路径如 `~/Android/ndk`。官方推荐使用 NDK 的 CMake 工具链。 - 下载地址:[Android NDK 官方网站](https://developer.android.google.cn/ndk/downloads)[^4]。 2. **CMake**:版本需 ≥ 3.10,安装命令: ```bash sudo apt-get install cmake ``` 3. **基础开发工具**:如 GCC、Make(通常预装于 Linux)。 4. **Java 环境**:可选,但建议安装 OpenJDK 以支持 JNI 头文件(JNI 接口需要 `jni.h`)。 > 提示:静态编译无需 Java 运行时,但 JNI 代码需包含 NDK 提供的 JNI 头文件(位于 `ndk/sysroot/usr/include/jni.h`),CMake 会自动处理路径。 --- ### **编译步骤详解(针对 JNI C++ 静态)** 以下是标准流程,基于 CMake 配置静态构建。关键点: - 使用 `add_library(... STATIC)` 指定类型为静态。 - 配置 CMake 工具链文件(`.cmake`)实现交叉编译。 - 脚本基于引用[3]修改,专为静态优化。 #### **步骤 1:创建项目目录结构** 在 Linux 终端执行: ```bash mkdir -p jni-static-lib/src # 存放 C++ 源码 mkdir -p jni-static-lib/build # 构建目录 cd jni-static-lib ``` - 在 `src/` 下创建 C++ 文件(如 `jni_lib.cpp`),编写 JNI 相关代码(见下方示例)。 #### **步骤 2:编写 CMakeLists.txt** 在项目根目录创建 `CMakeLists.txt` 文件,内容如下: ```cmake cmake_minimum_required(VERSION 3.10) project(AndroidJNIStaticLib) # 添加静态目标:关键为 STATIC 关键字 add_library(jni_static_lib STATIC src/jni_lib.cpp ) # 设置 JNI 头文件路径(NDK 自动包含) target_include_directories(jni_static_lib PRIVATE ${ANDROID_NDK}/sysroot/usr/include ) # 其他编译选项(可选) set_target_properties(jni_static_lib PROPERTIES CXX_STANDARD 11 OUTPUT_NAME "jni_static" # 输出文件名为 libjni_static.a ) ``` 说明: - `add_library(... STATIC)`:声明静态(动态应为 `SHARED`)。 - `target_include_directories`:确保 JNI 头文件(`jni.h`)被正确包含,NDK 路径由 CMake 自动解析。 - 更多 CMake 配置请参考官方文档[^4]。 #### **步骤 3:创建编译脚本(Shell Script)** 在项目根目录创建 `build.sh` 脚本,内容基于引用[3]修改: ```bash #!/bin/bash # 清除旧构建并创建 build 目录 rm -rf build mkdir build cd build # 设置 NDK 路径(根据您的安装修改) export ANDROID_NDK_HOME=~/Android/ndk/android-ndk-r25b # 替换为您的 NDK 路径 # 使用 CMake 配置交叉编译工具链 cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ -DANDROID_ABI=arm64-v8a \ # 指定 CPU 架构,可选 armeabi-v7a -DANDROID_NATIVE_API_LEVEL=24 \ # 最低 API 级别 -DCMAKE_BUILD_TYPE=Release \ # 编译类型:Release 或 Debug -DBUILD_SHARED_LIBS=OFF \ # 关键:禁用共享,强制静态 .. # 开始编译 make ``` 运行脚本: ```bash chmod +x build.sh ./build.sh ``` 说明: - `-DBUILD_SHARED_LIBS=OFF`:强制构建静态(引号中 OFF 表示关闭共享选项)。 - `-DANDROID_ABI`:指定目标架构(如 `arm64-v8a` 或 `armeabi-v7a`)。 - 编译成功后,静态文件 `libjni_static.a` 会出现在 `build/` 目录。 - 参考引用[3]的脚本思想,实现标准化构建[^3]。 #### **步骤 4:验证静态** 在终端检查输出: ```bash ls build/libjni_static.a file build/libjni_static.a # 应显示 ELF 格式的静态文件 ``` - 生成的静态可直接被 Android 共享(`.so`)或应用链接,用于 JNI 调用。 > 提示:静态本身JNI 运行时逻辑,但代码需遵循 JNI 规范。JNI 方法在应用层实现调用关系(参考引用[2]的 JNIEXPORT 示例)[^2]。 --- ### **完整示例实现** 假设您要编译一个简单的 JNI 静态,用于加法计算。以下是关键文件: - **`src/jni_lib.cpp`**:JNI C++ 源码。 ```cpp #include <jni.h> // JNI 头文件 // JNI 方法实现(静态直接暴露 JNI 方法,但代码可包含) jint add_numbers(JNIEnv* env, jclass clazz, jint a, jint b) { return a + b; // 简单加法逻辑 } ``` - **项目目录结构**: ``` jni-static-lib/ ├── CMakeLists.txt ├── build.sh ├── build/ # 运行后生成 └── src/ └── jni_lib.cpp ``` - **运行 `./build.sh` 后输出**:`build/libjni_static.a`(静态文件)。 #### **如何使用生成的静态** - 将 `libjni_static.a` 添加到 Android Studio 项目的 `jniLibs/` 目录。 - 在共享(`.so`)或应用的 CMake 中链接: ```cmake target_link_libraries(native-lib jni_static_lib) # 在共享 CMakeLists.txt 中添加 ``` - 然后通过 Java/Kotlin JNI 接口调用(方法签名需匹配,参考引用[2]示例)[^2]。 官方完整教程请参考:[Android NDK CMake 指南](https://developer.android.google.cn/ndk/guides/cmake)[^4]。 --- ### **常见问题与优化建议** - **问题:编译失败提示 "jni.h not found"** - 解决方案:确保 `CMakeLists.txt` 中正确包含 NDK 路径(如 `${ANDROID_NDK}/sysroot/usr/include`)。 - **问题:静态未生成** - 检查 `-DBUILD_SHARED_LIBS=OFF` 是否设置正确。 - **性能优化**: - 在 `CMakeLists.txt` 中启用 LTO(链接时优化):添加 `-DANDROID_LTO=thin` 到构建脚本。 - 为减少代码大小,使用 `-Oz` 编译选项(在 `CMakeLists.txt` 中设置 `target_compile_options(jni_static_lib PRIVATE -Oz)`)。 --- ### **相关问题(基于本主题扩展)** 1. **如何在 CMake 中指定特定 Android CPU 架构以优化性能?** 2. **静态(.a)与动态(.so)在 Android JNI 开发中有何优缺点比较?** 3. **如何处理 JNI 方法签名匹配导致的运行时错误?参考引用[2]的示例结构。** 4. **如何将生成的静态集成到 Android Studio 项目中并与 Java 层交互?** 如果需要更深入的场景扩展或代码调试,请提供具体细节!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值