AOSP ABI 32 64 Bit Support: A Practical Guide
AOSP, the Android Open Source Project, is the base code that powers most Android devices. When you build a modern AOSP image, you have to think about whether your code runs as 32 bit, 64 bit, or both. This choice affects performance, library size, and which apps can run on the device. In this guide, you will learn what an ABI is, how AOSP handles 32 and 64 bit builds, and how to set up your own build to support both.
Understanding this topic matters because Google now requires 64 bit support on most devices. If you work on platform code, system services, or native libraries, you need to know how the bits fit together.
What Is an ABI in AOSP
ABI stands for Application Binary Interface. Think of it as a contract between your code and the system. It defines how functions are called, how data is laid out in memory, and which instructions the CPU can run. In AOSP, the most common ABIs are armeabi-v7a (32 bit ARM) and arm64-v8a (64 bit ARM). For x86 devices, you will see x86 (32 bit) and x86_64 (64 bit).
When a developer builds a native library, they pick one or more ABIs. The library then runs only on devices that match. AOSP itself ships native libraries for each ABI it supports. The build system uses a property called TARGET_ARCH to pick which one to compile for.
Here is a simple example. If you set TARGET_ARCH in your BoardConfig.mk, you choose the primary ABI for your build.
TARGET_ARCH := arm64
TARGET_ARCH_VARIANT := armv8-a
If you want to support 32 bit apps on a 64 bit device, you also need to enable a secondary ABI. This is common for arm64 devices that want to run older 32 bit apps.
TARGET_2ND_ARCH := arm
TARGET_2ND_ARCH_VARIANT := armv7-a-neon
AOSP uses these variables to decide which sources to compile and which libraries to package. You can read the official list of ABIs on the Android NDK ABI page.
How AOSP Builds for 32 and 64 Bit
AOSP uses a build system based on make and a tool called Soong. When you run a build command, the system reads your device config and creates output for each ABI you enabled. The output goes into folders like out/target/product/your_device/system/lib64 for 64 bit libraries, and out/target/product/your_device/system/lib for 32 bit libraries.
The key build command for a full AOSP build looks like this.
source build/envsetup.sh
lunch aosp_arm64-userdebug
make -j8
If you want a build that supports both ABIs, you need a device config that lists both. The BoardConfig.mk file is where you set this. Here is a real example for a device that supports arm64 as the primary and arm as the secondary.
TARGET_ARCH := arm64
TARGET_ARCH_VARIANT := armv8-a
TARGET_2ND_ARCH := arm
TARGET_2ND_ARCH_VARIANT := armv7-a-neon
TARGET_BOARD_PLATFORM := generic
When the build runs, AOSP compiles each native library twice. The 64 bit version goes into /system/lib64. The 32 bit version goes into /system/lib. At runtime, the dynamic linker picks the right one based on the app or service that needs it.
The Role of the Dynamic Linker
The dynamic linker is a small program that loads shared libraries when a process starts. In AOSP, this program lives at /system/bin/linker (32 bit) and /system/bin/linker64 (64 bit). When you launch a 64 bit process, the kernel loads linker64. When you launch a 32 bit process on a 64 bit system, the kernel loads linker from the 32 bit library path.
This is why you need both folders on a mixed system. If /system/lib is missing, 32 bit apps will fail to start.
Adding Native Code That Supports Both ABIs
If you write a native module for AOSP, you should add an Android.bp file that builds for both ABIs when needed. Soong makes this easy. Here is an example of a shared library that supports 32 and 64 bit.
cc_library_shared {
name: "libexample",
srcs: ["src/example.c"],
shared_libs: ["liblog"],
cflags: ["-Wall", "-Werror"],
arch: {
arm: {
cflags: ["-DABI_32"],
},
arm64: {
cflags: ["-DABI_64"],
},
},
}
The arch block lets you set flags per ABI. You can also list separate sources per arch if your code uses CPU features that only exist on one variant.
When you build this module, AOSP creates libexample.so in both lib and lib64. The packaging system then copies them to the right place in the final image.
Checking Your Output
After a build, you can check which libraries are in your image. Use a simple find command on the output folder.
find out/target/product/generic/system -name "*.so" | head -20
You should see paths like system/lib/libexample.so and system/lib64/libexample.so. If only one is present, check your BoardConfig.mk and make sure both ABIs are enabled.
Common Problems With 32 and 64 Bit AOSP Builds
Mixed ABI builds can fail in a few common ways. The first is missing source files. Some HAL modules only have code for one ABI. If you enable a secondary ABI, the build will look for sources for that arch and fail if it cannot find them.
The second problem is linker errors at runtime. This often happens when a 32 bit library tries to load a 64 bit one, or the other way around. The system log will show a message like “dlopen failed: library “libfoo.so” not found”. To fix this, check the library paths and make sure each ABI has its own copy.
The third problem is build time. Building for two ABIs takes almost twice as long for native code. On a slow machine, this can be a real pain. You can speed things up by setting TARGET_2ND_ARCH to false if you do not need 32 bit support during development.
TARGET_2ND_ARCH := false
This turns off the secondary ABI and saves build time. Turn it back on for release builds.
For more details on the build flags, see the AOSP build system docs.
Frequently Asked Questions
Q: Does AOSP still support 32 bit devices?
A: AOSP still includes 32 bit support in the source tree. You can build a 32 bit only image by setting TARGET_ARCH to arm or x86 and leaving TARGET_2ND_ARCH empty. However, Google Play and many modern apps require 64 bit, so new devices should use 64 bit as the primary ABI.
Q: Can a 64 bit Android device run 32 bit apps?
A: Yes, if the device was built with a secondary 32 bit ABI. This is common for arm64 phones that want to support older apps. The kernel and the linker handle the switch at runtime.
Q: How do I know which ABI my AOSP build uses?
A: Check the BoardConfig.mk file in your device folder. Look for TARGET_ARCH and TARGET_2ND_ARCH. You can also check the output folders. A 64 bit build will have a lib64 folder, while a 32 bit build will only have lib.
Q: Is it slower to build both 32 and 64 bit at the same time?
A: Yes. Native code is compiled twice, so the build takes longer and uses more disk space. Most developers build only the primary ABI during daily work and add the secondary ABI for release builds.
Conclusion
AOSP gives you the tools to build for 32 bit, 64 bit, or both. The choice depends on your device goals and the apps you want to support. Start by picking a primary ABI in your BoardConfig.mk, then add a secondary ABI only if you need it. Always test your build by checking the output folders and running a sample app. A good next step is to clone the AOSP source, set up a simple aosp_arm64 build, and try adding a custom native library that supports both ABIs.

