5

I'm trying to add/remove modules in Android.bp, according to the set of envirenment variable. E.g., if I set 1 to BUILD_SOURCE, cc_prebuilt_binary is removed in Android.bp and some cc_binary is added instead.

I've seen the guide and seen below sentence, a https://android.googlesource.com/platform/build/soong/#how-do-i-write-conditionals

Soong deliberately does not support conditionals in Android.bp files. Instead, complexity in build rules that would require conditionals are handled in Go

But I couldn't find the way to control whole module not the property in the module.

Does anyone know how to do or where the guide is?

Thanks in advance :)

Chan Lee
  • 71
  • 1
  • 5
  • Not a full answer yet, but you can disable modules in Android.bp by adding enabled: false to the module declaration. Maybe you could set this flag in Go based on the environment variable (Reference: https://stackoverflow.com/questions/56602427)? – f9c69e9781fa194211448473495534 Oct 17 '19 at 05:38
  • Could you give me some examples about `enabled`, such as document, link,,, ? Or, is it possible to make module without srcs? – Chan Lee Oct 28 '19 at 00:01

2 Answers2

4

I'm assuming you have the following setup:

cc_binary {
  name: "my_binary",
  srcs: ["some_file.cc"]
}

cc_prebuilt_binary {
  name: "my_binary_prebuilt",
  srcs: ["some_blob"]
}

I would suggest the following approach:

Step 1: Selecting the module conditionally

The soong build system requires the module name to be unique. So in your case the cc_prebuilt_binary and the cc_binary need different names. Therefore, the place where you require these modules you would have to select the right one.

Since you are dealing with binaries, I am assuming you are selecting these modules via the PRODUCT_PACKAGES variable in some .mk file (as opposed to a library, which could also be selected as a dependency for another module). You would then adapt the PRODUCT_PACKAGES declaration to e.g.:

ifeq ($(BUILD_SOURCE),1)
    PRODUCT_PACKAGES += my_binary
else
    PRODUCT_PACKAGES += my_binary_prebuilt
endif

Step 2: Enabling the module conditionally

If the source files for both modules are always available, no further work should be needed. However, if e.g. the prebuilt binary isn't available at all when BUILD_SOURCE=1, you would need to completely disable this module. This is different from not selecting it as in Step 1: For disabled modules, the files specified in srcs are not verified for availability.

Disabling manually could be done as:

cc_prebuilt_binary {
  name: "my_binary_prebuilt",
  srcs: ["some_blob"],
  enabled: false
}

However, I am assuming you want to do this automatically based on the BUILD_SOURCE environment variable.

To this end, you would define a custom module preset (e.g. in a file my_prebuilt_preset.go) that sets the enabled flag based on the BUILD_SOURCE environment variable:

package my_prebuilt_preset

import (
    "android/soong/android"
    "android/soong/cc"
)

func myPrebuiltDefaults(ctx android.LoadHookContext) {
    type props struct {
        Target struct {
            Android struct {
                Enabled *bool
            }
        }
    }

    p := &props{}
    p.Target.Android.Enabled = new(bool)
    *p.Target.Android.Enabled = !ctx.AConfig().IsEnvTrue("BUILD_SOURCE")

    ctx.AppendProperties(p)
}

func myPrebuiltDefaultsFactory() android.Module {
    module := cc.DefaultsFactory()
    android.AddLoadHook(module, myPrebuiltDefaults)

    return module
}

func init() {
    android.RegisterModuleType("my_prebuilt_preset", myPrebuiltDefaultsFactory)
}

You would add a module for the Go file in your Android.bp:

bootstrap_go_package {
    name: "soong-my_prebuilt_preset",
    pkgPath: "android/soong/external/my_prebuilt_preset",
    deps: [
        "soong",
        "soong-android",
        "soong-cc"
    ],
    srcs: [
        "my_prebuilt_preset.go"
    ],
    pluginFor: ["soong_build"]
}

And then add the preset to your my_binary_prebuilt:

my_prebuilt_preset {
  name: "my-prebuilt-preset"
}

cc_prebuilt_binary {
  name: "my_binary_prebuilt",
  srcs: ["some_blob"],
  defaults: ["my-prebuilt-preset"]
}

Your my_binary_prebuilt should then be disabled when BUILD_SOURCE=1 and its srcs field should not be evaluated.

  • I am getting on AOSP build with this `error: vendor/qcom/opensource/camera-samples/Camera2Video/Android.bp:15:1: unrecognized module type "my_prebuilt_preset" ` – zeitgeist Feb 22 '22 at 07:50
0

GO

You can write a go script with your conditions. Follow

https://stackoverflow.com/a/58587560/10183099

What is art.go? And why is it considered a way to write conditionals in bp files?

Conditional compilation

If you just want to include a module conditionally you can define many Android.bp modules and include them based on conditions in Android.mk files. https://android.googlesource.com/platform/build/soong/+/HEAD/docs/best_practices.md#removing-conditionals

soong_config_modules

You will face parsing errors if any of your Android.bp files include libraries not supported by your AOSP.

To fix that you can use soong_config_modules. Note that this is supported only Android 11 R onwards.

Details are given in https://android.googlesource.com/platform/build/soong/+/refs/heads/master/android/soong_config_modules.go

However, I'll give you an example.

Here I am including special libraries when the AOSP is Android 12. Since these libraries might not be present on lower versions, I will not include iot-camera-system.mk in PRODUCT_PACKAGES so it will not be included as a preinstalled app.

What specifically I will achieve with soong_config_modules is removal of parsing errors when these libraries are not present (Android parses all Android.bp files to form a parse tree, it also checks for the existence of their dependencies and build fails when they are not present).

iot-camera-system.mk

# CameraApp Android Application Package

ifeq ($(PLATFORM_VERSION), $(filter $(PLATFORM_VERSION),S 12))
  PRODUCT_PACKAGES += CameraApp
  SOONG_CONFIG_NAMESPACES += camera
  SOONG_CONFIG_camera += camtargets
  SOONG_CONFIG_camera_camtargets := newCameraTarget
else
  SOONG_CONFIG_NAMESPACES += camera
  SOONG_CONFIG_camera += camtargets
  SOONG_CONFIG_camera_camtargets := oldCameraTarget
endif

Android.bp

// This introduces the module type camera_cc_defaults
// If target.mk file contained:
//
// SOONG_CONFIG_NAMESPACES += camera
// SOONG_CONFIG_camera += camtargets
// SOONG_CONFIG_camera_camtargets := newCameraTarget
//
// Then our libs would build with static_libs

soong_config_module_type {
    name: "camera_cc_defaults",
    module_type: "cc_defaults",
    config_namespace: "camera",
    variables: ["camtargets"],
    properties: ["static_libs"],
}

soong_config_string_variable {
    name: "camtargets",
    values: ["oldCameraTarget", "newCameraTarget"],
}

camera_cc_defaults {
    name: "camera_defaults",
    soong_config_variables: {
        camtargets: {
            oldCameraTarget: {
                static_libs: [
                ],
            },
            newCameraTarget: {
                static_libs: [
                    "androidx.core_core-ktx",
                    "androidx.fragment_fragment-ktx",
                    "androidx.navigation_navigation-fragment-ktx",
                    "androidx.navigation_navigation-ui-ktx",
                    "androidx.lifecycle_lifecycle-runtime-ktx",
                    "kotlinx_coroutines",
                    "kotlinx_coroutines_android",
                ],
            },
        },
    },
}

android_library {
  name: "utils",
  defaults: ["camera_defaults"],
  manifest: "utils/src/main/AndroidManifest.xml",
  platform_apis: true,

  srcs: [
    "utils/src/main/java/com/example/android/camera/utils/*.kt",
  ],

  resource_dirs: [
    "utils/src/main/res/",
  ],

  static_libs: [
    "androidx-constraintlayout_constraintlayout",
    "androidx.appcompat_appcompat",
    "androidx.localbroadcastmanager_localbroadcastmanager",
    "com.google.android.material_material",
    "androidx.exifinterface_exifinterface",
    "androidx.core_core",
    "androidx.preference_preference",
    "androidx.fragment_fragment",
    "androidx.recyclerview_recyclerview",
    "androidx.lifecycle_lifecycle-runtime",
    "androidx.lifecycle_lifecycle-extensions",
    "kotlin-stdlib",
    "kotlin-reflect",
    "gson-prebuilt-jar",
  ],

  optimize: {
    enabled: false,
  },
  dex_preopt: {
    enabled: false,
  },
}

android_app {
  name: "CameraApp",
  defaults: ["camera_defaults"],
  manifest: "app/src/main/AndroidManifest.xml",
  privileged: true,
  platform_apis: true,
  certificate: "platform",

  srcs: [
    "app/src/main/java/com/example/android/camera2/video/*.kt",
    "app/src/main/java/com/example/android/camera2/video/fragments/*.kt",
    "app/src/main/java/com/example/android/camera2/video/overlay/*.kt",
  ],

  resource_dirs: [
    "app/src/main/res/",
  ],

  static_libs: [
    "androidx-constraintlayout_constraintlayout",
    "androidx.appcompat_appcompat",
    "androidx.localbroadcastmanager_localbroadcastmanager",
    "com.google.android.material_material",
    "androidx.exifinterface_exifinterface",
    "androidx.core_core",
    "androidx.preference_preference",
    "androidx.fragment_fragment",
    "androidx.recyclerview_recyclerview",
    "androidx.lifecycle_lifecycle-runtime",
    "androidx.lifecycle_lifecycle-extensions",
    "kotlin-stdlib",
    "kotlin-reflect",
    "gson-prebuilt-jar",
    "utils",
  ],

  optimize: {
    enabled: false,
  },
  dex_preopt: {
    enabled: false,
  },
}
zeitgeist
  • 852
  • 12
  • 19