Android build system (Build System) analysis

Anatomy of Android Build System

How are Android prebuilt apps made, and what is the build system behind them?

This article aims to share knowledge about the Android build system and integration with original equipment manufacturers (OEMs), and simplify the process of understanding the complex mechanisms of AOSP. This article serves as a quick guide into the world of the AOSP build system, rather than manually consulting the various files and their internal workflow. The Gradle build system is not involved. The Android platform build system is completely different from the Gradle-based Android application build system. It is worth mentioning that, have you ever thought about how Android pre-built applications are made and what is the build system behind them? Finding high-quality resources about the core and inner workings of the Android operating system is a common pain point for most Android developers. Framework development is not easy, and besides, building a Framework application with its complexities can be confusing.

Main points of this article

By the end of this article, you will understand and understand all the intricacies, functions, definitions and associations about the build system of the Android platform. The following are four points discussed in detail:

  1. environment settings
    • runsource build/envsetup.sh
  2. Select the target product to build
    • runlunch <option>
  3. build code
    • run make <module-name>orm <module-name>
  4. run/flash/install on device
    • adb pushPush apk via
    • By fastbootflashing the mirror

But before diving into the above 4 steps, there are some prerequisites:

A. Evolution of the Android build system

B. Android.bpandblueprint

C. Download AOSP source code

A. Evolution of the Android build system

  • Before Android N version (v7.0),

Compilation is done by the GNU make tool. All rules are written in a configuration file named Makefile, and the make tool will compile the code according to the instructions in the Makefile.

What is make? make is an automated build tool that automatically compiles source code into executable programs and library files by reading Makefile.

What is a Makefile or .mk file? Makefile defines the dependencies of the target program and the relevant rules for generating the target program.

Just like Gradle has build.gradle, make has Makefile (main.mk).

  • After Android N version (v7.0),

At the Android level, GNU Make compilation became slow, error-prone, non-scalable, and difficult to test, so Google introduced the Ninja build system, which enables the flexibility of the Android build system through .ninja files, because the files are human- .ninjareadable .

What are ninjas? It is a compiled framework that will be compiled into files based on the corresponding .bp (blueprint) files .ninja. Typically, .ninjathe files are not modified manually, but rather compiled by .bp(blueprint)converting to a file ..ninja.ninja

What are soong and .bp files? To generate .ninjafiles, Google introduced the soong build system, which includes a blueprintingtool called soong for Android.bpparsing files into .ninjafiles, and the kati tool for Android.mkconverting files into .ninjafiles.

What is kati? This is a Golang and C++ based tool whose main function is to convert complex Android.mk files to ninja files.

P.S. Soong also compiled and generated a androidmkcommand to convert Android.mk file to Android.bp file.

Just like Gradle has it build.gradle, ninja has it build.ninja.

  • In the 2020 Android release notes, Google stated that they will start migrating the build system to Bazel.

B. Learn more about Android.bp and blueprinting

In Android.bp we build what we need depending on the module type.

The commonly used types and methods are as follows:

android_app: Used to build apk, its function is the same as BUILD_PACKAGE of Android.mk.
java_library: Generate a .jar package from a .class file. The generated jar package is not suitable for direct installation on the device, but it is used as a static_libs dependency.
static_libs: A library that is resolved by the caller at compile time and copied into the target application by the compiler.
android_library: Link the source code together with the Android resource files into the device's .jar file.
android_libraryThere are different variants of .classgenerating .jara package from a file, and from a aapt2generated package-res.apkfile named . The generated apk file cannot be installed directly on the device, but can be used as a dependency android_appof a module . : Compile using the SDK's hidden API : Specifies the signature to use, as above, using the platform signature. : imports the Android archive (aar) into , which must be used as a dependency of the module .static_libs
platform_apis
certificate
android_library_importandroid_appandroid_appstatic_libs

