Create config_setting per apex_name
These are created by bp2build in /build/bazel/rules/apex. Eventually
these config_settings should likely be colocated with the source apex
definition.
Another alternative was to make Bazel's apex a macro that generates a
config_setting. I did not pursue this further for now since it requires the
apex_available of every allowlisted cc_library to also be allowlisted.
This might not always be true (e.g. com.android.runtime)
Test: go test ./bp2build
Change-Id: Ibbb14b0d9c1491b3c79b7634a18d9d35b03922c1
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 4680256..d01877d 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -268,9 +268,8 @@
case productVariables:
// do nothing
case osAndInApex:
- if _, ok := osAndInApexMap[config]; !ok {
- panic(fmt.Errorf("Unknown os+in_apex config: %s", config))
- }
+ // do nothing
+ // this axis can contain additional per-apex keys
case inApex:
if _, ok := inApexMap[config]; !ok {
panic(fmt.Errorf("Unknown in_apex config: %s", config))
@@ -299,7 +298,10 @@
}
return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
case osAndInApex:
- return osAndInApexMap[config]
+ if ret, exists := osAndInApexMap[config]; exists {
+ return ret
+ }
+ return config
case inApex:
return inApexMap[config]
default:
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index b61b0a7..9f78195 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -4454,3 +4454,32 @@
},
})
}
+
+// Test that a config_setting specific to an apex is created by cc_library.
+func TestCcLibraryCreatesInApexConfigSetting(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library creates a config_setting for each apex in apex_available",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Dir: "build/bazel/rules/apex",
+ Blueprint: `
+cc_library {
+ name: "foo",
+ apex_available: [
+ "//apex_available:platform", // This will be skipped, since it is equivalent to //build/bazel/rules/apex:android-non_apex
+ "myapex"
+ ],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions(
+ "config_setting",
+ "android-in_myapex",
+ AttrNameToString{
+ "flag_values": `{
+ "//build/bazel/rules/apex:apex_name": "myapex",
+ }`,
+ },
+ ),
+ },
+ })
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index ad9d702..5ba6ea0 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -17,6 +17,7 @@
"fmt"
"path/filepath"
"strings"
+ "sync"
"android/soong/android"
"android/soong/bazel"
@@ -1196,6 +1197,63 @@
return !differ
}
+var (
+ apexConfigSettingKey = android.NewOnceKey("apexConfigSetting")
+ apexConfigSettingLock sync.Mutex
+)
+
+func getApexConfigSettingMap(config android.Config) *map[string]bool {
+ return config.Once(apexConfigSettingKey, func() interface{} {
+ return &map[string]bool{}
+ }).(*map[string]bool)
+}
+
+// Create a config setting for this apex in build/bazel/rules/apex
+// The use case for this is stub/impl selection in cc libraries
+// Long term, these config_setting(s) should be colocated with the respective apex definitions.
+// Note that this is an anti-pattern: The config_setting should be created from the apex definition
+// and not from a cc_library.
+// This anti-pattern is needed today since not all apexes have been allowlisted.
+func createInApexConfigSetting(ctx android.TopDownMutatorContext, apexName string) {
+ if apexName == android.AvailableToPlatform || apexName == android.AvailableToAnyApex {
+ // These correspond to android-non_apex and android-in_apex
+ return
+ }
+ apexConfigSettingLock.Lock()
+ defer apexConfigSettingLock.Unlock()
+
+ // Return if a config_setting has already been created
+ acsm := getApexConfigSettingMap(ctx.Config())
+ if _, exists := (*acsm)[apexName]; exists {
+ return
+ }
+ (*acsm)[apexName] = true
+
+ csa := bazel.ConfigSettingAttributes{
+ Flag_values: bazel.StringMapAttribute{
+ "//build/bazel/rules/apex:apex_name": apexName,
+ },
+ }
+ ca := android.CommonAttributes{
+ Name: "android-in_" + apexName,
+ }
+ ctx.CreateBazelConfigSetting(
+ csa,
+ ca,
+ "build/bazel/rules/apex",
+ )
+}
+
+func inApexConfigSetting(apexAvailable string) string {
+ if apexAvailable == android.AvailableToPlatform {
+ return bazel.AndroidAndNonApex
+ }
+ if apexAvailable == android.AvailableToAnyApex {
+ return bazel.AndroidAndInApex
+ }
+ return "//build/bazel/rules/apex:android-in_" + apexAvailable
+}
+
func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis,
config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) {
@@ -1241,6 +1299,13 @@
dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
}
}
+
+ // Create a config_setting for each apex_available.
+ // This will be used to select impl of a dep if dep is available to the same apex.
+ for _, aa := range apexAvailable {
+ createInApexConfigSetting(ctx.(android.TopDownMutatorContext), aa)
+ }
+
}
func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {