Android Studio利用CMake生成.so文件并且可供其他项目引用

news2024/11/27 15:38:26

1、CMake工具

1.1、CMake是什么

  • CMake是一个主要用于CPP的构建工具。
  • CMake语言是平台无关的中间编译工具。同一个CMake编译规则在不同系统平台构建出不同的可执行构建文件,所有操作都是通过编译CMakeLists.txt来完成的。在Linux产生MakeFile,在Windows平台产生Visual Studio工程等。
  • CMake旨在解决各平台的不同Make工具的产生的差异(比如GNU Make, QT的qmake,微软的nmake, BSD的pmake)。

1.2、CMake原理

CMake有两个阶段:配置、生成。

 1.3、CMake常用命令介绍

(1)cmake_minimum_required

  • 用于设定需要的最低版本的CMake
cmake_minimum_required
(
    VERSION <min>[...<policy_max>] [FATAL_ERROR]
)

(2)project

  • 用于指定cmake工程的名称,并将其存储在变量PROJECT_NAME中
project
(
    <PROJECT-NAME> 

    [<language-name>...]
)

或

project
(
    <PROJECT-NAME>

    [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]

    [DESCRIPTION <project-description-string>]

    [HOMEPAGE_URL <url-string>]

    [LANGUAGES <language-name>...]
)
VERSIONcmake工程的版本号
DESCRIPTIONcmake工程的简短的描述
HOMEPAGE_URLcmake工程的主页URL
LANGUAGEScmake工程的编译工程使用的语言

(3)add_library

使用该命令可以在:

  • Linux下生成(静态/动态)库so或者.a文件
  • Windows下就是dll与lib文件

它有两种命令格式

  • 第一种

add_library
(
    <name>

    [STATIC | SHARED | MODULE]
           
    [EXCLUDE_FROM_ALL]
            
    [source1] [source2] [...]
)
<name>库文件的名字,该库文件会根据命令里列出的源文件来创建
[STATIC | SHARED | MODULE]

作用是指定生成的库文件的类型

  • STATIC库:生成obj文件后,将其链接成静态库,用于链接到其他targets
  • SHARED库:生成obj文件后,将其链接成动态库,用于运行时加载
  • MODULE库:不能链接到其他targets,但是可以用dlopen之类的方法在运行时动态加载

注:如果没有明确指定要生成的library的类型到底是STATIC,SHARED还是MODULE。则查看BUILD_SHARED_LIBS变量,如果值为ON,则默认是SHARED,否则默认STATIC

[EXCLUDE_FROM_ALL]表明该target是否从默认构建target中排除
[source1] [source2] [...]source1 source2分别表示各个源文件

  •  第二种

生成一个obj文件对象,该对象库只编译源文件,但不链接

add_library
(
    <name> OBJECT [<source>...]
)

(4)find_library

  • 该命令用来查找一个库文件
find_library
(
    <VAR> name1 [path1 path2 ...]
)
<VAR>
  • 一个名为<VAR>的cache条目会被创建来存储该命令的结果。
  • 如果找到了该库文件,那么结果会存储在该变量里,并且搜索过程将不再重复,除非该变量被清空。
  • 如果没有找到,结果变量将会是<VAR>-NOTFOUND,并且在下次使用相同变量调用find_library命令时,搜索过程会再次尝试
NAMES在NAMES参数后列出的文件名是要被搜索的库名
PATHS附加的搜索位置在PATHS参数后指定

(5)target_link_libraries

  • 该指令的作用为将目标文件与库文件进行链接
target_link_libraries
(
    <target>

    [item1] [item2] [...][[debug|optimized|general] <item>] ...
)
  • 上述指令中的是指通过add_executable()和add_library()指令生成已经创建的目标文件。而[item]表示库文件没有后缀的名字。
  • 默认情况下,库依赖项是传递的。当这个目标链接到另一个目标时,链接到这个目标的库也会出现在另一个目标的连接线上。这个传递的接口存储在interface_link_libraries的目标属性中,可以通过设置该属性直接重写传递接口。

2、Android Studio生成.so

  • Android Studio版本:Android Studio Flamingo | 2022.2.1 Patch 2
  • 开发语言:Kotlin

2.1、新建C++项目

 

 

  • 可以选择C++版本,我选择的是默认

 

 

新建项目中会有CMakeLists.txt和native-lib.cpp两个文件

  • CMakeLists.txt:CMake工具会根据其中的命令编译生成.so文件
  • native-lib.cpp:C++文件

 CMakeLists.txt中的内容

# 指定需要的 CMake 最低版本为 3.22.1
cmake_minimum_required(VERSION 3.22.1)

# 指定项目名称为 "mysocreatefile"
project("mysocreatefile")

# 添加一个名为 "mysocreatefile" 的共享库,并将 "native-lib.cpp" 源文件添加到库中
# 这里使用 SHARED 标志表示这是一个共享库(动态链接库)
add_library(
        mysocreatefile

        SHARED

        native-lib.cpp
)

# 查找名为 "log" 的库,并将其路径保存在变量 log-lib 中
# 这是为了在后面的步骤中将这个库链接到目标库
find_library(
        log-lib

        log
)

# 将目标库 "mysocreatefile" 与 log-lib 变量中的库链接起来。
# 这意味着在编译和链接过程中,将使用 "log" 库提供的功能和符号
target_link_libraries(
        mysocreatefile

        ${log-lib}
)

native-lib.cpp中的内容,即C++要执行的代码

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_leon_mysocreatefile_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

MainActivity中的内容

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.sampleText.text = stringFromJNI()
    }

    external fun stringFromJNI(): String

    companion object {
        init {
            System.loadLibrary("mysocreatefile")
        }
    }
}
  • 可以看到程序已经为我们自动生成了一个动态生成.so文件的示例
  • 其中生成的.so文件的库的名称叫做"mysocreatefile"
  • 库中的C++方法Java_com_leon_mysocreatefile_MainActivity_stringFromJNI(),其中com_leon_mysocreatefile对应的是包名,MainActivity_stringFromJNI()对应的是类名和方法名,在Java中调用该方法时,必须使包名类名方法名与此处的保持一致,下面会示例讲解。
  • 想要在MainActivity中调用C++方法,需要先加载库System.loadLibrary("mysocreatefile"),然后声明native方法stringFromJNI(),这个方法名要与C++中的方法名对应
  • external对应Java中的public static native

build.gradle(:app)中,android{}目录中会有cmake的配置

我们可以Make一下项目,看一下示例生成的.so

 

 2.2、生成自定义功能的.so文件

  • 比如,我们想在.so中实现一个分数评定的功能,大于90分优秀,大于70分良好,小于60分不及格。

(1)创建一个Kotlin类

定义一个external方法

 

(2)创建cpp文件,用C++实现功能

 

 

  • 注:C++中方法名中的包名前缀、类名前缀、方法名前缀要与定义的Kotlin类的一致。
  • 如,Kotlin类的包名是com.leon.score,类名是ScoreTool,方法名是evaluateLevel
  • 则C++中的方法名就是Java_com_leon_score_ScoreTool_evaluateLevel

(3)修改CMakeList.txt

  • 可以将库名换一个myscorelib
  • 替换cpp文件
# 指定需要的 CMake 最低版本为 3.22.1
cmake_minimum_required(VERSION 3.22.1)

# 指定项目名称为 "myscorelib"
project("myscorelib")

# 添加一个名为 "myscorelib" 的共享库,并将 "score-lib.cpp" 源文件添加到库中
# 这里使用 SHARED 标志表示这是一个共享库(动态链接库)
add_library(
        myscorelib

        SHARED

        score-lib.cpp
)

# 查找名为 "log" 的库,并将其路径保存在变量 log-lib 中
# 这是为了在后面的步骤中将这个库链接到目标库
find_library(
        log-lib

        log
)

# 将目标库 "myscorelib" 与 log-lib 变量中的库链接起来。
# 这意味着在编译和链接过程中,将使用 "log" 库提供的功能和符号
target_link_libraries(
        myscorelib

        ${log-lib}
)

(4).so文件加载和使用

  • 需要通过System.loadLibrary来加载库myscorelib
package com.leon.score

class ScoreTool {

    companion object{
        init {
            System.loadLibrary("myscorelib")
        }
    }

    external fun evaluateLevel(score: Int): String
}

  • Make Project以生成.so文件(把之前.so的缓存全部删除再make)

 

  • 在MainActivity中调用该方法
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)


        //评定分数等级
        val score = 50
        val level = ScoreTool().evaluateLevel(score)


        //展示结果
        binding.sampleText.text = "得分:$score\n等级:$level"
    }
}

 

