Declare and use a build flag

Build flags are build-time constants and can't be changed during runtime. These flags are used in circumstances where aconfig flags can't be used, such as

  • You have a precompiled or prebuilt piece of code that you want include optionally in a build.
  • You want to make changes to build system itself.
  • You want to put flags around dependencies to manage code size.
  • You want to manage the launch of a feature, but you need to check the value of the flag before aconfig flags are made available by the system.

Declare a build flag

Build flags are declared in textproto files. To declare a build flag:

  1. Navigate to WORKING_DIRECTORY/build/release/flag_declarations/
  2. Create a file called RELEASE_MY_FLAG_NAME.textproto.
  3. Edit the file and add an entry similar to the following:

    name: "RELEASE_MY_FLAG_NAME"
    namespace: "android_UNKNOWN"
    description: "Control if we should read from new storage."
    workflow: LAUNCH
    containers: "product"
    containers: "system"
    containers: "system_ext"
    containers: "vendor"
    

    Where:

    • name contains the name of the flag preceded by RELEASE_. Only uppercase letters and underscore are allowed.
    • namespace contains the namespace for contributions. You must work with the assigned Google reviewer to determine your namespace. If you are using feature launch flags to maintain stability of your own AOSP mirror, you can use namespace however you like.
    • value is the initial type and value for the flag. The type can be bool_value or string_value. If type is string_value then the value must be in quotes. If not specified, the value is an empty string. Boolean values are represented as either true or the empty string for false.
    • workflow is either LAUNCH or PREBUILT. Use LAUNCH for boolean flags that advance from false to true, similar to feature launch flags. Use PREBUILT for flags that set a version, typically of a prebuilt.
    • containers the type of code you are writing, such as "vendor" for vendor code or "product" for product code. If you are in doubt of the value to use, use all four containers types as shown in the previous sample.

Use a build flag in a Soong file

In the build file and module where you want to query the flag value, use a conditional to branch on the flag value. For example, in the following snippet, the RELEASE__READ_FROM_NEW_STORAGE flag's value is queried:

cc_defaults {
  name: "aconfig_lib_cc_shared_link.defaults",
  shared_libs: select(release_flag("RELEASE_READ_FROM_NEW_STORAGE"), {
    true: ["libaconfig_storage_read_api_cc],
    default: [],
  }),
}

If this flag's value is true, the libaconfig_storage_read_api_cc module is dynamically linked into the cc_defaults module.

If this flag's value is false, nothing (default: [],) happens.

Use a build flag in a makefile

In the make file, a build flag is a read-only make variable. The following makefile sample accesses a build flag called RELEASED_PACKAGE_NFC_STCK:

# NFC and Secure Element packages
PRODUCT_PACKAGES += \
    $(RELEASE_PACKAGE_NFC_STACK) \
    Tag \
    SecureElement \
    android.hardware.nfc-service.st \
    android.hardware.secure_element@1.0-service.st \
    NfcOverlayCoral

This flag's declaration has a workflow field set to PREBUILT in RELEASE_PACKAGE_NFC_STACK.textproto and a string value of com.android.nfcservices RELEASE_PACKAGE_NFC_STACK.textproto the flag values file for the trunk_staging development configuration.