写点什么

Android 编译系统初探

作者:桑榆
  • 2022 年 8 月 01 日
  • 本文字数:2921 字

    阅读完需:约 10 分钟

零.从 HelloWorld.cpp 说起

下面是一个最简单的 C++程序,我们通过它来引入我们今天要讲解的 Android 编译系统

/*************************************************************************@File Name : HelloWorld.cpp@Author : SangYu@Email : sangyu.code@gmail.com@Description : Test for g++************************************************************************/#include <iostream>int main(){    std::cout<<"Hello World!"<<std::endl;    return 0;}
复制代码

g++编译指令:g++ -o main HelloWorld.cpp 

这里我们只有一个 cpp 文件,只需要一条命令即可编译出我们的可执行文件 main.exe

一.Make 与 Makefile

在大型项目开发过程中,我们会有不只一个 module,同时有数以万计的 cpp 文件,它们的编译组织(先编译谁,后编译谁,编译的库依赖哪些静态库,动态库......)这些问题我们就不能够再通过一条条命令来解决。Make 应运而生,帮助我们组织整个大型项目的编译过程,更重要地,能够识别出哪部分需要重新编译,并重新进行编译,并不需要重新编译整体项目。

The make utility automatically determines which pieces of a large program need to be recompiled, and issues commands to recompile them.

make 官网:www.gnu.org/software/ma…

Makefile---描述了整个程序是如何编译链接的,Make 的工作依赖于 MakeFile 的规则。

原书中的 Makefile 例子:

edit : main.o kbd.o command.o display.o \        insert.o search.o files.o utils.o        cc -o edit main.o kbd.o command.o display.o \            insert.o search.o files.o utils.omain.o : main.c defs.h        cc -c main.ckbd.o : kbd.c defs.h command.h        cc -c kbd.ccommand.o : command.c defs.h command.h        cc -c command.cdisplay.o : display.c defs.h buffer.h        cc -c display.cinsert.o : insert.c defs.h buffer.h        cc -c insert.csearch.o : search.c defs.h buffer.h        cc -c search.cfiles.o : files.c defs.h buffer.h command.h        cc -c files.cutils.o : utils.c defs.h        cc -c utils.cclean :    rm edit main.o kbd.o command.o display.o \        insert.o search.o files.o utils.o
复制代码

一个简单的例子:

#ifndef _ADD_HEAD_#define _ADD_HEAD_int AddInt(int num1, int num2);#endif
复制代码


#include <iostream>#include "Add.h"int AddInt(int num1, int num2){    return num1 + num2;}
int main(){ int num1,num2; std::cout<<"Entry two number:"; std::cin>>num1>>num2; std::cout<<"num1+num2:"<<num1<<"+"<<num2<<"="<<AddInt(num1,num2)<<std::endl; return 0;}
复制代码


exe_name=mainprogram_name=Addobjects_name=$(program_name).o$(exe_name):$(objects_name)        g++ -o $(exe_name) $(objects_name)$(program_name).o:$(program_name).h
.PHONY: cleanclean: -rm $(exe_name) $(objects_name)
复制代码



二.Android 编译系统

1.Android Make Build System---Android.mk

Android 基于 Make 做的 Android.mk,目前大部分 HAL 层代码和 JNI 代码都是使用该种方式进行的编译 Android.mk 的相关语法与关键字:developer.android.com/ndk/guides/…

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)LOCAL_MODULE := libxmlrpc++LOCAL_MODULE_HOST_OS := linux
LOCAL_RTTI_FLAG := -frttiLOCAL_CPPFLAGS := -Wall -Werror -fexceptionsLOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src
LOCAL_SRC_FILES := $(call \ all-cpp-files-under,src)include $(BUILD_SHARED_LIBRARY)
复制代码

Android.mk 方式的缺陷:

The Make build system is widely supported and used, but at Android's scale became slow, error prone, unscalable, and difficult to test. The Soong build system provides the flexibility required for Android builds.

编译变慢/易错的/无法扩展/难以测试