Let's try to create a random sample application called GlanceApp, the following is the sample Android.bp file, in the GlanceApp module, import glance_android_libraryas a static dependency, and as glance_android_librarydependencies , to build .glance_java_librarycontent_aar_pluginGlanceApp.apk

java_library {
    
    
    name: "glance_java_library",
    srcs: [
        "src/com/android/glance/file/**.java",
    ],
    jarjar_rules: ":jarjar-rules-shared",
}

android_library {
    
    
    name: "glance_android_library",
    manifest: "tests/AndroidManifest-base.xml",
    additional_manifests: ["tests/AndroidManifest.xml"],
    resource_dirs: [
        "res",
    ],
    srcs: [
        "src/**/*.kt",
        "src/**/*.java",
    ],
    static_libs: [
        "glance_java_library",
        "content_aar_plugin",
        "glide-annotation-and-compiler-prebuilt",
    ],
    libs: [
        "android.test.base",
    ],
    kotlincflags: ["-Xjvm-default=enable"],
    aaptflags: [
        "--extra-packages",
    ],
    plugins: ["dagger2-compiler","glide-annotation-processor"],
}

android_app {
    
    
    name: "GlanceApp",
    static_libs: [
        "glance_android_library",
    ],
    resource_dirs: [],
    platform_apis: true,
    system_ext_specific: true,
    certificate: "platform",
    privileged: true,
    kotlincflags: ["-Xjvm-default=enable"],
    dxflags: ["--multi-dex"],
    required: [ "privapp_whitelist_com.android.glance",],
    aaptflags: ["--auto-add-overlay",],
    platform_apis: true,
    certificate: "platform",
    optimize: {
    
    enabled: false,},
    sdk_version: "core_platform",
}

android_library_import {
    
    
    name: "content_aar_plugin",
    aars: ["libs/content_aar_plugin.aar"],
    static_libs: ["androidx-constraintlayout_constraintlayout",]
}

So, will be content_aar_pluginadded to your application, also adding glide (3rd party library) as a dependency.

Since we have privilegedset this to true, and set the certificate to platform, GlanceApp will act as a system privileged application.

C. Download AOSP source code

If you have not downloaded the AOSP source code, please use the following command to download the source code:

mkdir android-13.0.0_r12
cd android-13.0.0_r12
repo init --depth=1 -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r12
repo sync  --force-sync --no-clone-bundle --no-tags -j$(nproc)

Convert Android.mk and Android.bp into Ninja compiled files
The flowchart illustrates the following:

  1. Generate files from Android.mkand other Makefiles out/build-aosp_bluejay.ninja.
  2. Generate files from Android.bp out/soong/build.ninja. In addition, a smaller out/combined-aosp_bluejay.ninjafile is generated that is responsible for connecting the two as the entry point for execution.
  3. Ultimately, Ninja files are the tools that really directly control source code compilation, responsible for generating apk, aar, and dex files. The signing of the APK is also done using ninja rules, and then after all this is done, *.imgsthe file is created.

Finally, let's discuss these 3 steps in detail.

  1. runsource build/envsetup.sh
  2. select lunchoption
  3. run make <module-name>orm <module-name>

The first step of Android compilation

is running source build/envsetup.sh.

This paves the way for subsequent compilation steps. It is crucial to understand envsetup.shhow this corresponds to our analysis.

envsetup.shScript defines many functions. After executing this script, you can use Linux commands to directly execute these functions in the current console, such as lunch、mm、mmmetc. (use hmm to view all available commands). Therefore, lunchand mmmare actually shell functions, equivalent to shell scripts. Let's discuss build/envsetup.shthe rationale for implementing these commands in .

The second step of Android compilation

is to run lunchthe command. envsetup.shFunctions in the script lunch()set the environment for building images (*.imgs) and other artifacts (like apk, jar, .so, etc.). It AndroidProducts.mk.listreads a list of target devices from a file named list. When the function is called print_lunch_menu(), AndroidProducts.mk.listit takes COMMON_LUNCH_CHOICESthe variable from it and displays it to the user. From that function, will call get_build_var()and then call build/soong/soong_ui.bash --dumpvar-mode.

