我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Cmake学习记录(九)--使用Cmake交叉编译Android .so库

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Cmake学习记录(九)--使用Cmake交叉编译Android .so库

文章目录

一、前言

注意:本教程没有关于JNI接口的写法,只是把C代码编译成适合android平台的so库,想查看完整代码可以参考文末的第9条参考链接
目前Android编译.so的话使用Android Studio比较简单,但是有时候时候Android Studio的话还需要创建一个Android的项目,这里记录下脱离Android Studio单纯使用Cmake和C++开发工具Clion(或者其他的开发工具也行,这些开发工具和Android Studio不一样,哪一种工具都行)。
实际上编译.so还有比较简单的方式。比如直接在linux环境下面使用cmake编译c++项目即可,这时候出现的就是.so库。但是如果开发环境是Mac或者Windows的话,就会生成dylib或者exe文件,不是我们想要的文件,所以就需要使用交叉编译的技术。
Cmake对于编译Android的.so文件提供了两种方式: NDK或者交叉工具链。不管使用NDK或者交叉工具链哪种方式都需要跟NDK进行关联,不会出现脱离NDK就编译处.so的问题

二、使用NDK进行编译的相关代码

开发工具为CLion,需要注意的是Android Studio和CLion都采用了ninja构建系统,如果使用其他构建系统需要进行修改,不过文中代码已经有该代码,到时候改下路径即可
整体项目结构如下:
在这里插入图片描述
这其中的核心代码为:
需要注意的是该代码中的set部分需要写在project(untitled VERSION 1.0)函数调用之前

# control where the static and shared libraries are built so that on windows# we don't need to tinker with the path to run the executableset(CMAKE_SYSTEM_NAME Android)set(CMAKE_SYSTEM_VERSION 21) # API levelset(CMAKE_ANDROID_ARCH_ABI arm64-v8a)set(CMAKE_ANDROID_NDK /Users/c/Documents/sdk/android/ndk/25.1.8937393)#set(CMAKE_TOOLCHAIN_FILE /Users/c/Documents/sdk/android/ndk/25.1.8937393/build/cmake/android.toolchain.cmake)set(CMAKE_MAKE_PROGRAM /Users/c/Documents/sdk/android/cmake/3.22.1/bin/ninja)#set(CMAKE_ANDROID_STL_TYPE gnustl_static) # 需要注意的是NDK不支持这个属性,可能是NDK版本原因,所以使用c++_shared,set(CMAKE_ANDROID_STL_TYPE c++_shared)set(CMAKE_EXPORT_COMPILE_COMMANDS NO)set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")aux_source_directory(. class="lazy" data-src_LIST) #把当前目录(.)下所有源代码文件和头文件加入变量class="lazy" data-src_LIST#ADD_EXECUTABLE(hello ${class="lazy" data-src_LIST}) #生成应用程序 hello (在windows下会自动生成hello.exe)# 将相关文件添加到SqrtLibrary库 ,最终编译成共享库 .soadd_library(SqrtLibrary SHARED        ${class="lazy" data-src_LIST}        )

CMakeLists.txt

