The build system supports building binaries for two target CPU architectures (64 bit and 32 bit) in the same build. This is known as a multilib build.
For native static libraries and shared libraries, the build system sets up
rules to build binaries for both architectures. The product configuration
PRODUCT_PACKAGES), together with the dependency graph, determines which
binaries are built and installed to the system image.
For executables and apps, the build system builds only the 64-bit version by
default, but you can override this setting with a global
BoardConfig.mk variable or a module-scoped variable.
BoardConfig.mk includes the following variables to
configure the second CPU architecture and ABI:
You can see an example in
If you want the build system to build 32-bit executables and apps by default, set the following variable:
TARGET_PREFER_32_BIT := true
You can override this setting by using module-specific variables in
In a multilib build, module names in
both the 32-bit and 64-bit binaries, as long as they're defined by the build
system. For libraries pulled in by dependency, a 32-bit library is installed
only if it’s required by another 32-bit library or executable. The same is true
for 64-bit libraries.
However, module names on the
make command line cover only the
64-bit version. For example, after running
make libc builds only the 64-bit libc. To
build the 32-bit libc, you need to run
Module definition in Android.mk
You can use the
LOCAL_MULTILIB variable to configure your build
for 32 bit/64 bit and override the global
LOCAL_MULTILIB to one of the following:
"both"builds both 32 bit and 64 bit.
"32"builds only 32 bit.
"64"builds only 64 bit.
"first"builds for only the first architecture (32 bit in 32-bit devices and 64 bit in 64-bit devices).
""is the default. The build system decides which architecture to build based on the module class and other
LOCAL_variables, such as
If you want to build your module for specific architectures, use the following variables:
Set this variable to a list of architectures, such as
arm x86 arm64. If the architecture being built is in that list, the current module is included by the build system.
This variable is the opposite of
LOCAL_MODULE_TARGET_ARCH. If the architecture being built is not in that list, the current module is included by the build system.
There are minor variants of these two variables:
The build system warns if the current module is skipped because of the architectures listed.
To set up build flags for a particular architecture, use the architecture-specific
LOCAL_ variables. An architecture-specific
LOCAL_ variable is a
LOCAL_ variable with an architecture suffix, for example:
These variables are applied only if a binary is currently being built for that architecture.
Sometimes it’s easier to set up flags based on whether the binary is
currently being built for 32 bit or 64 bit. Use the
variable with a
_64 suffix, for example:
Installing a path
Previously, you could use
LOCAL_MODULE_PATH to install a library to a
location other than the default one. For example,
In a multilib build, use
LOCAL_MODULE_RELATIVE_PATH := hw
With this format, both the 64-bit and 32-bit libraries are installed in the correct place.
If you build an executable as both 32 bit and 64 bit, use one of the following variables to distinguish the install path:
Specifies the installed filename.
Specifies the install path.
In a multilib build, if you generate source files to
with explicit variables), it doesn’t work reliably. That’s
because the intermediate generated sources are required by both the 32-bit and
64-bit builds, but
$(local-intermediates-dir) only points to one of
the two intermediate directories.
The build system provides a dedicated, multilib-friendly,
intermediate directory for generating sources. You can call
$(generated-sources-dir-for) to get the directory’s path. Their uses are similar to
If a source file is generated to this dedicated directory and picked up
LOCAL_GENERATED_SOURCES, it's built for both 32 bit and 64 bit
in a multilib build.
In a multilib build, you can’t use
TARGET_ARCH (or together with
TARGET_2ND_ARCH) to tell the build system what architecture the prebuilt
binary targets. Instead, use the
With these variables, the build system can choose the corresponding 32-bit prebuilt binary even if it’s working on a 64-bit multilib build.
If you want to use the chosen architecture to compute the source path for the prebuilt
ODEX file generation
For 64-bit devices, by default we generate both 32-bit and 64-bit ODEX files
for the boot image and any Java libraries. For APKs, by default we generate
ODEX only for the primary 64-bit architecture. If an app will be launched in both
32-bit and 64-bit processes, use
LOCAL_MULTILIB := both to make sure that
both 32-bit and 64-bit ODEX files are generated. If the app has any 32-bit or 64-bit JNI
libraries, that flag also tells the build system to include them.