AndroidNDK开发之交叉编译

news2024/11/14 17:15:07

在Android studio2.2以及以上,构建原生库的默认工具是cmake
CMake是一个跨平台的构建工具,可以使用简单的语句来描述所有平台的安装(编译过程)。
能够输出各种各样的makefile或者project文件。cmake并不直接构建出最终的软件,而是产生其他工具的脚本(如makefile)。然后再根据这个工具的构建方式使用。
cmake是一个比make更高级的编译配置工具,可以根据不同的平台、不同的编译器生成相对应的makefile或vcproject项目,从而达到跨平台的目的。

c/c++ 编译成动态库和静态库的三种方式

  • 使用Linux gcc编译 实现ndk交叉编译
  • Android studio下使用mk实现ndk交叉编译(这种方式比较老旧,现在已被Cmake取代)
  • Android studio下使用Cmake实现ndk交叉编译

linux实现交叉编译

在linux环境中使用wget命令进行下载:

wget https://dl.google.com/android/repository/android-ndk-r26b-linux.zip

具体各位读者可以参考下面这篇博客:https://blog.csdn.net/qq_33979657/article/details/125187813

mk实现ndk交叉编译——了解即可

将工程的Test.c和Login.c打进so中。

  1. 编写gradle脚本
plugins {
    id 'com.android.application'
}