soong_ui.bashwill call the function /build/soong/cmd/soong_ui/main.goin , which will find all of them , and make a single one . Check out the code snippet below...main()build.FindSources(buildCtx, config, f)AndroidProducts.mkCOMMON_LUNCH_CHOICESAndroidProducts.mk.list

# lunch.bash
function print_lunch_menu()
{
    
    
    ...
    choices=$(TARGET_BUILD_VARIANT= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null)
    ...
}

function get_build_var()
{
    
    
    ...
    build/soong/soong_ui.bash --dumpvar-mode $1)
}

func main() {
    
    
    ...
    config := c.config(buildCtx, args...)
    ...
    f := build.NewSourceFinder(buildCtx, config)
    defer f.Shutdown()
    build.FindSources(buildCtx, config, f)
    ...
}

function lunch()
{
    
    
  print_lunch_menu
  ...
  read selection
  ...
  product=${selection%%-*} # Trim everything after first dash
  variant_and_version=${selection#*-} # Trim everything up to first dash
  if [ "$variant_and_version" != "$selection" ]; then
      variant=${variant_and_version%%-*}
      if [ "$variant" != "$variant_and_version" ]; then
          version=${variant_and_version#*-}
      fi
  fi
  ...
  TARGET_PRODUCT=$product \
  TARGET_BUILD_VARIANT=$variant \
  TARGET_PLATFORM_VERSION=$version \
  export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
  export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
  export TARGET_PLATFORM_VERSION=$(get_build_var TARGET_PLATFORM_VERSION)
  ...
}

uncommon but important commands

  1. set_stuff_for_environment: Its function is to add some paths to the PATH environment variable so that we can use some other tools in the Android source code, such as an emulator, in the console that has executed lunch.

  2. tapas: It sets up the build environment for building unbundled apps or APKs (normal Android packages). You can choose the chip architecture, the build variant, and the application required for the module build. For example:tapas SystemUI arm eng

  3. banchan: It sets up the build environment for building unbundled modules or APEX (local services, libraries, HAL, etc.). You can choose the chip architecture, the build variant, and the application required for the module build. For example:banchan com.android.boinic SystemUI arm eng

  4. make command

These commands become very easy if you understand how the lunch command works.

  • m: Compile from the top of the tree. For example: morm <module-name>
  • mm: Build and install all modules and their dependencies in the current directory.
  • mmm: Builds and installs all modules and their dependencies in the provided directory. To limit which modules are built, the following syntax can be used: mmm dir/:target1,target2. For example:mmm packages/apps/Launcher3

There are several other supported commands, you can use hmmthe command to see the list.

The third step of Android compilation

makeorm

Before Android N
the m or make command was equivalent make -f build/core/main.mk(built via GNU make)

Currently
the m or make command is equivalent build/soong/soong_ui.bash -make-mode, which is meant soong_ui.bashto be the core of the build system for the Android platform.

# song_ui.bash
source ${TOP}/build/soong/scripts/microfactory.bash

soong_build_go soong_ui android/soong/cmd/soong_ui
soong_build_go mk2rbc android/soong/mk2rbc/cmd
soong_build_go rbcrun rbcrun/cmd

cd ${TOP}
exec "$(getoutdir)/soong_ui" "$@"

It can be seen that soong_ui.bashthe main logic is divided into 4 parts:

Run microfactoryto set up the environment for building Go scripts. Help us soong_build_gobuild the requested binary with .
soong_build_go soong_uiPrepared the shell function call and executed soong's entry ie main.go.
soong_build_go mk2rbcand rbcrunexecuted the entry of the bazel build system and converted the different Makefiles to Starlark.
final execution soong_ui.
Therefore, from point 2 we understand that the entrance of soong ismain.go

Please note: point 3 is beyond the scope of this article.

In main.go, one of the following 4 parameters must be taken:

--dumpvar-mode
--dumpvars-mode
--make-mode
--build-mode

The first two parameters are less used and not used in build/craft, so we'll skip those and discuss the --make-modesum below --build-mode.

func main() {
    
    
 ...
 if os.Args[1] == " --dumpvar-mode" {
    
    
 dumpVar(buildCtx, config, os.Args[2:])
 } else if os.Args[1] == " --dumpvars-mode" {
    
    
 dumpVars(buildCtx, config, os.Args[2:])
 } else {
    
    
   //build --make-mode and --build-mode
   if inList("clean", config.Arguments()) || inList("clobber", config.Arguments()) {
    
    
     clean(ctx, config)
     return
   }
   if inList("help", config.Arguments())) {
    
    
     help(ctx, config)
     return
   }
   ...
 }
}

There are several other parameters like clobber/cleanand help, which call cleanbuild.goand help.sh. clobber/cleanUsed to delete the output folder, helpused to display the user manual for the command.

Next, let's dig into --make-modeand --build - mode.

Below is a high-level flow of the build process, and we'll discuss each join point one by one.
High-level flow of the build process
main.goBy config.gosetting the configuration, passing parameters such as skip, etc. kati.goThen, the FindSources function finds the mk file to merge into and soong.gothe bp file to process and convert to ninja file, and the help ninja.go. bazelOnly required if enabled bp2build.go, then you need to convert .bp files to BAZEL files. For this article, we assume it is not enabled bazel.

# main.go
function main() {
    
    
    c, args, err := getCommand(os.Args)
    ...
    buildCtx := build.Context{
    
    ContextImpl: &build.ContextImpl{
    
    
          Context: ctx,
          Logger:  log,
          Metrics: met,
          Tracer:  trace,
          Writer:  output,
          Status:  stat,
       }}
    config := c.config(buildCtx, args...)
    ...
    build.FindSources(buildCtx, config, f)
    ...
    c.run(buildCtx, config, args, logsDir)
}

Config will send parameters to build.go, to decide what to run and in what order. For example, if we run the following command:
build/soong/soong_ui.bash --make-mode --skip-ninja
Config's skipNinja will be true. Then proceed with:

//config.go
func config parseArgs(ctx Context, args []string) {
    
    
 for i := 0; i < len(args); i++ {
    
    
    arg := strings.TrimSpace(args[i])
    ...
    if arg == "--skip-ninja" {
    
    
       c.skipNinja = true
    } else if arg == "--skip-make" {
    
    
       c.skipConfig = true
       c.skipKati = true
    } else if arg == "--skip-kati" {
    
    
       c.skipKati = true
    } else if arg == "--soong-only" {
    
    
       c.skipKati = true
       c.skipKatiNinja = true
       ...
       c.arguments = append(c.arguments, arg)
    }
 }
}

Once the configuration is set, in the build process the variable "what" is set to by default runAll.

//build.go
func Build(ctx Context, config Config) {
    
    
	...
	what := RunAll
	...
	if config.SkipKati() {
    
    
		ctx.Verboseln("Skipping Kati as requested")
		what = what &^ RunKati
	}
	if config.SkipKatiNinja() {
    
    
		ctx.Verboseln("Skipping use of Kati ninja as requested")
		what = what &^ RunKatiNinja
	}
	if config.SkipSoong() {
    
    
		ctx.Verboseln("Skipping use of Soong as requested")
		what = what &^ RunSoong
	}
	if config.SkipNinja() {
    
    
		ctx.Verboseln("Skipping Ninja as requested")
		what = what &^ RunNinja
	}
  	...
	if what&RunSoong != 0 {
    
    
		runSoong(ctx, config)
	}
	if what&RunKati != 0 {
    
    
		genKatiSuffix(ctx, config)
		runKatiCleanSpec(ctx, config)
		runKatiBuild(ctx, config)
		runKatiPackage(ctx, config)

		ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0666) // a+rw
	}
  	...
  	if what&RunNinja != 0 {
    
    
		if what&RunKati != 0 {
    
    
			installCleanIfNecessary(ctx, config)
		}
		runNinjaForBuild(ctx, config)
	}
	// Currently, using Bazel requires Kati and Soong to run first, so check whether to run Bazel last.
	if what&RunBazel != 0 {
    
    
		runBazel(ctx, config)
	}
}

