'Is there a way to add/remove module in Android.bp?
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 :)
Solution 1:[1]
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.
Solution 2:[2]
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,
},
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | zeitgeist |