android {
    namespace 'com.mvp.myapplication'
    compileSdk 32

    defaultConfig {
        applicationId "com.mvp.myapplication"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        //1.第一步
        externalNativeBuild{
            cmake{
                abiFilters "armeabi-v7a"
            }
        }

        ndk{
            abiFilters "armeabi-v7a"
        }
        //=====================
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    //原始版本:手动写一个Android.mk文件,指定mk的路径
    externalNativeBuild{
        ndkBuild{
            path 'src/main/ndkDir/Android.mk'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.9.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
  • 编写mk文件
# 这里能够决定编译 Login.c Test.c

# 1.源文件所在的位置,宏函数 my-dir 返回当前目录(包含Android.mk 文件本身的目录)的路径
LOCAL_PATH := $(call my-dir)

$(info "LOCAL_PATH:======${LOCAL_PATH}") # src/main/ndkDir


# 2.清理
include $(CLEAR_VARS)

# TODO 预编译库的引入 == 提前编译好的库
LOCAL_MODULE := fmod

LOCAL_SRC_FILES := libfmod.so #引入动态库 .a 引入静态库

# 预编译动态库的makefile脚本
include $(PREBUILT_SHARED_LIBRARY)

# 预编译静态库的makefile脚本
# include $(PREBUILT_STATIC_LIBRARY)

# 引入其他makefile文件,之前最好都清理一遍,可以消除多余的LOCAL_XXX变量
include $(CLEAR_VARS)

# 3.指定库名称
# 存储需要构建的模块的名称,每个模块名称必须唯一,且不含任何空格
# 如果模块名称的开头已经是lib,则构建系统不会附加额外的前缀lib,而是按照模块名称,并添加so后最
LOCAL_MODULE := MyLoginJar #libMyLoginJar.so

# 包含要构建到模块中的c/c++源文件列表 以空格分开
LOCAL_SRC_FILES := Login.c \
Test.c

# 开始链接
# 静态库的链接
# LOCAL_STATIC_LIBRARIES := fmod
# 动态库的链接
LOCAL_SHARED_LIBRARIES := fmod

# 导入log库
LOCAL_LDLIBS := -lm -llog

# 4.动态库
# 构建动态库 最后生成总动态库 ---> libMyLoginJar.so
include $(PREBUILT_SHARED_LIBRARY)

# 构建静态库
# include $(PREBUILT_STATIC_LIBRARY)

# libfmod.so 先打入到fmod模块,然后fmod模块再打入到MyLoginJar模块中
  • 在java中引入并调用c相关的方法
package com.mvp.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("fmod");//如果是动态库,需要先加载,让系统生成一个副本
        System.loadLibrary("MyLoginJar");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

在这里插入图片描述

Cmake实现ndk交叉编译——大家可以参考笔者之前的一篇博客:

JNI技术之语言变声实现,这篇博客里面有对cmake相关的参数进行了详细介绍。这里笔者主要记录下cmake的相关语法。

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.18.1)

# Declares and names the project.

project("myapplication")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        myapplication

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        myapplication

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})


#cmake语法

#log信息的输出——message
#() = 重要信息
#STATUS = 非重要信息
#WARNING = cmake警告 代码会继续执行
#AUTHOR_WARNING = cmake警告(dev) 代码会继续执行
#SENO_ERROR = cmake错误 代码继续执行,但是会跳过生成的步骤
#FATAL_ERROR = cmake错误,终止所有处理过程

message("我是消息========>")

# cmake变量 cmake中所有变量都是string类型,可以使用set()unset()命令来声明或移除一个变量
#声明变量:set(变量名,变量值)
set(test 666)
unset(test)
message("test = ${test}") #会取不到值,test被移除了

#列表
#声明列表:set(列表名 值12 ...)set(列表名 "值1;值2...")
set( list 1 2 3 4)
message("list is ${list}")
set(list2 "1;2;3;4;5")
message("list2 is ${list2}")

#条件命令
#true(1,ON,YES,TRUE,Y,0的值)
#false(0,OFF,NO,FALSE,N,IGNORE)
set(if_tap OFF)
set(elseif_tap ON)

if (${if_tap})
    message("if")
elseif(${elseif_tap})
    message("elseif")
endif ()

#循环命令
#NOT a STREQUAL "xxx"(a不等于 xxx)
# break()命令可以跳出整个循环,continue命令可以继续当前循环
set(a "")
while(NOT a STREQUAL "xxx")
    set(a "${a}x")
    message(">>>>>>>a = ${a}")
endwhile()

foreach(item 1 2 3)
    message("item = ${item}")
endforeach()

foreach(item2 RANGE 2)
    message("item2 = ${item2}")
endforeach()

set( list 1 2 3 4)
foreach(item IN LISTS list)
    message("list = ${item}")
endforeach()

#函数命令
function(num_method n1 n2 n3)
    message("call num_method method")
    message("n1 = ${n1}")
    message("n2 = ${n2}")
    message("n3 = ${n3}")
    message("ARGC = ${ARGC}")
    message("arg1 = ${ARGV0} arg2 = ${ARGV1} arg3 = ${ARGV2}")
    message("all args = ${ARGV}")
endfunction()

num_method(100 200 300)

在这里插入图片描述

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

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

相关文章

MySQL错误之ONLY_FULL_GROUP_BY

报错信息: 翻译: 对该报错的解释 所以,实际上该报错是由于在SQL查询语句中有group by,而这个包含group by的SQL查询写的并不规范导致的,这个ONLY_FULL_GROUP_BY模式开启之后检查就会很严格,如果select列表…

node与 pnpm、node-sass 等工具的版本兼容关系

1. node & pnpm 2. node & node-sass 3. node-sass & sass-loader sass-loader依赖于node-sass,以下是部分版本号对应

1、postman的安装及使用

一、安装、登录 1.安装 下载地址 2.注册登录(保存云服务进度) 二、界面介绍 三、执行接口测试页面 请求页签: 1、params:当是get请求时,通过params传参 2、authorization:鉴权 3、headers&#xff1…

STM32 中断系统

单片机学习 目录 文章目录 前言 一、中断系统 1.1 什么是中断 1.2 中断优先级 1.3 中断嵌套 1.4 C语言中的中断程序 二、STM32的中断通道和中断向量 2.1 中断通道 2.2 嵌套向量中断控制器NVIC 2.2.1 什么是NVIC 2.2.2 NVIC基本结构 2.2.3抢占优先级和响应优先级 2.2.4 NVIC的优…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《计及电动汽车需求响应的高速公路服务区光储充鲁棒优化配置》

这个标题涉及到一个关于高速公路服务区的优化配置问题,其中考虑了电动汽车需求响应和光储充的因素。让我们逐步解读这个标题: 高速公路服务区: 涉及到高速公路上的服务区,这是供驾驶员休息、加油、用餐等的地方。 电动汽车需求响…

SEM代运营的服务费用为什么不按广告费比例抽佣?

如果SEM代运营公司是按广告费比例来抽取佣金,就意味着客户的广告费花得越多,代运营公司的收入也就越高。本来应当屏蔽掉的无效广告点击和恶意点击,出于代运营公司自身利益考虑,处理这些事情时也就不那么干脆利索。只要能保障客户有…

gvim中的捕获替换

有些时候我们在使用vim的时候,希望将其中的某些pattern, 替换成另外的pattern, 直接使用替换的话,会将某些不属于这个pattern的地方给误替换,因此可以采用如下的方式; 简单说下规则: \ ( \) : 用括号将需要捕获…

springboot 外部化配置

背景:修改jar包中的配置比较麻烦 项目部署的时候放一个配置文件在jar包外 配置文件优先级: 1.jar包内的application.properties/yaml 2.jar包内的application-{profile}.properties/yaml 3.jar包外的application.properties/yaml 4.jar包外的application-{profile}.properties…

指针变量与指针类型的深入理解

1.知识总结 相关代码展示 #include <stdio.h> int main() {int n 0x11223344;int *pi &n; *pi 0; return 0; } #include <stdio.h> int main() {int n 0x11223344;char *pc (char *)&n;*pc 0;return 0; } #include <stdio.h> int main() {i…

解决Vscode使用git提交卡住的问题

使用Vscode的git提交代码经常会很慢/卡住。 先点击左下角&#xff0c;进入设置 找到git的配置(建议直接搜索)&#xff0c;把use Editor As commit input的勾选去掉即可解决。

【C++干货铺】适配器 | stack | queue

个人主页点击直达&#xff1a;小白不是程序媛 C系列学习专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 stack的介绍和使用 stack的介绍 stack的使用 queue的介绍和使用 queue的介绍 queue的使用 容器适配器 什么是适配器 STL中stack和queue的底层结构 d…

Ubuntu 23.10 服务器版本 ifconfig 查不到网卡 ip(已解决)

文章目录 1、问题描述2、 解决方案 1、问题描述 服务器&#xff1a;ubuntu 23.10 经常会遇到虚拟机添加仅主机网卡后&#xff0c;通过 ifconfig 无法获取其网卡 ip 2、 解决方案 修改网卡配置文件&#xff1a; # 进入网卡配置文件目录 cd /etc/netplan # 备份原始文件 cp …

MAV3D:从文本描述中生成三维动态场景

Singer U, Sheynin S, Polyak A, et al. Text-to-4d dynamic scene generation[J]. arXiv preprint arXiv:2301.11280, 2023. MAV3D 是 Meta AI 研究者们提出的一种从文本描述生成三维动态场景的方法。从所提供的文本生成的动态视频输出可以从任何摄像机位置和角度查看&#xf…

基于python和django旅游管理系统

基于python和django旅游管理系统 摘要 基于Python和Django的旅游管理系统是一个以现代化技术为基础的系统&#xff0c;旨在提升旅游行业的管理效率和服务水平。该系统以Django框架为核心&#xff0c;结合Python编程语言的灵活性和强大的生态系统&#xff0c;实现了多方面的功能…

极兔速递单号查询,极兔速递物流查询,一键复制查询好的物流信息

批量查询极兔速递单号的物流信息&#xff0c;并将查询好的物流信息一键复制出来。 所需工具&#xff1a; 一个【快递批量查询高手】软件 极兔速递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;第一次使用的朋友记得先注册&…

CP_AUTOSAR分层软件架构内容简介

目录 0、前言1、综述1.1 AUTOSAR应用范围及拓展性1.2 架构总体介绍 0、前言 随着汽车功能需求日益增加&#xff0c;稳定安全的AUTOSAR分层软件架构逐渐作为一个热词呈现在汽车电子软件开发领域。那么AUTOSAR分层软件架构到底包括了哪些内容&#xff1f;架构之间的是什么关系&am…

mac mysql连接中断重新启动办法

遇到如图所示问题&#xff0c;可以用下面的命令重启mysql服务 sudo /usr/local/mysql/support-files/mysql.server start

【深度学习】卷积神经网络(CNN)的参数优化方法

著名&#xff1a; 本文是从 Michael Nielsen的电子书Neural Network and Deep Learning的深度学习那一章的卷积神经网络的参数优化方法的一些总结和摘录&#xff0c;并不是我自己的结论和做实验所得到的结果。我想Michael的实验结果更有说服力一些。本书在github上有中文翻译的…

浅谈 Guava 中的 ImmutableMap.of 方法的坑

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐&…

数据结构与算法编程题16

已知长度为n的线性表A&#xff0c;请写一时间复杂度为O(n)、空间复杂度为O(1)的算法&#xff0c;该算法删除线性表中所有值为item的数据元素。 item 3 数组下标 i 0 1 2 3 4 5 6 7 8 顺序表&#xff1a; 1 2 3 4 3 3 5 3 7 #include <iostream> using namespace std;typ…