cmake_minimum_required(VERSION 3.23) # 这是Cmake版本#======这一段来自Android开发者平台:https://developer.android.google.cn/ndk/guides/cmake?hl=zh-cn #-DCMAKE_FIND_ROOT_PATH=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/prefab/armeabi-v7a/prefab#-DCMAKE_BUILD_TYPE=Debug#-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk/22.1.7171670/build/cmake/android.toolchain.cmake#-DANDROID_ABI=armeabi-v7a#-DANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670#-DANDROID_PLATFORM=android-23#-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a#-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670#-DCMAKE_EXPORT_COMPILE_COMMANDS=ON#-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a#-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a#-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/ninja#-DCMAKE_SYSTEM_NAME=Android#-DCMAKE_SYSTEM_VERSION=23#====== end ======# control where the static and shared libraries are built so that on windows# we don't need to tinker with the path to run the executableset(CMAKE_SYSTEM_NAME Android)set(CMAKE_SYSTEM_VERSION 21) # API levelset(CMAKE_ANDROID_ARCH_ABI arm64-v8a)set(CMAKE_ANDROID_NDK /Users/c/Documents/sdk/android/ndk/25.1.8937393)set(CMAKE_MAKE_PROGRAM /Users/c/Documents/sdk/android/cmake/3.22.1/bin/ninja)#set(CMAKE_ANDROID_STL_TYPE gnustl_static) # 需要注意的是NDK不支持这个属性,可能是NDK版本原因,所以使用c++_shared,set(CMAKE_ANDROID_STL_TYPE c++_shared)set(CMAKE_EXPORT_COMPILE_COMMANDS NO)set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")project(untitled VERSION 1.0)add_subdirectory(libscanner)configure_file(square.h.in square.h)# specify the C++ standardadd_library(tutorial_compiler_flags INTERFACE)target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)# 通过BUILD_SHARED_LIBS 创建共享库,后面值需要设置为ON,# 这个属性写到这里,如果libscanner使用这个值的话有时候会报找不到的错误,如果经过反复Build后无法解决,将该属性写到相关的libscanner的CMakeLists.txt。但是这样的话最终rebuld后只会生成libscanner的.so。不过这也是预想的情况本身顶层目录也没有要求生成.so文件option(BUILD_SHARED_LIBS "Build using shared libraries" ON)add_executable(untitled square_main.cpp)target_link_libraries(untitled PUBLIC scanner tutorial_compiler_flags)target_include_directories(untitled PUBLIC        "${PROJECT_BINARY_DIR}"        "${PROJECT_SOURCE_DIR}/libscanner"        )# 打印日志message("---PROJECT_BINARY_DIR--${PROJECT_BINARY_DIR}")message("---PROJECT_SOURCE_DIR--${PROJECT_SOURCE_DIR}")message("---libscanner头文件--${PROJECT_SOURCE_DIR}/libscanner")

libscanner/CMakeLists.txt

add_library(scanner scanner.cpp) # 默认编译成静态库# state that anybody linking to us needs to include the current source dir# to find MathFunctions.h, while we don't.target_include_directories(scanner        INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}        )#add_executable(MakeTable scanner.cpp)#target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags)aux_source_directory(. class="lazy" data-src_LIST) #把当前目录(.)下所有源代码文件和头文件加入变量class="lazy" data-src_LIST#ADD_EXECUTABLE(hello ${class="lazy" data-src_LIST}) #生成应用程序 hello (在windows下会自动生成hello.exe)# 将相关文件添加到SqrtLibrary库add_library(SqrtLibrary SHARED       ${class="lazy" data-src_LIST}        )# 文件应该去哪个路径下面查找target_include_directories(SqrtLibrary PRIVATE        ${CMAKE_CURRENT_BINARY_DIR}        )# 将tutorial_compiler_flags库链接到SqrtLibrarytarget_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)# 将SqrtLibrary库链接到libscannertarget_link_libraries(scanner PRIVATE SqrtLibrary)# 将tutorial_compiler_flags库链接到libscannertarget_link_libraries(scanner PUBLIC tutorial_compiler_flags)message("YM--->${BUILD_SHARED_LIBS}")# state that SqrtLibrary need PIC when the default is shared librariesset_target_properties(SqrtLibrary PROPERTIES        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}        )

写完后重新ReBuild后即可在build文件夹下找到生成的.so库

四、使用交叉工具链进行编译

如果使用交叉工具链的话,编译跟上述方式相比只需要更改一行代码,由于NDK 新版r-19之后的改动,所以使用起来会更加简单。只要指定CMAKE_TOOLCHAIN_FILE属性即可

#set(CMAKE_ANDROID_NDK /Users/c/Documents/sdk/android/ndk/25.1.8937393)set(CMAKE_TOOLCHAIN_FILE /Users/c/Documents/sdk/android/ndk/25.1.8937393/build/cmake/android.toolchain.cmake)

五、参考链接

  1. Android 官网的CMake介绍
  2. 深入理解使用CMake编译 NDK 程序
  3. cmake-toolchains(7)
  4. android/ndk-samples
  5. CMAKE 在Linux下 构建android 编译、打包、发布环境
  6. android 交叉编译常用库(cmake
  7. 10、NDK交叉编译小记
  8. cmake : add_library详解
  9. MAC环境编译Android环境下的FFmpeg6.0版本

来源地址:https://blog.csdn.net/Mr_Tony/article/details/130956210

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Cmake学习记录(九)--使用Cmake交叉编译Android .so库

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录