当前位置: 首页 > news >正文

Android mk/bp构建工具介绍

   零. 前言

由于Bluedroid的介绍文档有限,以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等),加上需要掌握的语言包括Java/C/C++等,加上网络上其实没有一个完整的介绍Bluedroid系列的文档,所以不管是蓝牙初学者还是蓝牙从业人员,都有不小的难度,学习曲线也相对较陡,所以我有了这个想法,专门对Bluedroid做一个系统性的介绍,尽可能的涵盖所有内容。

-------------------------------------------------------------------------------------------------------------------------

蓝牙视频教程(跟韦东山老师合作), 其中专题21就是专门针对Bluedroid做的系统介绍

https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.20.5aeb41f98e267j&id=693788592796

--------------------------------------------------------------------------------------------------------------------------

一. Android mk

1. 介绍

Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名、引用的头文件目录、需要编译的.c/.cpp文件和.a静态库文件等。要掌握jni,就必须熟练掌握Android.mk的语法规范。

LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
................  
LOCAL_xxx       := xxx  
LOCAL_MODULE    := hello-jni  
LOCAL_SRC_FILES := hello-jni.c  
LOCAL_xxx       := xxx  
................  
include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH变量指定了该.mk的路径,$(call my-dir)调用NDK内部的函数获得当前.mk文件的路径

include $(CLEAR_VARS)清空了除了LOCAL_PATH之外的所有LOCAL_xxx变量的值

省略号中间就是对于模块参数的设置,主要包括:模块名字、模块源文件、模块类型、编译好的模块存放位置、以及编译的平台等

include $(BUILD_xxx_xxx)执行NDK的默认脚本,它会收集include $(CLEAR_VARS)脚本后所有定义的LOCAL_xxx变量,然后根据它们来生成模块。

2. Android.mk语法详解

LOCAL_PATH := $(call my-dir)
每个Android.mk文件必须以定义LOCAL_PATH为开始。它用于在开发tree中查找源文件。宏my-dir 则由Build System提供。返回包含Android.mk的目录路径。

include $(CLEAR_VARS)
CLEAR_VARS 变量由Build System提供。并指向一个指定的GNU Makefile,由它负责清理很多LOCAL_xxx.
例如:LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES等等。但不清理LOCAL_PATH.
这个清理动作是必须的,因为所有的编译控制文件由同一个GNU Make解析和执行,其变量是全局的。所以清理后才能避免相互影响。

LOCAL_MODULE := hello-jni

LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块。名字必须唯一且不包含空格。Build System会自动添加适当的前缀和后缀。例如,foo,要产生动态库,则生成libfoo.so. 但请注意:如果模块名被定为:libfoo.则生成libfoo.so. 不再加前缀

LOCAL_MODULE_PATH :=$(TARGET_ROOT_OUT) 指定最后生成的模块的目标地址

TARGET_ROOT_OUT:根文件系统,路径为out/target/product/generic/root

TARGET_OUT:system文件系统,路径为out/target/product/generic/system

TARGET_OUT_DATA:data文件系统,路径为out/target/product/generic/data

除了上面的这些,NDK还提供了很多其他的TARGET_XXX_XXX变量,用于将生成的模块拷贝到输出目录的不同路径

默认是TARGET_OUT

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SRC_FILES变量必须包含将要打包如模块的C/C++ 源码。不必列出头文件,build System 会自动帮我们找出依赖文件。缺省的C++源码的扩展名为.cpp. 也可以修改,通过LOCAL_CPP_EXTENSION

include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY:是Build System提供的一个变量,指向一个GNU Makefile Script。
它负责收集自从上次调用 include $(CLEAR_VARS) 后的所有LOCAL_XXX信息。并决定编译为什么。

BUILD_STATIC_LIBRARY :编译为静态库。
BUILD_SHARED_LIBRARY :编译为动态库
BUILD_EXECUTABLE :编译为Native C可执行程序

BUILD_PREBUILT :该模块已经预先编译

NDK还定义了很多其他的BUILD_XXX_XXX变量,它们用来指定模块的生成方式。

三. Android.mk实战

1.编译静态库

首先我们把vendor下创建一个Study的目录,然后再Study创建一个test1的目录,tree如下:

我们的目标是把test.c编译成一个静态库

test.c代码如下:

#include <stdio.h>int test(void)
{printf("hello Androoid.mk\r\n");return 0;
}

