Platform mapping-based product config
This allows us to set product variables as build settings instead
of loading them from a target's provider, which further allows us
to read product config variables in transitions.
Bug: 287539062
Bug: 269577299
Test: Presubmits
Change-Id: I8497703f706162572ceb3486240e1eb02a37f5f6
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index b22cb28..cfe52db 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -80,6 +80,12 @@
os.Exit(1)
}
bp2buildFiles := CreateBazelFiles(ctx.Config(), nil, res.buildFileToTargets, ctx.mode)
+ injectionFiles, additionalBp2buildFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics)
+ if err != nil {
+ fmt.Printf("%s\n", err.Error())
+ os.Exit(1)
+ }
+ bp2buildFiles = append(bp2buildFiles, additionalBp2buildFiles...)
writeFiles(ctx, bp2buildDir, bp2buildFiles)
// Delete files under the bp2build root which weren't just written. An
// alternative would have been to delete the whole directory and write these
@@ -88,11 +94,6 @@
// performance implications.
deleteFilesExcept(ctx, bp2buildDir, bp2buildFiles)
- injectionFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics)
- if err != nil {
- fmt.Printf("%s\n", err.Error())
- os.Exit(1)
- }
writeFiles(ctx, android.PathForOutput(ctx, bazel.SoongInjectionDirName), injectionFiles)
starlarkDeps, err := starlark_import.GetNinjaDeps()
if err != nil {
@@ -107,20 +108,20 @@
// This includes
// 1. config value(s) that are hardcoded in Soong
// 2. product_config variables
-func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, error) {
+func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) {
var ret []BazelFile
- productConfigFiles, err := CreateProductConfigFiles(ctx)
+ productConfigInjectionFiles, productConfigBp2BuildDirFiles, err := CreateProductConfigFiles(ctx)
if err != nil {
- return nil, err
+ return nil, nil, err
}
- ret = append(ret, productConfigFiles...)
+ ret = append(ret, productConfigInjectionFiles...)
injectionFiles, err := soongInjectionFiles(ctx.Config(), metrics)
if err != nil {
- return nil, err
+ return nil, nil, err
}
- ret = append(ret, injectionFiles...)
- return ret, nil
+ ret = append(injectionFiles, ret...)
+ return ret, productConfigBp2BuildDirFiles, nil
}
// Get the output directory and create it if it doesn't exist.
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 7224496..8d5c99c 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -1,14 +1,20 @@
package bp2build
import (
+ "android/soong/android"
+ "android/soong/starlark_import"
+ "encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
+
+ "github.com/google/blueprint/proptools"
+ "go.starlark.net/starlark"
)
func CreateProductConfigFiles(
- ctx *CodegenContext) ([]BazelFile, error) {
+ ctx *CodegenContext) ([]BazelFile, []BazelFile, error) {
cfg := &ctx.config
targetProduct := "unknown"
if cfg.HasDeviceProduct() {
@@ -25,9 +31,14 @@
if !strings.HasPrefix(productVariablesFileName, "/") {
productVariablesFileName = filepath.Join(ctx.topDir, productVariablesFileName)
}
- bytes, err := os.ReadFile(productVariablesFileName)
+ productVariablesBytes, err := os.ReadFile(productVariablesFileName)
if err != nil {
- return nil, err
+ return nil, nil, err
+ }
+ productVariables := android.ProductVariables{}
+ err = json.Unmarshal(productVariablesBytes, &productVariables)
+ if err != nil {
+ return nil, nil, err
}
// TODO(b/249685973): the name is product_config_platforms because product_config
@@ -39,11 +50,16 @@
"{VARIANT}", targetBuildVariant,
"{PRODUCT_FOLDER}", currentProductFolder)
- result := []BazelFile{
+ platformMappingContent, err := platformMappingContent(productReplacer.Replace("@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"), &productVariables)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ injectionDirFiles := []BazelFile{
newFile(
currentProductFolder,
"soong.variables.bzl",
- `variables = json.decode("""`+strings.ReplaceAll(string(bytes), "\\", "\\\\")+`""")`),
+ `variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`),
newFile(
currentProductFolder,
"BUILD",
@@ -99,6 +115,7 @@
"product_config_platforms",
"common.bazelrc",
productReplacer.Replace(`
+build --platform_mappings=platform_mappings
build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
@@ -120,6 +137,48 @@
build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
`)),
}
+ bp2buildDirFiles := []BazelFile{
+ newFile(
+ "",
+ "platform_mappings",
+ platformMappingContent),
+ }
+ return injectionDirFiles, bp2buildDirFiles, nil
+}
+func platformMappingContent(mainProductLabel string, mainProductVariables *android.ProductVariables) (string, error) {
+ productsForTesting, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing")
+ if err != nil {
+ return "", err
+ }
+ result := "platforms:\n"
+ result += platformMappingSingleProduct(mainProductLabel, mainProductVariables)
+ for product, productVariablesStarlark := range productsForTesting {
+ productVariables, err := starlarkMapToProductVariables(productVariablesStarlark)
+ if err != nil {
+ return "", err
+ }
+ result += platformMappingSingleProduct("@//build/bazel/tests/products:"+product, &productVariables)
+ }
+ return result, nil
+}
+
+func platformMappingSingleProduct(label string, productVariables *android.ProductVariables) string {
+ buildSettings := ""
+ buildSettings += fmt.Sprintf(" --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride))
+ result := ""
+ for _, extension := range []string{"", "_linux_x86_64", "_linux_bionic_x86_64", "_linux_musl_x86", "_linux_musl_x86_64"} {
+ result += " " + label + extension + "\n" + buildSettings
+ }
+ return result
+}
+
+func starlarkMapToProductVariables(in map[string]starlark.Value) (android.ProductVariables, error) {
+ var err error
+ result := android.ProductVariables{}
+ result.ApexGlobalMinSdkVersionOverride, err = starlark_import.NoneableString(in["ApexGlobalMinSdkVersionOverride"])
+ if err != nil {
+ return result, err
+ }
return result, nil
}