Once all meta filters are done, like skip Kati, skip Ninja, etc., the Soong process will start.

Soong's pipeline
has a tool called bootstrap that reads a Blueprint file that describes itself and generates .bootstrap/build.ninjaa file that describes how to build a full version of it, and uses that to generate the final Ninja file that Soong sends out.

//song.go
func runSoong(ctx Context, config Config) {
    
    
    ...
    buildMode := config.bazelBuildMode()
    integratedBp2Build := buildMode == mixedBuild
    ...
    bootstrapBlueprint(ctx, config)
    ...
    ninja := func(name, ninjaFile string, targets ...string) {
    
    
		...
		ninjaArgs := []string{
    
    
			"-d", "keepdepfile",
			"-d", "stats",
			"-o", "usesphonyoutputs=yes",
			"-o", "preremoveoutputs=yes",
			"-w", "dupbuild=err",
			"-w", "outputdir=err",
			"-w", "missingoutfile=err",
			"-j", strconv.Itoa(config.Parallel()),
			"--frontend_file", fifo,
			"-f", filepath.Join(config.SoongOutDir(), ninjaFile),
		}
        ...
    }
    ...
    if config.Bp2Build() {
    
    
		targets = append(targets, config.Bp2BuildMarkerFile())
    }
    ...
    ninja("bootstrap", "bootstrap.ninja", targets...)
    ...
}

