While Android.mk served AOSP well for years, its reliance on GNU Make caused critical bottlenecks. Make is a procedural scripting language, meaning the build system had to "execute" thousands of files sequentially just to figure out what needed to be built. As AOSP grew to millions of files, this evaluation phase alone began taking upwards of 15 minutes.
To solve this, Google introduced Soong, a modern build system written in Go, powered by a strict, declarative language called Blueprint.
What is an Android.bp file?
Instead of Android.mk files, modern AOSP uses Android.bp files. The "bp" stands for Blueprint.
Unlike Make, Blueprint is not a scripting language. You cannot write if/else statements, you cannot run shell commands natively, and you cannot define arbitrary global variables. Blueprint is strictly declarative; it only describes the modules and their properties.
Blueprint Syntax
Blueprint syntax is heavily inspired by JSON. It consists of module definitions followed by a set of key-value properties.
Here is a standard Android.bp file defining a C++ binary:
cc_binary {
name: "my_custom_daemon",
srcs: [
"main.cpp",
"helper.cpp",
],
shared_libs: [
"liblog",
"libbase",
],
cflags: ["-Werror"],
}
Key Differences from Android.mk
- No
LOCAL_PATHrequired: Because Blueprint parses the entire tree efficiently, it automatically knows the relative path of theAndroid.bpfile. - No
CLEAR_VARSrequired: Blueprint uses strict object encapsulation. The properties defined inside one module (cc_binary) have absolutely zero risk of leaking into or polluting another module. - Strict Typing: In Make, everything is a string. In Blueprint, properties have strict types.
srcsmust be a list of strings ([]), whilenamemust be a single string. - No Conditionals: You cannot write
ifeq ($(TARGET_DEVICE), pixel)inside anAndroid.bpfile. If you need device-specific logic, you must handle it outside the blueprint file or use specialized Soong namespace features (likesoong_config_module_type).
Why is it so fast?
Because Android.bp files contain no executable logic or conditionals, the Soong parser can read and process thousands of them in parallel in a matter of seconds.
Soong quickly builds a massive dependency graph in memory (e.g., "my_custom_daemon depends on liblog"), determines exactly what needs to be compiled, and outputs a highly optimized build.ninja file for the Ninja build system to execute concurrently.
# You can see the raw ninja rules generated by Soong
m out/soong/build.ninja