本文是最后一篇,主要介绍android.bp。:转载自Android 编译之android.bp

作者:qiuxintai
链接:https://www.jianshu.com/p/f69d1c381182
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1. Ninja

1.1 Ninja简介

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

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

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

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

例如,我们可以采用Makefile, go, python等等来维护编译的流程和逻辑。

1.2 Ninja的构建文件

虽然Ninja的构建文件是可读的(human-readable),但是手写不是特别方便。我们可以先来看一段ninja文件的内容:

# This file is used to build ninja itself.
# It is generated by configure.py.ninja_required_version = 1.3# The arguments passed to configure.py, for rerunning it.
configure_args = root = .
builddir = build
cxx = g++
ar = ar
cflags = -g -Wall -Wextra -Wno-deprecated -Wno-missing-field-initializers $
-Wno-unused-parameter -fno-rtti -fno-exceptions -fvisibility=hidden $
-pipe '-DNINJA_PYTHON="python"' -O2 -DNDEBUG -DUSE_PPOLL $
-DNINJA_HAVE_BROWSE -I.
ldflags = -L$builddirrule cxxcommand = $cxx -MMD -MT $out -MF $out.d $cflags -c $in -o $outdescription = CXX $outdepfile = $out.ddeps = gccrule arcommand = rm -f $out && $ar crs $out $indescription = AR $outrule linkcommand = $cxx $ldflags -o $out $in $libsdescription = LINK $out

可以看到,ninja的构建文件,书写起来是不很方便的,所以,我们需要一些ninja构建文件的生成器。

这些生成器就是一些元构建系统(meta-build system),例如Blueprint、CMake等等。

Ninja的基于底层实现使其非常适合嵌入到这些功能更强大的构建系统中。

更多ninja构建文件的生成器,可参考:List of generators producing ninja build files。

Ninja用于构建Google Chrome浏览器,Android,LLVM的一部分。由于CMake可在大多数平台上运行,并且可以生成多种格式的项目文件,包括Ninja。所以Ninja也可以作为CMake的底层实现,在许多其他项目中使用。

1.3 Ninja的下载和使用

Ninja的最新版本为v1.10.2,于2020年11月23日发布:Ninja release v1.10.2。
当然我们也可以下载ninja源码自行编译:

$ git clone git://github.com/ninja-build/ninja.git && cd ninja
$ git checkout release
$ cat README

Ninja的设计哲学和设计背景,是否以及如何在项目中使用Ninja,Ninja的平台支持以及Ninja详细的语言语义等等更多Ninja相关的知识,请参考:
Ninjia使用手册

2. Blueprint

2.1 Blueprint简介

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

在大多数构建系统使用内置规则或特定领域语言来描述将模块描述转换为构建规则的逻辑。

Blueprint将其委托给使用Go编写的针对每个项目的构建逻辑。

对于大型,异构项目,这允许以高级语言维护固有、复杂的构建逻辑,同时仍可以通过修改易于理解的Blueprint文件来对单个模块进行简单更改。

2.2 android中的Blueprint

前面在Ninja的构建文件一节我们提到了,Blueprint是ninja构建文件的生成器。android 编译系统soong集成了Blueprint,Blueprint可将我们编写的android.bp解析生成一个ninja构建文件

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

3. kati

kati 是Google开发的一个实验性的GNU make clone,kati的主要目标是加快Android的增量构建。目前,kati本身并不能提供更快的构建。 而是将Makefile转换为ninja。一开始kati是用go语言开发的,但作者发现使用go写的有性能问题,后来作者又用C++进行了重写,也就是kati变成了ckati(作者的原文描述可以查看android源码目录下的:build/kati/INTERNALS.md)。后续提到kati时,如不特别指出,即是指ckati。

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

android源码目录下的:prebuilts/build-tools下有预置的kati,Android 7.0及以上版本,编译源码时会自动使用kati。大多数情况下,我们不会直接使用kati,但如果你还想了解更多kati的相关信息,可以访问:https://github.com/google/kati。也可以查看android源码目录下的 build/kati/INTERNALS.md 和 build/kati/README.md。

4. soong

4.1 soong简介