Android.mk代码如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := test.c
LOCAL_MODULE := test1
include $(BUILD_STATIC_LIBRARY)

编译方法:

方法1:在android 跟目录下敲指令:make test1

方法2:在vendor/Study/test1目录下敲指令mm

注意:两个方法都需要先source build/envsetup.sh -> lunch选择41

test.a生成在out/target/product/rk3399_roc_pc_plus/obj_arm/STATIC_LIBRARIES/test1_intermediates/test1.a

NOTED:我们发现生成的并不是libtest1.a,而是test1.a,这个要注意下

2.编译动态库

首先我们把vendor下创建一个Study的目录,然后再Study创建一个test2的目录,tree如下:

我们的目标是把test.c编译成一个静态库

test.c代码如下:

#include <stdio.h>int test(void)
{printf("hello Androoid.mk\r\n");return 0;
}

Android.mk代码如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := test.c
LOCAL_MODULE := test2
include $(BUILD_SHARED_LIBRARY)

编译方法:

方法1:在android 跟目录下敲指令:make test2

方法2:在vendor/Study/test2目录下敲指令mm

注意:两个方法都需要先source build/envsetup.sh -> lunch选择41

test.so生成在out/target/product/rk3399_roc_pc_plus/obj_arm/SHARED_LIBRARIES/test2_intermediates/test2.so

NOTED:我们发现生成的并不是libtest2.so,而是test2.so,这个要注意下

二. Android bp

1. Android.bp概念

Android.bp 文件首先是 Android 系统的一种编译配置文件,是用来代替原来的 Android.mk文件的。在Android7.0 以前,Android 都是使用 make 来组织各模块的编译,对应的编译配置文件就是 Android.mk。

在 Android7.0 开始,Google 引入了 ninja 和 kati 来编译,为啥引入 ninja?因为随着 Android 越来越庞大,module 越来越多,编译时间也越来越久,而使用 ninja 在编译的并发处理上较 make 有很大的提升。Ninja 的配置文件就是Android.bp,Android 系统使用 Blueprint 和 Soong 工具来解析 Android.bp 转换生成 ninja文件。为了兼容老的 mk 配置文件,Android 当初也开发了 Kati 工具来转换 mk 文件生成ninja,目前 Android Q 里边,还是支持 Android.mk 方式的。相信在将来的版本中,会彻底让 mk 文件废弃,同时 Kati 也就淘汰了,只保留 bp 配置方式,所以我们要提前学习bp。

这里涉及到Ninja, kati, Soong, bp概念,接下来分别简单介绍一下。

Ninja

ninja是一个编译框架,会根据相应的ninja格式的配置文件进行编译,但是ninja文件一般不会手动修改,而是通过将Android.bp文件转换成ninja格文件来编译。

Android.bp

Android.bp的出现就是为了替换Android.mk文件。bp跟mk文件不同,它是纯粹的配置,没有分支、循环等流程控制,不能做算数逻辑运算。如果需要控制逻辑,那么只能通过Go语言编写。

Soong

Soong类似于之前的Makefile编译系统的核心,负责提供Android.bp语义解析,并将之转换成Ninja文件。Soong还会编译生成一个androidmk命令,用于将Android.mk文件转换为Android.bp文件,不过这个转换功能仅限于没有分支、循环等流程控制的Android.mk才有效。

Blueprint

Blueprint是生成、解析Android.bp的工具,是Soong的一部分。Soong负责Android编译而设计的工具,而Blueprint只是解析文件格式,Soong解析内容的具体含义。Blueprint和Soong都是由Golang写的项目,从Android 7.0,prebuilts/go/目录下新增Golang所需的运行环境,在编译时使用。

Kati

kati是专为Android开发的一个基于Golang和C++的工具,主要功能是把Android中的Android.mk文件转换成Ninja文件。代码路径是build/kati/,编译后的产物是ckati。

重要的事情说三遍,Android.mk可以引用Android.bp中的模块,反之Android.bp不能引用Android.mk中的模块。

重要的事情说三遍,Android.mk可以引用Android.bp中的模块,反之Android.bp不能引用Android.mk中的模块。

重要的事情说三遍,Android.mk可以引用Android.bp中的模块,反之Android.bp不能引用Android.mk中的模块。

2. Android mk转换成Android bp

1.安装androidmk 工具

我们以rk3399来举例说明

source build/envsetup.sh

lunch rk3399_roc_pc_plus-userdebug

make androidmk

生成androidmk转换工具,路径为:/out/soong/host/linux-x86/bin/androidmk