If Bp2Build true, it means that the Bazel build system needs to be used and needs to be executed bp2build.go. It writes the equivalent of a file that can be built with Android.bpBazel .bzl .
Google wants to offload all compilation-related tasks to Bazel. It's a huge project, and the Android code is huge. I don't know when this project will be completed. Generated
from . Afterwards, Kati will be executed to parse Makefiles, but this is not part of Soong's bootstrapping. Kati's flow Loading Android.mk is performed in build.go , which calls the flow in the file (core/main.mk), including Android.mk for each subdirectory in the following way.Android.bpout/soong/build.ninja


runKati

subdir_makefiles := $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT).mk $(SOONG_ANDROID_MK)
# Android.mk files are only used on Linux builds, Mac only supports Android.bp
ifeq ($(HOST_OS),linux)
  subdir_makefiles += $(file <$(OUT_DIR)/.module_paths/Android.mk.list)
endif
subdir_makefiles += $(SOONG_OUT_DIR)/late-$(TARGET_PRODUCT).mk
subdir_makefiles_total := $(words int $(subdir_makefiles) post finish)
.KATI_READONLY := subdir_makefiles_total

$(foreach mk,$(subdir_makefiles),$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] including $(mk) ...)$(eval include $(mk)))

Based on this logic, we often see [xxx/xxx] contains xxx at compile time. Search for files in the Android source code, find Android.mk, put the corresponding file path into AndroidProducts.mk.listthe file, and generate the ninja file for it. It uses ckati to achieve.

For example: command:ckati,-f build/make/core/main.mk

From Android.mk and other Makefiles, out/build-<product_name>.ninja files will be generated.

Let's discuss what the generated ninja file looks like. Take SystemUI-core as an example.

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Module:  SystemUI-core
# Variant: android_common
# Type:    android_library
# Factory: android/soong/android.ModuleFactoryAdaptor.func1
# Defined: frameworks/base/packages/SystemUI/Android.bp:69:1