2.Soong build system---Android.bp

Soong 构建系统是在 Android 7.0 (Nougat) 中引入的,旨在取代 Make。它利用 Kati GNU Make 克隆工具和 Ninja 构建系统组件来加速 Android 的构建。


根据设计,Android.bp 文件很简单。它们不包含任何条件语句,也不包含控制流语句;所有复杂问题都由用 Go 编写的构建逻辑处理。


cc_library_shared {    name: “libxmlrpc++”,        rtti: true,    cppflags: [        “-Wall”,        “-Werror”,        “-fexceptions”,    ],
export_include_dirs: [“src”], srcs: [“src/**/*.cpp”], target: { darwin: { enabled: false, }, },}
复制代码


https://source.android.google.cn/compatibility/tests/development/blueprints

(1).Ninja

Ninja 是一个专注于速度的小型构建系统。它与其他构建系统在两个主要方面不同:


  • Ninja 的输入文件被设计为由更高级的构建系统生成。

  • Ninja 被设计为尽可能快地运行构建, 其他构建系统基于高级语言,而 Ninja 基于汇编。


Ninja 基于汇编,专注于速度,不支持分支、循环等流程控制,也不支持逻辑运算,但它允许以其它语言如来维护这些复杂的编译流程和逻辑。例如,我们可以采用 Makefile, go, python 等等来维护编译的流程和逻辑。

(2).Blueprint

Blueprint 是一个元构建系统,该系统读取 Blueprint 文件来描述需要构建的模块,并生成一个 Ninja 清单来描述需要运行的命令及其依赖项。


Blueprint 是 ninja 构建文件的生成器。android 编译系统 soong 集成了 Blueprint,Blueprint 可将我们编写的 android.bp 解析生成一个 ninja 构建文件。我们在编译一个模块时,只需要将这个模块的 android.bp 文件配置好,编译系统会自动为这个模块生成 ninja 清单,最终使用 ninja 来调用 gcc、clang、java、dex、aapt2 等等命令来构建模块。

(3).kati

简单地说,kati 就是一个转换工具,它可以将 Makefile 和.mk 文件转换为 ninja。

(4).Soong

Soong集成了 Ninja, 而 Ninja 专注于速度,没有条件或流程控制语句,也不支持逻辑运算。但它允许以其它语言如来维护这些复杂的编译流程和逻辑。例如,我们可以继续采用 makefile, 或者采用 go 语言来维护编译流程和逻辑。上面已经提到了 Ninja,Blueprint, kati 等等好几种工具,为了完整、快速的构建一个 android 系统,就需要一个“管家”来协调这些工具。例如,将.bp 转换成 ninja 时使用 Blueprint, 将 Makefile 转换成 ninja 时使用 kati。这个选择转换工具、选择解析框架、解析维护构建逻辑的“管家”就是 soong。

(5).androidmk

androidmk 可以将 android.mk 转换成 android.bp。

(6).bpfmt

用于格式化 Android.bp 文件的工具 bpfmt,类似于 gofmt。


Android.bp 的规范格式包括:


  • 4 个空格缩进。

  • 多元素列表的每个元素后的换行符。

  • 在 lists 和 maps 的结尾处始终包含一个逗号。

(7).ninja,Blueprint,kati,androidmk 与 Soong 的关系和作用

  • kati 可以将 Android.mk 文件转换成 ninja 文件。

  • androidmk 可以将 Android.mk 文件转换成 Android.bp 文件

  • Blueprint 可以将 Android.bp 文件转换成 ninja 文件。

  • Blueprint,kati,androidmk 由 Soong 调用和协调,一起合作完成 android 源码的构建。


发布于: 刚刚阅读数: 3
用户头像

桑榆

关注

北海虽赊,扶摇可接;东隅已逝,桑榆非晚! 2020.02.29 加入

Android手机厂商-相机软件系统工程师 爬山/徒步/Coding

评论

发布
暂无评论
Android编译系统初探_编译_桑榆_InfoQ写作社区