2.转换

androidmk Android.mk > Android.bp

3.Android bp语法

1.编译静态库

首先我们把vendor下创建一个Study的目录,然后再Study创建一个test1的目录,tree如下:

我们的目标是把test.c编译成一个静态库

test.c代码如下:

#include <stdio.h>int test(void)
{printf("hello Androoid.mk\r\n");return 0;
}

Android.bp代码如下:

cc_library_static {name: "test3",srcs: ["test.c"],
}

编译方法:

方法1:在android 跟目录下敲指令:make test3

方法2:在vendor/Study/test3目录下敲指令mm

注意:两个方法都需要先source build/envsetup.sh -> lunch选择41

test.a生成在out/target/product/rk3399_roc_pc_plus/obj_arm/STATIC_LIBRARIES/test3_intermediates/test3.a

NOTED:我们发现生成的并不是libtest3.a,而是test3.a,这个要注意下

其中cc_library_static就是编译成c/c++ 静态库,可以有以下类型

name就是模组的名称

srcs就是源文件

2.编译动态库

首先我们把vendor下创建一个Study的目录,然后再Study创建一个test2的目录,tree如下:

我们的目标是把test.c编译成一个静态库

test.c代码如下:

#include <stdio.h>int test(void)
{printf("hello Androoid.mk\r\n");return 0;
}

Android.bp代码如下:

cc_library_shared {name: "test4",srcs: ["test.c"],
}

编译方法:

方法1:在android 跟目录下敲指令:make test4

方法2:在vendor/Study/test4目录下敲指令mm

注意:两个方法都需要先source build/envsetup.sh -> lunch选择41

test.so生成在out/target/product/rk3399_roc_pc_plus/obj_arm/SHARED_LIBRARIES/test4_intermediates/test4.so

NOTED:我们发现生成的并不是libtest4.so,而是test4.so,这个要注意下

相关文章:

Android mk/bp构建工具介绍

零. 前言 由于Bluedroid的介绍文档有限&#xff0c;以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等)&#xff0c;加上需要掌握的语言包括Java/C/C等&#xff0c;加上网络上其实没有一个完整的介绍Bluedroid系列的文档&#xff0…...

数据源及分层开发

数据源及分层开发 1. 使用Tomcat数据源 连接池工作原理&#xff1a; 连接池是由容器提供的&#xff0c;用来管理池中连接对象。 连接池自动分配连接对象并对闲置的连接进行回收。 数据源&#xff08;DataSource&#xff09;&#xff1a; javax.sql.DataSource接口负责建立…...

气膜场馆照明设计:科技与环保的完美结合—轻空间

气膜场馆的照明设计&#xff0c;选用高效节能的400瓦LED灯具&#xff0c;结合现代节能技术&#xff0c;提供强大而均匀的光照。LED灯具在光效和寿命方面优势显著&#xff0c;不仅降低运营能耗&#xff0c;还有效减少碳排放&#xff0c;为绿色场馆建设贡献力量。 科学分布&…...

并行IO接口8255

文章目录 8255A芯片组成外设接口三个端口两组端口关于C口&#xff08;★&#xff09; 内部逻辑CPU接口 8255A的控制字&#xff08;★&#xff09;位控字&#xff08;D70&#xff09;方式选择控制字&#xff08;D71&#xff09; 8255A的工作方式工作方式0&#xff08;基本输入/输…...

Level DB --- SkipList

class SkipList class SkipList 是Level DB中的重要数据结构&#xff0c;存储在memtable中的数据通过SkipList来存储和检索数据&#xff0c;它有优秀的读写性能&#xff0c;且和红黑树相比&#xff0c;更适合多线程的操作。 SkipList SkipList还是一个比较简单的数据结构&a…...

第二十二周机器学习笔记:动手深度学习之——线性代数

第二十周周报 摘要Abstract一、动手深度学习1. 线性代数1.1 标量1.2 向量1.3 矩阵1.4 张量1.4.1 张量算法的基本性质 1.5 降维1.5.1 非降维求和 1.6 点积1.6.1 矩阵-向量积1.6.2 矩阵-矩阵乘法 1.7 范数 总结 摘要 本文深入探讨了深度学习中的数学基础&#xff0c;特别是线性代…...

leetcode 50个简单和中等难度的题

简单难度题目&#xff08;25个&#xff09; ‌两数之和 (Two Sum)‌‌有效的括号 (Valid Parentheses)‌‌罗马数字转整数 (Roman to Integer)‌‌最长公共前缀 (Longest Common Prefix)‌‌合并两个有序链表 (Merge Two Sorted Lists)‌‌移除链表元素 (Remove Linked List E…...

多模态大模型(5)--LLaVA

人类通过如视觉、语言、听觉等多种渠道与世界互动&#xff0c;每个单独的渠道在表示和传达某些概念时都有其独特的优势&#xff0c;人工智能&#xff08;AI&#xff09;的一个核心愿景是开发一个能够有效遵循多模态视觉和语言指令的通用助手&#xff0c;与人类意图一致&#xf…...

Vue实训---3-element plus的使用与布局

1.引入ElementPlus ElementPlus官网指南&#xff1a;快速开始 | Element Plus 在我们的项目main.js文件中&#xff0c;加入红框里的内容&#xff1a; import { createApp } from vue import App from ./App.vue // 引入全局样式&#xff0c;是对样式的初始化 import "/a…...

TritonServer中加载模型,并在Gunicorn上启动Web服务调用模型

TritonServer中加载模型,并在Gunicorn上启动Web服务调用模型 一、TritonServer中加载模型1.1 搭建本地仓库1.2 配置文件1.3 服务端代码1.4 启动TritonServer二、Gunicorn上启动Web服务2.1 安装和配置Gunicorn2.2 启动Gunicorn三、调用模型四、性能优化与监控五、总结在深度学习…...

快速删除 node_modules 目录的集中方法

要快速删除 node_modules 目录&#xff0c;可以使用以下几种方法&#xff1a; 方法 1: 使用 rimraf 如果你在 Windows 上或者想要一个跨平台的解决方案&#xff0c;可以使用 rimraf 这个工具&#xff0c;它是 Node.js 版本的 rm -rf。 安装 rimraf&#xff1a; npm install …...

shell编程--if判断与for循环

shell编程与其他编程语言一样都有if判断与循环&#xff0c;今天了解一下if判断语句和for循环语句。 if判断语句讲解 我们写出一个if判断 a 1 b 2if [ "$a" -eq "$b" ]; thenecho "相等" elseecho "不相等" fi 在shell中-eq是表示…...

Makefile基础应用

1 使用场景 在Linux环境下&#xff0c;我们通常需要通过命令行来编译代码。例如&#xff0c;在使用gcc编译C语言代码时&#xff0c;需要使用以下命令。 gcc -o main main.c 使用这种方式编译代码非常吃力&#xff0c;每次调试代码都需要重新在命令行下重新编译&#xff0c;重复…...

计算机网络基础全攻略:探秘网络构建块(1/10)

一、计算机网络基础概念 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路和通信设备连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统…...

SpringMVC-Day1

SpringMVC 1.SpringMVC介绍 springMVC是一种基于Java实现MVC模型的轻量级Web框架 优点&#xff1a; 使用简单&#xff0c;开发便捷&#xff08;相较于Servelt&#xff09; 灵活性强 使用SpringMVC技术开发web程序流程 创建web工程&#xff08;Maven结构&#xff09; 设置…...

【虚拟机】VMWare的CentOS虚拟机断电或强制关机出现问题

VMware 虚拟机因为笔记本突然断电故障了&#xff0c;开机提示“Entering emergency mode. Exit the shell to continue.”&#xff0c;如下图所示&#xff1a; 解决方法&#xff1a;输入命令&#xff1a; xfs_repair -v -L /dev/dm-0 注&#xff1a;报 no such file or direct…...

探索 RocketMQ:企业级消息中间件的选择与应用

一、关于RocketMQ RocketMQ 是一个高性能、高可靠、可扩展的分布式消息中间件&#xff0c;它是由阿里巴巴开发并贡献给 Apache 软件基金会的一个开源项目。RocketMQ 主要用于处理大规模、高吞吐量、低延迟的消息传递&#xff0c;它是一个轻量级的、功能强大的消息队列系统&…...

vue中v-if和v-for优先级

在Vue中&#xff0c;v-for的优先级高于v-if。这意味着在同一个元素上使用v-if和v-for时&#xff0c;v-for将首先被解析&#xff0c;然后是v-if。 下面是一个代码示例&#xff1a; <template><div><div v-for"item in items" v-if"item.isDispl…...

使用Kotlin写一个将字符串加密成short数组,然后可以解密还原成原始的字符串的功能

文章目录 一、运行效果1.1 单个字符串加解密1.2 多个字符串数组加解密二、源代码2.1 控制流图2.2 实现的源代码一、运行效果 1.1 单个字符串加解密 待加密的单个字符串: 测试字符串转化成short数组-----字节卷动 单个字符串加密后的数据: [19914, -21676, 31702, 23463, 2833…...

windows C#-取消任务列表(上)

如果不想等待异步控制台应用程序完成&#xff0c;可以取消该应用程序。 通过遵循本文的示例&#xff0c;可将取消添加到下载网站内容的应用程序。 可通过将 CancellationTokenSource 实例与每个任务进行关联来取消多个任务。 如果选择 Enter 键&#xff0c;则将取消所有尚未完成…...

Linux---ps命令

​​​​​​Linux ps 命令 | 菜鸟教程 (runoob.com) process status 用于显示进程的状态 USER: 用户名&#xff0c;运行此进程的用户名。PID: 进程ID&#xff08;Process ID&#xff09;&#xff0c;每个进程的唯一标识号%CPU: 进程当前使用的CPU百分比%MEM: 进程当前使用的…...

解决k8s拉取私有镜像401 Unauthorized 问题

拉取镜像时未指定账户和密码通常是因为需要访问的镜像仓库启用了认证&#xff0c;但 Kubernetes 默认配置中未提供访问凭据。要解决此问题&#xff0c;可以按照以下步骤配置镜像仓库的认证信息&#xff1a; 1. 创建 Kubernetes Secret 为镜像仓库配置访问凭据&#xff0c;使用…...

Ruby 模块(Module)

Ruby 模块&#xff08;Module&#xff09; 概述 Ruby 是一种动态、开放源代码的编程语言&#xff0c;以其简洁明了的语法和强大的功能而闻名。在 Ruby 中&#xff0c;模块&#xff08;Module&#xff09;是一个重要的概念&#xff0c;它用于封装一组相关的方法和常量。模块提…...

HAL库的简单介绍以及环境搭建

目录 引言 一、HAL库的基本介绍 二、HAL库开发环境搭建 1、安装JAVA运行环境 2、安装STM32CubeMX 3、在线下载芯片支持包 引言 前面&#xff0c;我们学习了STM32基于寄存器的开发方式&#xff0c;能够更接近底层&#xff0c;但是随着我们学习的越来越深、代码越来与复杂…...

如何在 PyCharm 中配置 HTTP 代理以确保网络连接的顺畅性

如何在 PyCharm 中配置 HTTP 代理以确保网络连接的顺畅性 在配置 PyCharm 的 HTTP 代理以确保网络连接的顺畅性时&#xff0c;需按照一定的步骤进行设置&#xff0c;这不仅有助于确保 PyCharm 能够顺利访问互联网资源&#xff0c;还能保证插件和工具的正常更新与同步。以下是详…...

PHP 8.4 重磅发布了

文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons&#xff1a;JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram&#xff0c;自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 &#xff1f; 5 IDEA必装的插件&…...

LVM缩容

当前环境 rootjmk:~/shell# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 953.9G 0 disk |-nvme0n1p1 259:1 0 512M 0 part /boot/efi |-nvme0n1p2 259:2 0 488M 0 part /boot -nvme0n1p3 …...

Next.js 独立开发教程(三):CSS 样式的完整指南

系列文章目录 Next.js 开发教程(一)&#xff1a;入门指南-CSDN博客 Next.js 开发教程&#xff08;二&#xff09;&#xff1a;从零构建仪表盘应用-CSDN博客 有兴趣的可以蹲个后续&#xff0c;我会陆续发布一系列的文章。 目录 系列文章目录 1. 样式在 Next.js 中的基本支持…...

React (三)

文章目录 项目地址十二、性能优化12.1 使用useMemo避免不必要的计算12.2 使用memo缓存组件,防止过度渲染12.3 useCallBack缓存函数12.4 useCallBack里访问之前的状态(没懂)十三、Styled-Components13.1 安装13.2给普通html元素添加样式13.3 继承和覆盖样式13.4 给react组件添…...

Python数据结构之链表

一、链表 1、目的 解决顺序表存储数据有上限&#xff0c;并且插入和删除操作效率低的问题。 2、概念 链表&#xff1a;链式存储的线性表&#xff0c;使用随机的物理内存存储逻辑上连续的数据。 链表的组成&#xff1a;由一个个结点组成 结点&#xff1a;由数据域和链接域组…...