3、在其他项目中使用自定义的.so文件

  • 将cmake目录下动态生成的.so文件复制一份备用

 

3.1、新建一个Android项目

  • 将刚才复制的.so文件放置app下的libs中

 

  • 配置build.gradle(:app)中的sourceSets和ndk
android {
	...
    sourceSets{
        main{
            jniLibs.srcDirs = ['libs']
        }
    }

    defaultConfig {
		...
        ndk {
            // 设置支持的SO库架构
            abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
        }
        
    }  
}

3.2、适配工具类

  • 创建的工具类必须和.so文件中方法的包名,类名,方法名一致,才能引用到.so库中的C++方法

 

3.3、使用.so方法

 

 

CMake概念

CMake命令

OOM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/720132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5.1ORB-SLAM3之回环检测线程检测是否存在共视区域

1.简介 本质上是计算当前关键帧和关键帧数据库中的关键帧是否存在公共单词&#xff0c;相似性分数是否满足要求。 bool LoopClosing::NewDetectCommonRegions();主要包括以下几个模块&#xff1a; 寻找回环候选关键帧和融合候选关键帧对候选关键帧进行共视几何验证如果共视几…

Android Studio实现内容丰富的安卓校园二手交易平台(带聊天功能)

如需源码可以添加q-------3290510686&#xff0c;也有演示视频演示具体功能&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号083 1.开发环境 android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.查看二手商品…

AndroidStudio设置compileSdk33后xml无提示问题

这个非常蛋疼的问题遇到很多次了&#xff0c;AndroidStudio升级compileSdk33后无xml提示。挺久前写一个调研demo时发现了这个问题&#xff0c;但因为那会任务重&#xff0c;也没有去深入研究&#xff0c;就在写代码时用target32&#xff0c;写完打包demo时修改为33&#xff0c;…

附录7-用户列表案例,element-ui

目录 1 效果 1.1 查询所有用户 1.2 添加新用户 1.3 删除用户 1.4 用户详情 2 后端 2.1 查询所有 2.2 添加 2.3 删除 2.4 查询单个 3 前端 3.1 环境 3.2 main.js 3.3 userList.vue 3.4 userInfo.vue 1 效果 1.1 查询所有用户 1.2 添加新用户 …

工厂水电能耗监测系统组成

工厂水电能耗监测系统是一种用于监测工厂水电能耗的系统&#xff0c;可以帮助工厂管理者了解水电能耗情况&#xff0c;提高能源利用效率&#xff0c;降低生产成本。本文将从系统组成、功能、优点等方面进行介绍。 一、系统组成 工厂水电能耗监测系统由多个部分组成&#xff0c…

MySQL第一天

文章目录 作业1 简述MySQL体系结构CetenOS 7的MySQLyum在线安装CetenOS 7的MySQL的二进制方式安装 作业1 简述MySQL体系结构 MySQL是由SQL接口、解析器、优化器、缓存、储存引擎组成的&#xff0c;MySQL的最重要的是它的储存引擎架构&#xff0c;这种设计将查询处理及其系统任…

【运维工程师学习】Debian安装

【运维工程师学习】Debian安装 1、界面说明2、选择语言3、等待探测并挂载安装介质完成4、设置主机名称、用户信息5、磁盘分区6、创建分区7、最终分区为8、安装ssh9、查看ssh状态10、查看内存大小11、查询系统磁盘及分区情况12、查看各磁盘及分区剩余13、查看ip地址 选择镜像文件…

新服务器配环境

本章节的大概思路为&#xff1a; 1、远程连接服务器 直接远程连接&#xff0c;前的是你要连接的目录名称&#xff0c;后为服务器公网IP。 ssh xxxxxx.xxx.xxx.xxx 远程连接服务器不同端口 -p后为端口名称 ssh xxxxxx.xxx.xxx.xxx -p xxxx 之后输入密码就行了。 2、创建子用…

c语言修炼之猜数字游戏

前言 小伙伴们&#xff0c;今天来学习猜数字游戏叭&#xff01;废话不多说&#xff0c;让我们一起开始学习叭! 思路&#xff1a; 一打开游戏就出现一个菜单然后可以让我们选择是进入游戏还是退出游戏&#xff01; #include<stdio.h> void menu() {printf("*****…

详解高性能无锁队列的实现