m.SystemUI-core_android_common.moduleDesc = //frameworks/base/packages/SystemUI:SystemUI-core
m.SystemUI-core_android_common.moduleDescSuffix = $ [common]
m.SystemUI-core_android_common.javacFlags = -Xlint:-dep-ann
m.SystemUI-core_android_common.kotlincFlags = -Xjvm-default=enable -Xsam-conversions=class -no-stdlib -no-jdk

rule m.SystemUI-core_android_common.aidl
    command = rm -rf out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/aidl0.tmp && mkdir -p out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/aidl0.tmp && FLAGS=' -Iframeworks/base/core/java -Iframeworks/base/drm/java -Iframeworks/base/graphics/java -Iframeworks/base/identity/java -Iframeworks/base/keystore/java -Iframeworks/base/location/java -Iframeworks/base/lowpan/java -Iframeworks/base/media/java -Iframeworks/base/media/mca/effect/java -Iframeworks/base/media/mca/filterfw/java -Iframeworks/base/media/mca/filterpacks/java -Iframeworks/base/mms/java -Iframeworks/base/opengl/java -Iframeworks/base/rs/java -Iframeworks/base/sax/java -Iframeworks/base/telecomm/java -Iframeworks/base/telephony/java -Iframeworks/base/packages/SystemUI -Iframeworks/base/packages/SystemUI/src --min_sdk_version=current -Iframeworks/base/packages/SystemUI/' && out/host/linux-x86/bin/aidl -dout/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/frameworks/base/packages/SystemUI/src/com/android/systemui/assist/IAssistHandleService.aidl.d $$FLAGS  frameworks/base/packages/SystemUI/src/com/android/systemui/assist/IAssistHandleService.aidl out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/aidl0.tmp/frameworks/base/packages/SystemUI/src/com/android/systemui/assist/IAssistHandleService.java && out/host/linux-x86/bin/soong_zip -srcjar -write_if_changed -o out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/aidl0.srcjar -C out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/aidl0.tmp -D out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/aidl0.tmp && rm -rf out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/gen/aidl/aidl0.tmp # hash of input list: 9def94a8716a4acf60f436254037b1e48158f63767ed67940332f88206e735f1
    restat = true

rule m.SystemUI-core_android_common.lint
    command = out/host/linux-x86/bin/sbox --sandbox-path out/soong/.temp --output-dir out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/lint --manifest out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/lint.sbox.textproto
    rspfile = out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/lint-srcs.list
    rspfile_content = ${in}

