AndroidNDK开发之交叉编译

在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 32defaultConfig {applicationId "com.mvp.myapplication"minSdk 21targetSdk 32versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"//1.第一步externalNativeBuild{cmake{abiFilters "armeabi-v7a"}}ndk{abiFilters "armeabi-v7a"}//=====================}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}//原始版本:手动写一个Android.mk文件,指定mk的路径externalNativeBuild{ndkBuild{path 'src/main/ndkDir/Android.mk'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility 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 := fmodLOCAL_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");}@Overrideprotected 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.hqwc.cn/news/211325.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《微信小程序开发从入门到实战》学习二十六

3.4 开发参与投票页面 参与投票页面同样需要收集用户提交的信息,哪个用户在哪个投票选择了什么选项,因此它也是一个表单页面 3.4.1 如何获取投票信息 假设用户A在投票创建页面后填了表单(1.创建投票),用户A 点了提交…

合并两个有序链表,剑指offer,力扣

目录 力扣题目地址: 原题题目: 我们直接看题解吧: 解题方法: 审题目事例提示: 解题思路: 具体流程如下: 代码实现: 知识补充: 力扣题目地址: 21. 合并两个有序…

基于C#实现Prim算法

图论在数据结构中是非常有趣而复杂的,作为 Web 码农的我,在实际开发中一直没有找到它的使用场景,不像树那样的频繁使用,不过还是准备仔细的把图论全部过一遍。 一、最小生成树 图中有一个好玩的东西叫做生成树,就是用…

前缀和——724. 寻找数组的中心下标

文章目录 🍓1. 题目🫒2. 算法原理🦄解法一:暴力枚举🦄解法二:前缀和 🥔3. 代码实现 🍓1. 题目 题目链接:724. 寻找数组的中心下标 - 力扣(LeetCode&#xff0…

排查光模块故障原因,少不了这2条命令!

光模块故障定位常用命令 根据光模块的告警信息查找故障原因: display interface transceiver查看光模块光功率是否正常 display interface transceiver verbose根据光模块的告警信息查找故障原因 执行命令display interface transceiver查看“Alarm information”…

传统制造业如何有效实现数字化?企业数字化转型可以借助哪些工具?

2020年,制造业数字化转型行业的价值为2630亿美元。然而,到2026年,这一数字预计将达到惊人的7670亿美元。随着新技术的出现,工业4.0时代已经开始。这是由软件开发和自动化带来的对数字化的日益依赖所决定的,这使得制造过…

python获取json所有节点和子节点

使用python获取json的所有父结点和子节点 并使用父节点加下划线命名子节点 先展示一段json代码 {"level1": {"level2": {"level3": [{"level4": "4value"},{"level4_2": "4_2value"}]},"level2_…

深入剖析预约上门服务系统源码:构建高效服务的代码之旅

在本文中,我们将深入研究预约上门服务系统的源码,透过代码的层层剖析,揭示系统背后的技术奥秘。我们将关注系统的核心功能,并通过代码示例演示其实现过程,为读者提供一个深度技术解读的体验。 1. 技术栈选择&#xf…

plantUML学习与实战

背景 在日常工作或者生活中,使用交互图来描述想法,往往相对于文字来说,可读性更高,同时一定程度上可以提高沟通效率,但是苦于,不想对一堆控件拖拖拉拉,本人就是一个很讨厌画图,但是…

java学习part09类的构造器

1. 2.默认构造器 如果没有显式定义任何构造器,系统会默认加一个默认构造器。 如果定义了,则不会有默认构造器。 默认构造器的权限和类的权限一样,类是public构造器就是public,类是缺省默认构造器就是缺省 反编译之后添加的构造…

Astute Graphics 2023(ai创意插件合集)

Astute Graphics 2023是一家专注于图形编辑软件的公司,以制作高质量、功能强大的图像编辑工具而闻名。如Poser Pro、Poser 3D、Smart Shapes、Astute Sketch Pro等。 Astute Graphics的软件具有以下特点: 强大的图像编辑功能:Astute Graphi…

动态规划求二维网格中从左上角到右下角的最短路径( 每次只能向下、向右、向右下走 ) java 实现

dp[i][j] 表示在以点(0,0)作为左上角,点(i,i) 作为右下角的二维网格中 左上角到右下角的最短路径, 动态转移方程为:dp[i][j] min{ dp[i][j-1],dp[i-1][j],dp[i-1][j-1] }.distance weight[i][j] ImageUtils.java: import java.a…