Android NDK开发详解之NDK构建项目的方法

Android NDK开发详解之NDK构建项目的方法

使用 NDK 编译代码主要有三种方法:

基于 Make 的 ndk-build。

ndk-build的用法

Android NDKr4引入了一个新的、小巧的shell脚本ndk-build,

来简化源码编译。

该文件位于NDK根目录,

进入你的工程根目录或子目录之后,在命令行下调用即可。

例如:

复制代码
cd $PROJECT

$NDK/ndk-build

指向你的NDK的安装目录,PROJECT指向你的Android工程目录

几个常见调用方式如下:

ndk-build 编译

ndk-build clean 清掉二进制文件

ndk-build NDK_DEBUG=1 编译为可调试版的二进制文件

ndk-build NDK_DEBUG=0 编译为release版

ndk-build V=1 执行ndk-build且打印出它所执行的详细编译命令。

ndk-build -B 强制重新编译

ndk-build -B V=1 -B 和 V=1 的组合

ndk-build NDK_LOG=1 打印出内部的NDK日志信息(用于调试NDK自己)

ndk-build NDK_APP_APPLICATION_MK=<文件路径> 用这里指定的路径寻找Application.mk文件

ndk-build -C <project路径> 先cd进入<project路径>,然后执行ndk-build。

CMake。

CMake是一个跨平台的编译工具,它可以生成与平台无关的makefile、Visual Studio等项目文件,快速轻松地构建和管理代码。CMake支持多种编程语言,包括C++、Java、Python等,并广泛应用于开发各种软件项目,例如OpenGL、Qt、Boost等库。

Android Studio从2.2版本开始支持使用CMake编译C/C++库,开发者可以使用CMake管理项目,在NDK中编译、构建和测试他们的本地代码,以及让他们的C++代码更容易地与Java代码合作。

使用CMake构建Android项目

在Android Studio中,创建一个C++库工程时,会自动生成CMakeLists.txt文件。

复制代码
cmake_minimum_required(VERSION 3.4.1)

#定义变量
set(my_src_path ${CMAKE_SOURCE_DIR}/src/main/cpp)
set(my_lib_path ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})

#将目录下所有.cpp文件生成一个名为NativeFunc的库文件,并输出到libs目录下
add_library(NativeFunc SHARED
            ${my_src_path}/Add.cpp
            ${my_src_path}/Subtract.cpp
            ${my_src_path}/Multiply.cpp
            ${my_src_path}/Divide.cpp)

#导入log库
find_library(log-lib log)

#将libNativeFunc.so、log库打包到jniLibs目录下
target_link_libraries(NativeFunc ${log-lib})
set_target_properties(NativeFunc PROPERTIES
                      LIBRARY_OUTPUT_DIRECTORY ${my_lib_path})

在CMakeLists.txt中,首先设置一些变量,包括源码路径、静态库路径等;然后定义一个NativeFunc的共享库,并将所有.cpp源文件与它关联;最后链接log库、打包共享库到指定目录。

CMakeLists.txt的作用类似于Makefile,不同的是CMake可以跨平台生成不同类型的构建脚本。

使用CMake的高效方法

使用变量

在CMakeLists.txt中,使用变量可以方便地管理路径、文件等复杂的参数。

复制代码
set(my_src_path ${CMAKE_SOURCE_DIR}/src/main/cpp)
set(my_include_path ${CMAKE_SOURCE_DIR}/src/main/cpp/include)
set(my_lib_path ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})

在代码中使用已定义的变量,代码可读性大大提高,同时也有利于维护。

add_library(NativeFunc SHARED

${my_src_path}/Add.cpp

${my_src_path}/Subtract.cpp

${my_include_path}/Multiply.cpp

${my_include_path}/Divide.cpp)

使用函数

CMake提供一些函数库和宏,用于模块化的构建过程,例如字符串操作、文件操作、流控制等。

复制代码
#在头文件目录中寻找include文件夹
include_directories(${my_include_path})
#加入头文件转换函数(将.cpp文件转为.h文件)
function(convert_file_to_header file_name)
  get_filename_component(file_we ${file_name} NAME_WE)
  set(output_file "${my_include_path}/${file_we}.h")
  file(WRITE "${output_file}" "//在这里写你需要包含的.h头文件内容")
endfunction()
#调用convert_file_to_header函数,将Multiply.cpp转为Multiply.h
convert_file_to_header(${my_src_path}/Multiply.cpp)

通过引用函数库、定义函数等方式,可以在CMakeLists.txt中编写更加灵活的脚本,提高项目的可扩展性和可维护性。

定义参数

使用CMake,在构建Android项目时可以定义一些构建参数,例如定义编译器版本、CPU架构、编译选项等。这些参数可以在CMake脚本、源码中使用,方便地进行版本控制、多平台适配等工作。

复制代码
#设置编译器版本
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

#设置编译选项
add_compile_options(-Wall -Werror)

#设置CPU架构
if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon -mfloat-abi=softfp")
endif()

通过定义参数,可以规范化项目的构建工作,提高开发效率和项目质量。

独立工具链,用于与其他构建系统集成,或与基于 configure 的项目搭配使用。

您可以单独使用 Android NDK 附带的工具链,也可以将其作为插件与现有 IDE 结合使用。如果您已拥有自己的构建系统,并且只需要能够调用交叉编译器以便为其添加对 Android 的支持,这种灵活性就会非常有意义。

相关推荐
小bo波7 小时前
使用Thread子类创建线程 VS 使用Runnable接口创建线程的区别
java·多线程·thread·并发编程·runnable
SamDeepThinking8 小时前
高并发场景下,CompletableFuture与ForkJoinPool该如何取舍?
java·后端·面试
方白羽10 小时前
Android Gradle 缓存与文件目录深度解析
android·gradle·android studio
张不才11 小时前
CPU 100% 了怎么办?Java 性能排障的标准化操作
java·后端
shepherd11112 小时前
吞吐量提升 10 倍:高并发大批量数据处理任务的架构演进与性能调优
java·后端·架构
曲幽14 小时前
Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招!
android·termux·nohup·services·wake-lock
plainGeekDev15 小时前
单例模式 → object 声明
android·java·kotlin
程序员陆业聪15 小时前
读者点单·03|Compose 与传统 View 混用的 12 个真实坑
android
程序员陆业聪15 小时前
读者点单·02|Android 启动优化实战:Trace 抓取→Application 编排→冷启动全流程拆解
android
Coffeeee15 小时前
帮你快速理解AI Agent之我想招个Android实习生
android·人工智能·agent