build $
        out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/manifest_fixer/AndroidManifest.xml: g.java.manifestFixer $
        frameworks/base/packages/SystemUI/AndroidManifest.xml | ${g.android.soong.java.config.ManifestFixerCmd}
    description = ${m.SystemUI-core_android_common.moduleDesc}fix manifest${m.SystemUI-core_android_common.moduleDescSuffix}
    args = --library --targetSdkVersion  33 --minSdkVersion  33 --raise-min-sdk-version
    
    build $
            out/soong/.intermediates/development/samples/SystemUI/SystemUI/android_common/meta_lic: g.android.licenseMetadataRule | ${g.android.licenseMetadataCmd} || $
            out/soong/.intermediates/build/soong/java/core-libraries/core-public-stubs-system-modules/android_common/meta_lic $
            out/soong/.intermediates/build/soong/java/core-libraries/legacy.core.platform.api.stubs/android_common/meta_lic $
            out/soong/.intermediates/external/apache-http/org.apache.http.legacy/android_common/meta_lic $
            out/soong/.intermediates/frameworks/base/android_stubs_current/android_common/meta_lic $
            out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/meta_lic out/soong/.intermediates/frameworks/base/ext/android_common/meta_lic $
            out/soong/.intermediates/frameworks/base/framework/android_common/meta_lic $
            out/soong/.intermediates/frameworks/base/test-base/android.test.base/android_common/meta_lic $
            out/soong/.intermediates/frameworks/base/test-mock/android.test.mock/android_common/meta_lic $
            out/soong/.intermediates/libcore/core-lambda-stubs/android_common/meta_lic $
            out/soong/.intermediates/system/libhidl/transport/base/1.0/android.hidl.base-V1.0-java/android_common/meta_lic $
            out/soong/.intermediates/system/libhidl/transport/manager/1.0/android.hidl.manager-V1.0-java/android_common/meta_lic
        description = ${m.SystemUI_android_common.moduleDesc}license metadata${m.SystemUI_android_common.moduleDescSuffix}
        args = -mt android_app -r development/samples/SystemUI -mc UNKNOWN -p "Android" -k SPDX-license-identifier-Apache-2.0 -c notice -n 'build/soong/licenses/LICENSE:Android' -d 'out/soong/.intermediates/build/soong/java/core-libraries/core-public-stubs-system-modules/android_common/meta_lic:dynamic' -d out/soong/.intermediates/build/soong/java/core-libraries/legacy.core.platform.api.stubs/android_common/meta_lic -d 'out/soong/.intermediates/external/apache-http/org.apache.http.legacy/android_common/meta_lic:dynamic' -d 'out/soong/.intermediates/frameworks/base/android_stubs_current/android_common/meta_lic:dynamic' -d 'out/soong/.intermediates/frameworks/base/android_stubs_current/android_common/meta_lic:dynamic' -d out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/meta_lic -d out/soong/.intermediates/frameworks/base/ext/android_common/meta_lic -d out/soong/.intermediates/frameworks/base/framework/android_common/meta_lic -d 'out/soong/.intermediates/frameworks/base/test-base/android.test.base/android_common/meta_lic:dynamic' -d 'out/soong/.intermediates/frameworks/base/test-mock/android.test.mock/android_common/meta_lic:dynamic' -d out/soong/.intermediates/libcore/core-lambda-stubs/android_common/meta_lic -d 'out/soong/.intermediates/libcore/core-lambda-stubs/android_common/meta_lic:dynamic' -d 'out/soong/.intermediates/system/libhidl/transport/base/1.0/android.hidl.base-V1.0-java/android_common/meta_lic:dynamic' -d 'out/soong/.intermediates/system/libhidl/transport/manager/1.0/android.hidl.manager-V1.0-java/android_common/meta_lic:dynamic' -s out/host/linux-x86/framework/android.test.base-hostdex.jar -s out/soong/.intermediates/build/soong/java/core-libraries/legacy.core.platform.api.stubs/android_common/dex/legacy.core.platform.api.stubs.jar -s out/soong/.intermediates/frameworks/base/android_stubs_current/android_common/dex/android_stubs_current.jar -s out/soong/.intermediates/frameworks/base/framework/android_common/combined/framework.jar -s out/soong/.intermediates/libcore/core-lambda-stubs/android_common/withres/core-lambda-stubs.jar -s out/target/product/barbet/system/framework/android.hidl.base-V1.0-java.jar -s out/target/product/barbet/system/framework/android.hidl.manager-V1.0-java.jar -s out/target/product/barbet/system/framework/android.test.base.jar -s out/target/product/barbet/system/framework/android.test.mock.jar -s out/target/product/barbet/system/framework/ext.jar -s out/target/product/barbet/system/framework/framework-res.apk -s out/target/product/barbet/system/framework/oat/arm/android.hidl.base-V1.0-java.odex -s out/target/product/barbet/system/framework/oat/arm/android.hidl.base-V1.0-java.vdex -s out/target/product/barbet/system/framework/oat/arm/android.hidl.manager-V1.0-java.odex -s out/target/product/barbet/system/framework/oat/arm/android.hidl.manager-V1.0-java.vdex -s out/target/product/barbet/system/framework/oat/arm/android.test.base.odex -s out/target/product/barbet/system/framework/oat/arm/android.test.base.vdex -s out/target/product/barbet/system/framework/oat/arm/android.test.mock.odex -s out/target/product/barbet/system/framework/oat/arm/android.test.mock.vdex -s out/target/product/barbet/system/framework/oat/arm/org.apache.http.legacy.odex -s out/target/product/barbet/system/framework/oat/arm/org.apache.http.legacy.vdex -s out/target/product/barbet/system/framework/oat/arm64/android.hidl.base-V1.0-java.odex -s out/target/product/barbet/system/framework/oat/arm64/android.hidl.base-V1.0-java.vdex -s out/target/product/barbet/system/framework/oat/arm64/android.hidl.manager-V1.0-java.odex -s out/target/product/barbet/system/framework/oat/arm64/android.hidl.manager-V1.0-java.vdex -s out/target/product/barbet/system/framework/oat/arm64/android.test.base.odex -s out/target/product/barbet/system/framework/oat/arm64/android.test.base.vdex -s out/target/product/barbet/system/framework/oat/arm64/android.test.mock.odex -s out/target/product/barbet/system/framework/oat/arm64/android.test.mock.vdex -s out/target/product/barbet/system/framework/oat/arm64/org.apache.http.legacy.odex -s out/target/product/barbet/system/framework/oat/arm64/org.apache.http.legacy.vdex -s out/target/product/barbet/system/framework/org.apache.http.legacy.jar -s out/target/product/barbet/system/framework/org.apache.http.legacy.jar.prof  -t out/soong/.intermediates/development/samples/SystemUI/SystemUI/android_common/SystemUI.apk -i out/target/product/barbet/system/app/SystemUI/SystemUI.apk

Use rule <rule-name>, you can define a rule for reuse, the command format is as follows:

m.<module>-<variant>-*: where and will be Android.bp/Android.mkdefined in and * can be treated as different flags like javacFlagsor kotlincFlags.

build $ <function>: which is actually the command to 1. aapt2convert the XML file and the Java file to .classa file using and the Java compiler, and then 2. .classconvert the file to .dexa file to create a file..apk

It also has additional rules for copying all generated artifacts into the appropriate directories. Directories out/target/product/bluejay/<obj>are used to stage "object" files, and these intermediate binary images are used to build the final program. What actually lands on the target file system is stored in out/target/product/bluejaythe root, system, and data directories under the directory. Usually, they are bundled into vbmeta.img、system.img、ramdisk.img 和 userdata.imgimage files called .

These images are also made, packaged and compressed as part of the ninja files generated by Kati.

rule m.microdroid_vbmeta_bootconfig_android_arm64_armv8-a.vbmeta
    command = out/host/linux-x86/bin/avbtool make_vbmeta_image --key external/avb/test/data/testkey_rsa4096.pem --algorithm SHA256_RSA4096 --rollback_index $$(date -d 'TZ="GMT" 2022-09-05' +%s | head -1 | tr -d '$
') --rollback_index_location 0 --chain_partition bootconfig:1:out/soong/.intermediates/packages/modules/Virtualization/microdroid/microdroid_vbmeta_bootconfig/android_arm64_armv8-a/bootconfig.avbpubkey --chain_partition uboot_env:2:out/soong/.intermediates/packages/android_arm64_armv8-a/uboot_env.avbpubkey
                               --output out/soong/.intermediates/packages/modules/Virtualization/microdroid/microdroid_vbmeta_bootconfig/android_arm64_armv8-a/microdroid_vbmeta_bootconfig.img && truncate -s 65536 out/soong/.intermediates/packages/modules/Virtualization/microdroid/microdroid_vbmeta_bootconfig/android_arm64_armv8-a/microdroid_vbmeta_bootconfig.img # hash of input list: f8343f0c11db644e49c173205360d2628cff5f895d40de988e2f1dfac75e3524

in conclusion

Hope this article gave you a good understanding of the Android platform build system and AOSP.
As you may have noticed, I mentioned the Bazel build system several times in the article . It's starting to gain traction as a potential replacement for the current build system. I'd love to talk about the Bazel build system in more detail in a future article, as things develop.

Guess you like

Origin blog.csdn.net/u011897062/article/details/132524869
Recommended