在android 6.0版本之前,编译android源码采用的是基于make的编译系统(make-based build system),也就是android的各个库、APK等等目标文件都是采用make来构建的。 但是,由于make在编译时表现出效率不够高、增量编译速度慢等问题,Google在android 7.0版本引进了编译速度更快的soong来替代make。

Soong集成了Ninja, 而Ninja专注于速度,没有条件或流程控制语句,也不支持逻辑运算。但它允许以其它语言如来维护这些复杂的编译流程和逻辑。例如,我们可以继续采用makefile, 或者采用go语言来维护编译流程和逻辑。

上面已经提到了Ninja,Blueprint, kati等等好几种工具,为了完整、快速的构建一个android系统,就需要一个“管家”来协调这些工具。例如,将.bp转换成ninja时使用Blueprint, 将Makefile转换成ninja时使用kati。这个选择转换工具、选择解析框架、解析维护构建逻辑的“管家”就是soong。

编译android源码时,soong也会被自动使用,我们可以和原来一样:

首先,source build/envsetup.sh。

然后,lunch选择target。

最后,使用m、mm、mmm或者make来编译指定的模块或者整个系统。

但是,m、mm、mmm或者make最终都会使用soong来编译。

因为source之后,build/envsetup.sh中已经将make指向soong了

function get_make_command()
{# If we're in the top of an Android tree, use soong_ui.bash instead of makeif [ -f build/soong/soong_ui.bash ]; then# Always use the real make if -C is passed infor arg in "$@"; doif [[ $arg == -C* ]]; thenecho command makereturnfidoneecho build/soong/soong_ui.bash --make-modeelseecho command makefi
}function make()
{_wrap_build $(get_make_command "$@") "$@"
}function m()
{local T=$(gettop)if [ "$T" ]; then_wrap_build $T/build/soong/soong_ui.bash --make-mode $@elseecho "Couldn't locate the top of the tree.  Try setting TOP."return 1fi
}function mm()
{local T=$(gettop)# If we're sitting in the root of the build tree, just do a# normal build.if [ -f build/soong/soong_ui.bash ]; then_wrap_build $T/build/soong/soong_ui.bash --make-mode $@else# Find the closest Android.mk file.local M=$(findmakefile)local MODULES=local GET_INSTALL_PATH=local ARGS=# Remove the path to top as the makefilepath needs to be relativelocal M=`echo $M|sed 's:'$T'/::'`if [ ! "$T" ]; thenecho "Couldn't locate the top of the tree.  Try setting TOP."return 1elif [ ! "$M" ]; thenecho "Couldn't locate a makefile from the current directory."return 1elselocal ARGfor ARG in $@; docase $ARG inGET-INSTALL-PATH) GET_INSTALL_PATH=$ARG;;esacdoneif [ -n "$GET_INSTALL_PATH" ]; thenMODULES=ARGS=GET-INSTALL-PATH-IN-$(dirname ${M})ARGS=${ARGS//\//-}elseMODULES=MODULES-IN-$(dirname ${M})# Convert "/" to "-".MODULES=${MODULES//\//-}ARGS=$@fiif [ "1" = "${WITH_TIDY_ONLY}" -o "true" = "${WITH_TIDY_ONLY}" ]; thenMODULES=tidy_onlyfiONE_SHOT_MAKEFILE=$M _wrap_build $T/build/soong/soong_ui.bash --make-mode $MODULES $ARGSfifi
}function mmm()
{local T=$(gettop)if [ "$T" ]; thenlocal MAKEFILE=local MODULES=local MODULES_IN_PATHS=local ARGS=local DIR TO_CHOPlocal DIR_MODULESlocal GET_INSTALL_PATH=local GET_INSTALL_PATHS=local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')for DIR in $DIRS ; doDIR_MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'`DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'`# Remove the leading ./ and trailing / if any exists.DIR=${DIR#./}DIR=${DIR%/}if [ -f $DIR/Android.mk -o -f $DIR/Android.bp ]; thenlocal TO_CHOP=`(\cd -P -- $T && pwd -P) | wc -c | tr -d ' '`local TO_CHOP=`expr $TO_CHOP + 1`local START=`PWD= /bin/pwd`local MDIR=`echo $START | cut -c${TO_CHOP}-`if [ "$MDIR" = "" ] ; thenMDIR=$DIRelseMDIR=$MDIR/$DIRfiMDIR=${MDIR%/.}if [ "$DIR_MODULES" = "" ]; thenMODULES_IN_PATHS="$MODULES_IN_PATHS MODULES-IN-$MDIR"GET_INSTALL_PATHS="$GET_INSTALL_PATHS GET-INSTALL-PATH-IN-$MDIR"elseMODULES="$MODULES $DIR_MODULES"fiMAKEFILE="$MAKEFILE $MDIR/Android.mk"elsecase $DIR inshowcommands | snod | dist | *=*) ARGS="$ARGS $DIR";;GET-INSTALL-PATH) GET_INSTALL_PATH=$DIR;;*) if [ -d $DIR ]; thenecho "No Android.mk in $DIR.";elseecho "Couldn't locate the directory $DIR";fireturn 1;;esacfidoneif [ -n "$GET_INSTALL_PATH" ]; thenARGS=${GET_INSTALL_PATHS//\//-}MODULES=MODULES_IN_PATHS=fiif [ "1" = "${WITH_TIDY_ONLY}" -o "true" = "${WITH_TIDY_ONLY}" ]; thenMODULES=tidy_onlyMODULES_IN_PATHS=fi# Convert "/" to "-".MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}ONE_SHOT_MAKEFILE="$MAKEFILE" _wrap_build $T/build/soong/soong_ui.bash --make-mode $DASH_ARGS $MODULES $MODULES_IN_PATHS $ARGSelseecho "Couldn't locate the top of the tree.  Try setting TOP."return 1fi
}

