At the end of every module definition in an Android.mk file, you must declare a build rule. This rule tells the AOSP build system exactly what to do with the LOCAL_ variables you just defined.
Here are the most common build rules you will encounter in legacy AOSP code.
1. BUILD_PACKAGE (Generating an APK)
This is the rule used to compile standard Android applications (.apk files).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MySystemApp
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := MySystemApp
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
LOCAL_PACKAGE_NAME: The name of the final APK.LOCAL_CERTIFICATE: Tells the build system which cryptographic key to use to sign the APK.- Result: The build system compiles the Java files, packages the XML resources, signs the APK, and places it in
out/target/product/<device>/system/app/MySystemApp/.
2. BUILD_EXECUTABLE (Native Binaries)
Used for compiling C or C++ code into a standalone command-line binary (like ping, logcat, or a custom diagnostic daemon).
include $(CLEAR_VARS)
LOCAL_MODULE := my_custom_daemon
LOCAL_SRC_FILES := daemon.cpp
include $(BUILD_EXECUTABLE)
- Result: Places a binary executable directly in the
/system/bin/or/vendor/bin/directory on the physical device.
3. Libraries: Static vs Shared
When writing C/C++ code that needs to be used by multiple other programs, you compile it into a library.
BUILD_SHARED_LIBRARY
Compiles a dynamically linked library (.so file).
- How it works: The library is placed on the device's storage (e.g.,
/system/lib64/libmath.so). When an app needs it, the Android dynamic linker loads it into memory at runtime. It saves storage space because multiple apps can share the exact same library file.
BUILD_STATIC_LIBRARY
Compiles a statically linked library (.a file).
- How it works: This library is never placed on the physical device. Instead, the actual compiled code is physically copied and embedded directly into the binary of the app that uses it during the compilation phase on your Ubuntu host.
4. BUILD_PREBUILT
Often, hardware vendors provide closed-source, proprietary binaries (like a camera driver or a specialized APK) where you do not have the source code. You cannot use BUILD_PACKAGE because there is nothing to compile.
include $(CLEAR_VARS)
LOCAL_MODULE := proprietary_camera_driver
LOCAL_SRC_FILES := libcamera_vendor.so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
include $(BUILD_PREBUILT)
- Result: Instead of trying to compile code via a compiler, the build system simply copies the pre-existing binary file directly into the correct location in the final OS image.