一、无锁队列 1.1 什么是无锁队列 无锁队列&#xff08;Lock-Free Queue&#xff09;是一种并发数据结构&#xff0c;它允许多个线程在没有锁的情况下进行并发操作。 传统的队列通常通过互斥锁来实现线程安全的操作&#xff0c;但互斥锁在高并发情况下可能会造成竞争和性能瓶…

【后端面经-Java】AQS详解

【后端面经-Java】AQS详解 1. AQS是什么&#xff1f;2. AQS核心思想2.1 基本框架2.1.1 资源state2.1.2 CLH双向队列 2.2 AQS模板 3. 源码分析3.1 acquire(int)3.1.1 tryAcquire(int)3.1.2 addWaiter(Node.EXCLUSIVE)3.1.3 acquireQueued(Node node, int arg) 3.2 release(int)3…

校园水电节能管理解决方案

随着社会经济的不断发展&#xff0c;能源问题日益突出&#xff0c;节能减排成为了各级各类学校必须面对的问题。学校的水电能源消耗是其中的一个重要方面&#xff0c;因此&#xff0c;如何对校园水电进行节能管理成为了一个迫切的问题。本文将从以下几个方面介绍校园水电节能管…

在选择自动化测试工具时需要考虑哪些因素?

自动化测试工具是软件开发中不可或缺的一部分&#xff0c;它可以提高测试效率、减少人力成本、提升软件质量&#xff0c;那在选择自动化测试工具时需要考虑哪些因素&#xff1f; 测试需求&#xff1a;首先要明确自动化测试的需求是什么&#xff0c;不同的测试需求对应着不同的工…

电子电气架构相关安全体系介绍

摘要&#xff1a; 随着电子电气架构技术的不断升级&#xff0c;整车越来越多的系统和组件对功能安全产生影响&#xff0c;为此&#xff0c;功能安全也从部分关键系统开发&#xff0c;向整车各系统全面开发拓展。同时&#xff0c;由于域集中式、中央集中式等新架构形态的出现&a…

文档翻译免费怎么做?三分钟告诉你

小乐&#xff1a;嘿&#xff0c;小阳&#xff0c;你知道吗&#xff1f;我最近在学习文档翻译英文&#xff0c;真是太神奇了&#xff01; 小阳&#xff1a;哇&#xff0c;真的吗&#xff1f;那听起来很厉害啊&#xff01;文档翻译英文是怎么做的呢&#xff1f; 小乐&#xff1…

深入解析Java多态进阶学习

目录 1.动态绑定机制 实例A实例B实例C2.多态数组 3.多态数组的高阶用法 4.多态参数 5.多态参数的高阶用法 1.动态绑定机制 java的动态绑定机制非常重要 实例A 我们来看一个实例&#xff1a; 阅读上面的代码&#xff0c;请说明下面的程序将输出什么结果&#xff1a; 程序将会…

机器学习24:《数据准备和特征工程-II》收集数据

构建数据集常用的步骤如下所示&#xff1a; 收集原始数据。识别特征和标签来源。选择抽样策略。拆分数据。 这些步骤在很大程度上取决于你如何构建 ML 问题。本文主要介绍——数据收集-Collecting Data。 目录 1. 数据集的大小和质量 1.1 数据集的大小 1.2 数据集的质量 …

.NET Core webapi 从零开始在IIS上面发布后端接口

文章目录 原因环境配置windows环境.NET Core安装开发端安装服务端安装 新建ASP.NET项目 原因 .NET core是以后.NET未来的趋势&#xff0c;虽然我感觉Java在web后端的主导地位10年内不会动摇&#xff0c;因为Java占据了先发优势。 不过C#的特点就是&#xff0c;简单&#xff0…

mysql三大日志之我对Binlog的理解

mysql 我们先来看一下MySQL的基本架构&#xff0c;从大的方面来讲&#xff0c;一个server层&#xff0c;一个引擎层。server层就像一个接口&#xff0c;可以对接任何符合规定的引擎。具体的细节可以参考我之前写过的文章mysql的这些坑你踩过吗&#xff1f;快来看看怎么优化mys…

Blazor 自定义可重用基础组件之 带标头排序的Table

实现点击标头按所在列值进行排序&#xff0c;是一个非常有用的功能&#xff0c;其他的UI一般搞得非常复杂&#xff0c;添加标志图标什么的&#xff0c;使得本就不宽裕的表格更加拥挤。我的思路是&#xff0c;点击所在列的标头部位&#xff0c;传递标头值&#xff0c;然后根据标…