使用make构建项目,主要工作是编写Makefile;

类似的,使用soong构建项目,主要工作是编写bp文件。关于bp文件我们会在接下来的第5节中详细介绍。

4.2 androidmk

soong中还集成了一个非常有用的工具androidmk。androidmk可以将android.mk转换成android.bp。我们可以使用androidmk来转换代码中已有的android.mk,以此来减少重写android.bp的工作量。例如,我们将一个Android.mk转换成Android.bp:

androidmk Android.mk > Android.bp

注意:androidmk工具可以转换变量,模块,注释和某些条件,但是自定义的Makefile规则,复杂的条件语句或其它的额外的include语句,必须手动转换。

在现有版本,由于kati工具的存在,继续使用android.mk也是没有问题的。但是,也许在将来的某一天,Google可能会不再支持Makefile。因此,建议新增的模块采用android.bp,存量的android.mk,在条件允许的情况下,也应当尽量转换成android.bp

4.3 bpfmt

为了方便格式化,Soong还包含了一个用于格式化Android.bp文件的工具bpfmt,类似于gofmt。 以一个简单的bp文件为例:

cc_binary {name: "gzip",srcs: ["src/test/minigzip.c","src/test/utils.c",],shared_libs: ["libz"],stl: "none",
}

Android.bp的规范格式包括:

  • 4个空格缩进。
  • 多元素列表的每个元素后的换行符。
  • 在lists和maps的结尾处始终包含一个逗号。

我们可以使用bpfmt工具来规范格式化Android.bp文件。例如,要递归地格式化当前目录中的所有Android.bp文件:

bpfmt -w .

4.4 ninja,Blueprint,kati,androidmk与Soong的关系和作用

  • kati可以将Android.mk文件转换成ninja文件。
  • androidmk可以将Android.mk文件转换成Android.bp文件
  • Blueprint可以将Android.bp文件转换成ninja文件。
  • Blueprint,kati,androidmk由Soong调用和协调,一起合作完成android源码的构建。

它们的关系示意图如下:

5. Android.bp

5.1 bp文件的命名与文件格式

soong的编译配置文件以.bp结尾,通常命名为Android.bp,但也有少数情况不以Android.bp命名。例如:frameworks/rs/support.bp。与Makefile一样,使用soong编译前,会遍历所有以bp为后缀名的文件。因此,soong的编译配置文件只要以.bp结尾即可。

5.2 模块(module)

bp文件中的模块(module) 以模块类型(module type)开头,后面跟着一系列的属性(property)。每个模块都必须具有一个属性名为name的属性,并且name的属性值在所有Android.bp文件中必须是唯一的。bp文件的内容与JSON、Bazel BUILD很像,模块的格式为:

[module type] {name: "[name value]",[property1 name]:"[property1 value]",[property2 name]:"[property2 value]",
}

一个简单的bp文件:

cc_binary {name: "gzip",srcs: ["src/test/minigzip.c"],shared_libs: ["libz"],stl: "none",
}
常见的模块类型有:
cc_library,
cc_library_headers,
cc_library_shared,
cc_library_static,
android_app,
android_app_certificate,
java_library,
java_library_static,
java_sdk_library等等。

soong预置了一系列的模块类型和属性,芯片原厂也会添加一些自定义的模块类型和属性,例如,MTK平台就定义了一些以mtk开头的模块类型。如果想了解更多,已有源码并且已编译的可以查看:out/soong/docs/soong_build.html。如果没有源码,也可查看AOSP的在线文档:$AOSP/out/soong/docs/soong_build.html

5.2.1 默认模块(defaults)

soong提供了一系列xx_defaults模块类型,例如:cc_defaults, java_defaults, doc_defaults, stub_defaults等等。模块类型为xx_defaults的模块提供了一组可由其它模块继承的属性。其它模块可以通过添加属性`defaults:[“ <:default_module_name>”]“来指定继承xx_defaults类型的模块定义的属性。因此,我们定义一个新模块时,可以通过将默认模块的属性放在name属性之后,其它属性之前,来合并两个模块的属性。
例如:

java_defaults {name: "framework-defaults",installable: true,srcs: [// From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS"core/java/**/*.java","graphics/java/**/*.java","location/java/**/*.java","lowpan/java/**/*.java","media/java/**/*.java",]//......省略无关
}java_library {name: "framework",defaults: ["framework-defaults"],javac_shard_size: 150,
}java_library {name: "framework-annotation-proc",defaults: ["framework-defaults"],// Use UsedByApps annotation processorplugins: ["unsupportedappusage-annotation-processor"],
}

这个例子中,模块aidl_mapping在srcs属性中引用了framework-defaults。

5.2.2 引用模块

一个模块可以通过它的模块名来引用。在默认模块这一小节中,其实我们已经引用过了其它模块了。这里我们再来一个例子:

cc_binary {name: "app",shared_libs: ["libfoo"],
}

例子中,libfoo模块必须存在才有效,并且在构建树中有且仅有一个libfoo模块时才有效。

5.3 文件列表

一个属性的属性值为一系列文件时,属性值也可以采用全局匹配模式和输出路径扩展。

全局匹配模式可以包含普通的Unix通配符*,例如“ * .java”。

全局匹配模式也可以包含单个**通配符作为路径元素,它将匹配零个或多个路径元素。 例如,java / ** / *。java将匹配 java/Main.java 和 java/com/android/Main.java。

输出路径扩展采用:module或:module {.tag}格式,其中module是生成输出文件的模块的名称,并且扩展为这些输出文件的列表。 使用可选的{.tag}后缀,模块可以根据tag生成不同的输出列表。
例如:

// AIDL interface between storaged and framework.jar
filegroup {name: "storaged_aidl",srcs: ["binder/android/os/IStoraged.aidl",],path: "binder",
}java_library_static {name: "services.core.unboosted",srcs: ["java/**/*.java",":storaged_aidl",],//......省略无关
}

5.4 类型和变量

Android.bp文件中,变量和属性是强类型的,变量是基于首次分配动态地创建的,属性是根据模块类型静态地创建的。 支持的类型有:

Bool (true or false)
Integers (int)
Strings ("string")
Lists of strings (["string1", "string2"])
Maps ({key1: "value1", key2: ["value2"]})

maps可以是任何类型的值,包括嵌套maps。 Lists和Map的最后一个值后面可能带有逗号。
字符串可以使用\“包含双引号,例如” cat \“ a b \”“。

5.5 注释

Android.bp文件可以和C/C++的注释类似,可以包含多行注释和单行注释。

多行注释:/ * 注释 * /
单行注释://注释。

5.6 运算符

Android.bp文件可以使用+运算符附加字符串,字符串列表和映射。 整数可以使用+运算符求和。 追加映射会在两个映射中生成键的并集,并追加两个映射中都存在的任何键的值。
例如:

cc_test {name: "libandroidfw_tests",host_supported: true,defaults: ["libandroidfw_defaults"],cppflags: [// This is to suppress warnings/errors from gtest"-Wno-unnamed-type-template-args",],srcs: [// Helpers/infra for testing."tests/CommonHelpers.cpp","tests/TestHelpers.cpp","tests/TestMain.cpp",// 省略无关部分],static_libs: ["libgmock"],target: {android: {srcs: ["tests/BackupData_test.cpp","tests/ObbFile_test.cpp",],shared_libs: common_test_libs + ["libui"],},host: {static_libs: common_test_libs + ["liblog", "libz"],},},data: ["tests/data/**/*.apk"],
}

注意:
除了上述介绍的内容之外,Soong还包含了包、命名空间、名称解析、可见性、soong配置变量等等内容。但是,我在Android 9.0和Android 10.0两份源码中都没有找到合适的例子,本人也不是很理解,为避免误导他人,这些内容就不介绍了,如果想了解更多,请参考:https://android.googlesource.com/platform/build/soong/

6. Android.mk和Android.bp的区别

Android.mk文件通常可以包含多个同名模块(例如,用于库的静态(static)和共享(shared)版本,用于不同主机(host)的版本,用于不同设备(device)版本)。

Android.bp文件的每个模块都需要唯一的名称,但是单个模块可以构建为多个变体。例如,通过添加host_supported:true。 包含多个同名模块的Android.mk被androidmk转换成Android.bp之后,将生成多个冲突的模块,这些模块必须手动处理,将同名模块改为一个具有多个变体的模块,这些在target:{android:{},host:{}}块内的变体可以有区别,例如,引用不同的源文件,不同架构的共享库文件等等。

Soong故意不支持Android.bp文件中的大多数条件。 Google建议从构建中删除大多数条件。Soong将本地支持的大多数条件将转换为map属性。 构建模块时,将选择map中的属性之一,并且将其值追加到模块顶层的同名属性中。
例如,要支持特定于体系结构的文件:

cc_library {...srcs: ["generic.cpp"],arch: {arm: {srcs: ["arm.cpp"],},x86: {srcs: ["x86.cpp"],},},
}

为arm平台构建时,将构建generic.cpp和arm.cpp。 在为x86平台构建时,将构建generic.cpp和x86.cpp。

7.Android.bp实战

7.1 编译APP

以DocumentsUI为例(为看起来清晰,有整理和部分删减):

android_app {name: "DocumentsUI",manifest: "AndroidManifest.xml",srcs: ["src/**/*.java",],resource_dirs: ["res",],static_libs: ["androidx.appcompat_appcompat","androidx.recyclerview_recyclerview",],privileged: true,certificate: "platform",optimize: {proguard_flags_files: ["proguard.flags"],},sdk_version: "system_current",min_sdk_version: "28",target_sdk_version: "28",required: ["privapp_whitelist_com.android.documentsui"],
}

可以看到,Android.bp非常简洁,而且命名很清晰,基本上看属性名就知道是起什么作用的。这里只列出了android_app的常用属性,并没有将它的所有属性列出来,开发过程中如果需要配置APP的其它属性,请参考:out/soong/docs/soong_build.html。如果没有源码,也可查看AOSP的在线文档:$AOSP/out/soong/docs/soong_build.html

7.2 编译java库

java_library {name: "updatable-media",srcs: [":updatable-media-srcs",],aidl: {export_include_dirs: ["apex/java",],// It would be great if we don't need to add include_dirs for public// parcelable classes. Find a better way.include_dirs: [// To refer:// android.os.Bundle// android.os.ResultReceiver"frameworks/base/core/java",],},permitted_packages: ["android.media",],installable: true,// Make sure that the implementaion only relies on SDK or system APIs.no_framework_libs: true,libs: [// The order matters. android_system_* library should come later."framework_media_annotation","android_system_stubs_current",],
}

7.3 编译java静态库

java_library_static {name: "services.core.unboosted",aidl: {include_dirs: ["frameworks/native/aidl/binder","system/core/storaged/binder","system/netd/server/binder","system/vold/binder",],},srcs: ["java/**/*.java",":netd_aidl",":netd_metrics_aidl",":installd_aidl",":storaged_aidl",":vold_aidl",":mediaupdateservice_aidl","java/com/android/server/EventLogTags.logtags","java/com/android/server/am/EventLogTags.logtags",],libs: ["services.net","android.hardware.light-V2.0-java","android.hardware.power-V1.0-java","android.hardware.tv.cec-V1.0-java","android.hidl.manager-V1.0-java",],static_libs: ["time_zone_distro","time_zone_distro_installer","android.hardware.authsecret-V1.0-java","android.hardware.broadcastradio-V2.0-java","android.hardware.health-V1.0-java","android.hardware.health-V2.0-java","android.hardware.weaver-V1.0-java","android.hardware.biometrics.fingerprint-V2.1-java","android.hardware.oemlock-V1.0-java","android.hardware.tetheroffload.control-V1.0-java","android.hardware.vibrator-V1.0-java","android.hardware.configstore-V1.0-java","android.hardware.contexthub-V1.0-java",],
}

7.4 编译共享库(shared)

cc_library_shared {name: "libbluetooth_jni",compile_multilib: "first",srcs: ["bluetooth_socket_manager.cc","com_android_bluetooth_btservice_AdapterService.cpp","com_android_bluetooth_hfp.cpp","com_android_bluetooth_hfpclient.cpp","com_android_bluetooth_a2dp.cpp","com_android_bluetooth_a2dp_sink.cpp","com_android_bluetooth_avrcp_controller.cpp","com_android_bluetooth_avrcp_target.cpp","com_android_bluetooth_hid_host.cpp","com_android_bluetooth_hid_device.cpp","com_android_bluetooth_hearing_aid.cpp","com_android_bluetooth_pan.cpp","com_android_bluetooth_gatt.cpp","com_android_bluetooth_sdp.cpp","IUserManager.cc","permission_helpers.cc",],header_libs: ["libbluetooth_headers"],include_dirs: ["libnativehelper/include/nativehelper","system/bt/types",],shared_libs: ["libandroid_runtime","libbinder","libbluetooth-binder","libchrome","libnativehelper","liblog","libutils",],static_libs: ["libbluetooth-types","libcutils",],cflags: ["-Wall","-Werror","-Wextra","-Wno-unused-parameter",],sanitize: {scs: true,},
}

7.5 编译静态库(static)

cc_library_static {name: "libmedia_player2_util",defaults: [ "libmedia_defaults" ],srcs: ["AudioParameter.cpp","BufferingSettings.cpp","DataSourceDesc.cpp","MediaCodecBuffer.cpp","Metadata.cpp","NdkWrapper.cpp",],shared_libs: ["libbinder","libcutils","liblog","libmediandk","libnativewindow","libmediandk_utils","libstagefright_foundation","libui","libutils",],export_shared_lib_headers: ["libbinder","libmediandk",],header_libs: ["media_plugin_headers",],include_dirs: ["frameworks/av/media/ndk",],static_libs: ["libstagefright_rtsp","libstagefright_timedtext",],export_include_dirs: ["include",],cflags: ["-Werror","-Wno-error=deprecated-declarations","-Wall",],sanitize: {misc_undefined: ["unsigned-integer-overflow","signed-integer-overflow",],cfi: true,},
}

8. 结语

Google在Android N就引入了Soong,目的是替换make。但是,很遗憾的是截止到Android Q,甚至Android R,它们的源码中都还存在大量的Makefile。也许make就是构建语言里的C语言,无论世界如何发展变化,它的生命力依然旺盛。未来的很长一段时间内Android.bp和Android.mk可能会一直共存,一起完成Android系统源码的构建。这并不代表我们可以不用去学习Android.bp,技术总是不断的发展,我们则需要不断的学习才能适应技术的发展。

9.本文参考

https://android.googlesource.com/platform/build/soong/
https://android.googlesource.com/platform/build/soong/+/HEAD/docs/best_practices.md#network-access

作者:qiuxintai
链接:https://www.jianshu.com/p/f69d1c381182
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Android——编译(三):android.bp的相关知识相关推荐

  1. python实现单例模式的三种方式及相关知识解释

    python实现单例模式的三种方式及相关知识解释 模块模式 装饰器模式 父类重写new继承 单例模式作为最常用的设计模式,在面试中很可能遇到要求手写.从最近的学习python的经验而言,singlet ...

  2. java窗口三栏布局_移动端的flex三栏布局的相关知识介绍(代码示例)

    本篇文章给大家带来的内容是关于移动端的flex三栏布局的相关知识介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 默认情况下先显示移动端,通过 @media 属性适配屏 ...

  3. 【Python之pymysql库学习】三.sql语句的相关知识(保姆级图文+实现代码)

    目录 实现效果 实现思路 实现代码 总结 欢迎关注 『Python之pymysql库学习』 系列,持续更新中 欢迎关注 『Python之pymysql库学习』 系列,持续更新中 实现效果 把给读取数据 ...

  4. Android(三)原生开发基本知识

    文章目录 一.基本认识 1.目的:实现业务逻辑,生成可用apk 2.打开Android Studio([环境搭建](https://blog.csdn.net/liangwenrong/article ...

  5. 全志 android 编译,全志Android SDK编译详解(二)

    注意要确定安装了jdk) 第一步: cd  lichee; ./build.sh  -p sun5i_elite -k 3.0  (apt-get install uboot-mkimage需要安装m ...

  6. android 编译主机,Android】源码编译 ---zzz

    问题解决 参考 1)/bin/bash: prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-gcc: 权限不够 解决:chmod a+x ...

  7. H6机顶盒Android编译[2]-Android编译

    注意:本人也是第一次android编译,记录其过程为方便自己,同时给初学者提供参考,不正确之处还望包含指正! 前言 使用易新泰的H6机顶盒平台,搭载全志H6处理器,使用易新泰提供的SDK环境,使用ub ...

  8. ogre android 编译,Ogre3d Android平台编译教程

    上一篇我们讲了Ogre3d 在 Window平台的编译流程方法 这一篇我们介绍 Ogre3d 编译到Android 平台的方法.可以和官方英文教程对照学习. 转载自博客 http://blog.csd ...

  9. android 自带gps定位Location相关知识

    android自带gps定位功能相信大家都不会太陌生了,都有所涉及.简单的写了一个示例程序,获取经纬度还有其它相关数据的代码,还有其他相关的知识,比如直接跳转到打开系统gps设置的界面.还有一个bug ...

最新文章

  1. 软件项目开发无成熟框架套路之成本代价
  2. NeHe教程Qt实现——lesson13
  3. perl 分析mysql binlog
  4. python中魔法方法__str__与__repr__的区别
  5. 【问链-区块链基础知识系列】 第十四课 数字货币交易所的前世、今生和未来(一)
  6. corners边框_安卓中设置(shape)圆角背景和边框(stroke)相关的问题
  7. maya中英文切换插件_老司机都在用的30款maya常用插件
  8. windows下远程连接Linux桌面
  9. getsockopt和setsockopt函数
  10. 绕开登录进行爬虫_爬虫小偏方:绕开登陆和访问频率控制
  11. Python自动对Word文件中Python程序进行着色
  12. 厦门高职计算机专业,厦门高职,厦门高职学校,厦门高职学校哪个相对好一些 - IT教育频道...
  13. python模块之junos-eznc
  14. Mujoco编程开发-官方文档
  15. 计算机理解人的情感的前提是,情感识别
  16. 广东迅视资管 别让“顺风车”再度行驶至安全边缘
  17. 四川农大2020计算机专业录取分数线,2020四川农业大学研究生分数线汇总(含2016-2019历年复试)...
  18. 力扣 167. 两数之和 II - 输入有序数组
  19. python实例-银行管理系统(特简单的那种)
  20. 【附源码】计算机毕业设计java羽毛球场地管理系统设计与实现

热门文章

  1. 2022年中国元宇宙市场投融资情况分析:1-4月投融资金额已完成81.2亿元,其中元宇宙游戏占36.27%[图]
  2. Linux/c++服务器开发方向的重点
  3. 《蚂蚁塔防》Antbuster
  4. 《投名状》,真正的赢家到底是谁?
  5. 阶乘之和 大数阶乘之和
  6. 一次性查找并统一替换多个 Excel 中的多个关键字
  7. matlab机器人运动画gif动图
  8. 量子计算或可解救全球芯片危机
  9. 45个有用的JavaScript技巧,值得你学习
  10. js计算机制作,计算机等级考试:使用Javascript制作声音按钮