Move the android_platform next to it's entrypoint product config file

Because we're going to start generating partition images for the
product, and the partitions will eventually be checked in, we want
them to be in sensible locations. And the platform should be there as
well so all the targets for a product are co-located.

Bug: 297269187
Test: m nothing && b build --config=android //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal
Change-Id: Iaa25c44aa00295ada279d5fd49b5498bbafb89d5
This commit is contained in:
Cole Faust
2023-09-14 15:16:58 -07:00
parent 2e3f8e6b35
commit b4cb0c857f
4 changed files with 200 additions and 108 deletions

View File

@@ -484,6 +484,12 @@ type ProductVariables struct {
KeepVndk *bool `json:",omitempty"` KeepVndk *bool `json:",omitempty"`
CheckVendorSeappViolations *bool `json:",omitempty"` CheckVendorSeappViolations *bool `json:",omitempty"`
// PartitionsVars are extra variables that are used to define the partition images. They should
// not be read from soong modules.
PartitionVars struct {
ProductDirectory string `json:",omitempty"`
} `json:",omitempty"`
} }
func boolPtr(v bool) *bool { func boolPtr(v bool) *bool {

View File

@@ -53,9 +53,10 @@ func createProductConfigFiles(
return res, err return res, err
} }
// TODO(b/249685973): the name is product_config_platforms because product_config currentProductFolder := fmt.Sprintf("build/bazel/products/%s-%s", targetProduct, targetBuildVariant)
// was already used for other files. Deduplicate them. if len(productVariables.PartitionVars.ProductDirectory) > 0 {
currentProductFolder := fmt.Sprintf("product_config_platforms/products/%s-%s", targetProduct, targetBuildVariant) currentProductFolder = fmt.Sprintf("%s%s-%s", productVariables.PartitionVars.ProductDirectory, targetProduct, targetBuildVariant)
}
productReplacer := strings.NewReplacer( productReplacer := strings.NewReplacer(
"{PRODUCT}", targetProduct, "{PRODUCT}", targetProduct,
@@ -72,7 +73,7 @@ func createProductConfigFiles(
} }
productLabelsToVariables := make(map[string]*android.ProductVariables) productLabelsToVariables := make(map[string]*android.ProductVariables)
productLabelsToVariables[productReplacer.Replace("@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}")] = &productVariables productLabelsToVariables[productReplacer.Replace("@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}")] = &productVariables
for product, productVariablesStarlark := range productsForTestingMap { for product, productVariablesStarlark := range productsForTestingMap {
productVariables, err := starlarkMapToProductVariables(productVariablesStarlark) productVariables, err := starlarkMapToProductVariables(productVariablesStarlark)
if err != nil { if err != nil {
@@ -81,7 +82,30 @@ func createProductConfigFiles(
productLabelsToVariables["@//build/bazel/tests/products:"+product] = &productVariables productLabelsToVariables["@//build/bazel/tests/products:"+product] = &productVariables
} }
res.bp2buildTargets = createTargets(productLabelsToVariables) res.bp2buildTargets = make(map[string]BazelTargets)
res.bp2buildTargets[currentProductFolder] = append(res.bp2buildTargets[currentProductFolder], BazelTarget{
name: productReplacer.Replace("{PRODUCT}-{VARIANT}"),
packageName: currentProductFolder,
content: productReplacer.Replace(`android_product(
name = "{PRODUCT}-{VARIANT}",
soong_variables = _soong_variables,
)`),
ruleClass: "android_product",
loads: []BazelLoad{
{
file: ":soong.variables.bzl",
symbols: []BazelLoadSymbol{{
symbol: "variables",
alias: "_soong_variables",
}},
},
{
file: "//build/bazel/product_config:android_product.bzl",
symbols: []BazelLoadSymbol{{symbol: "android_product"}},
},
},
})
createTargets(productLabelsToVariables, res.bp2buildTargets)
platformMappingContent, err := platformMappingContent( platformMappingContent, err := platformMappingContent(
productLabelsToVariables, productLabelsToVariables,
@@ -92,26 +116,6 @@ func createProductConfigFiles(
} }
res.injectionFiles = []BazelFile{ res.injectionFiles = []BazelFile{
newFile(
currentProductFolder,
"soong.variables.bzl",
`variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`),
newFile(
currentProductFolder,
"BUILD",
productReplacer.Replace(`
package(default_visibility=[
"@soong_injection//product_config_platforms:__subpackages__",
"@//build/bazel/product_config:__subpackages__",
])
load(":soong.variables.bzl", _soong_variables = "variables")
load("@//build/bazel/product_config:android_product.bzl", "android_product")
android_product(
name = "{PRODUCT}-{VARIANT}",
soong_variables = _soong_variables,
)
`)),
newFile( newFile(
"product_config_platforms", "product_config_platforms",
"BUILD.bazel", "BUILD.bazel",
@@ -121,7 +125,7 @@ package(default_visibility = [
"@soong_injection//product_config_platforms:__subpackages__", "@soong_injection//product_config_platforms:__subpackages__",
]) ])
load("//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables") load("@//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables")
load("@//build/bazel/product_config:android_product.bzl", "android_product") load("@//build/bazel/product_config:android_product.bzl", "android_product")
# Bazel will qualify its outputs by the platform name. When switching between products, this # Bazel will qualify its outputs by the platform name. When switching between products, this
@@ -145,33 +149,33 @@ android_product(
# currently lunched product, they should all be listed here # currently lunched product, they should all be listed here
product_labels = [ product_labels = [
"@soong_injection//product_config_platforms:mixed_builds_product-{VARIANT}", "@soong_injection//product_config_platforms:mixed_builds_product-{VARIANT}",
"@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}", "@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}",
`)+strings.Join(productsForTesting, "\n")+"\n]\n"), `)+strings.Join(productsForTesting, "\n")+"\n]\n"),
newFile( newFile(
"product_config_platforms", "product_config_platforms",
"common.bazelrc", "common.bazelrc",
productReplacer.Replace(` productReplacer.Replace(`
build --platform_mappings=platform_mappings build --platform_mappings=platform_mappings
build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64 build --platforms @//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT} build:android --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
build:linux_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86 build:linux_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86
build:linux_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64 build:linux_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
build:linux_bionic_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64 build:linux_bionic_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64
build:linux_musl_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86 build:linux_musl_x86 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86
build:linux_musl_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86_64 build:linux_musl_x86_64 --platforms=@//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86_64
`)), `)),
newFile( newFile(
"product_config_platforms", "product_config_platforms",
"linux.bazelrc", "linux.bazelrc",
productReplacer.Replace(` productReplacer.Replace(`
build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64 build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
`)), `)),
newFile( newFile(
"product_config_platforms", "product_config_platforms",
"darwin.bazelrc", "darwin.bazelrc",
productReplacer.Replace(` productReplacer.Replace(`
build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64 build --host_platform @//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
`)), `)),
} }
res.bp2buildFiles = []BazelFile{ res.bp2buildFiles = []BazelFile{
@@ -179,6 +183,10 @@ build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_dar
"", "",
"platform_mappings", "platform_mappings",
platformMappingContent), platformMappingContent),
newFile(
currentProductFolder,
"soong.variables.bzl",
`variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`),
} }
return res, nil return res, nil
@@ -421,8 +429,11 @@ func starlarkMapToProductVariables(in map[string]starlark.Value) (android.Produc
return result, nil return result, nil
} }
func createTargets(productLabelsToVariables map[string]*android.ProductVariables) map[string]BazelTargets { func createTargets(productLabelsToVariables map[string]*android.ProductVariables, res map[string]BazelTargets) {
res := make(map[string]BazelTargets) createGeneratedAndroidCertificateDirectories(productLabelsToVariables, res)
}
func createGeneratedAndroidCertificateDirectories(productLabelsToVariables map[string]*android.ProductVariables, targets map[string]BazelTargets) {
var allDefaultAppCertificateDirs []string var allDefaultAppCertificateDirs []string
for _, productVariables := range productLabelsToVariables { for _, productVariables := range productLabelsToVariables {
if proptools.String(productVariables.DefaultAppCertificate) != "" { if proptools.String(productVariables.DefaultAppCertificate) != "" {
@@ -433,20 +444,20 @@ func createTargets(productLabelsToVariables map[string]*android.ProductVariables
} }
} }
for _, dir := range allDefaultAppCertificateDirs { for _, dir := range allDefaultAppCertificateDirs {
content := fmt.Sprintf(ruleTargetTemplate, "filegroup", "generated_android_certificate_directory", propsToAttributes(map[string]string{ content := `filegroup(
"srcs": `glob([ name = "generated_android_certificate_directory",
srcs = glob([
"*.pk8", "*.pk8",
"*.pem", "*.pem",
"*.avbpubkey", "*.avbpubkey",
])`, ]),
"visibility": `["//visibility:public"]`, visibility = ["//visibility:public"],
})) )`
res[dir] = append(res[dir], BazelTarget{ targets[dir] = append(targets[dir], BazelTarget{
name: "generated_android_certificate_directory", name: "generated_android_certificate_directory",
packageName: dir, packageName: dir,
content: content, content: content,
ruleClass: "filegroup", ruleClass: "filegroup",
}) })
} }
return res
} }

View File

@@ -39,18 +39,24 @@ type BazelAttributes struct {
Attrs map[string]string Attrs map[string]string
} }
type BazelLoadSymbol struct {
// The name of the symbol in the file being loaded
symbol string
// The name the symbol wil have in this file. Can be left blank to use the same name as symbol.
alias string
}
type BazelLoad struct {
file string
symbols []BazelLoadSymbol
}
type BazelTarget struct { type BazelTarget struct {
name string name string
packageName string packageName string
content string content string
ruleClass string ruleClass string
bzlLoadLocation string loads []BazelLoad
}
// IsLoadedFromStarlark determines if the BazelTarget's rule class is loaded from a .bzl file,
// as opposed to a native rule built into Bazel.
func (t BazelTarget) IsLoadedFromStarlark() bool {
return t.bzlLoadLocation != ""
} }
// Label is the fully qualified Bazel label constructed from the BazelTarget's // Label is the fully qualified Bazel label constructed from the BazelTarget's
@@ -110,30 +116,62 @@ func (targets BazelTargets) String() string {
// LoadStatements return the string representation of the sorted and deduplicated // LoadStatements return the string representation of the sorted and deduplicated
// Starlark rule load statements needed by a group of BazelTargets. // Starlark rule load statements needed by a group of BazelTargets.
func (targets BazelTargets) LoadStatements() string { func (targets BazelTargets) LoadStatements() string {
bzlToLoadedSymbols := map[string][]string{} // First, merge all the load statements from all the targets onto one list
bzlToLoadedSymbols := map[string][]BazelLoadSymbol{}
for _, target := range targets { for _, target := range targets {
if target.IsLoadedFromStarlark() { for _, load := range target.loads {
bzlToLoadedSymbols[target.bzlLoadLocation] = outer:
append(bzlToLoadedSymbols[target.bzlLoadLocation], target.ruleClass) for _, symbol := range load.symbols {
alias := symbol.alias
if alias == "" {
alias = symbol.symbol
}
for _, otherSymbol := range bzlToLoadedSymbols[load.file] {
otherAlias := otherSymbol.alias
if otherAlias == "" {
otherAlias = otherSymbol.symbol
}
if symbol.symbol == otherSymbol.symbol && alias == otherAlias {
continue outer
} else if alias == otherAlias {
panic(fmt.Sprintf("Conflicting destination (%s) for loads of %s and %s", alias, symbol.symbol, otherSymbol.symbol))
}
}
bzlToLoadedSymbols[load.file] = append(bzlToLoadedSymbols[load.file], symbol)
}
} }
} }
var loadStatements []string var loadStatements strings.Builder
for bzl, ruleClasses := range bzlToLoadedSymbols { for i, bzl := range android.SortedKeys(bzlToLoadedSymbols) {
loadStatement := "load(\"" symbols := bzlToLoadedSymbols[bzl]
loadStatement += bzl loadStatements.WriteString("load(\"")
loadStatement += "\", " loadStatements.WriteString(bzl)
ruleClasses = android.SortedUniqueStrings(ruleClasses) loadStatements.WriteString("\", ")
for i, ruleClass := range ruleClasses { sort.Slice(symbols, func(i, j int) bool {
loadStatement += "\"" + ruleClass + "\"" if symbols[i].symbol < symbols[j].symbol {
if i != len(ruleClasses)-1 { return true
loadStatement += ", " }
return symbols[i].alias < symbols[j].alias
})
for j, symbol := range symbols {
if symbol.alias != "" && symbol.alias != symbol.symbol {
loadStatements.WriteString(symbol.alias)
loadStatements.WriteString(" = ")
}
loadStatements.WriteString("\"")
loadStatements.WriteString(symbol.symbol)
loadStatements.WriteString("\"")
if j != len(symbols)-1 {
loadStatements.WriteString(", ")
} }
} }
loadStatement += ")" loadStatements.WriteString(")")
loadStatements = append(loadStatements, loadStatement) if i != len(bzlToLoadedSymbols)-1 {
loadStatements.WriteString("\n")
} }
return strings.Join(android.SortedUniqueStrings(loadStatements), "\n") }
return loadStatements.String()
} }
type bpToBuildContext interface { type bpToBuildContext interface {
@@ -857,11 +895,18 @@ func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) (BazelTarget, e
} else { } else {
content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes) content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes)
} }
var loads []BazelLoad
if bzlLoadLocation != "" {
loads = append(loads, BazelLoad{
file: bzlLoadLocation,
symbols: []BazelLoadSymbol{{symbol: ruleClass}},
})
}
return BazelTarget{ return BazelTarget{
name: targetName, name: targetName,
packageName: m.TargetPackage(), packageName: m.TargetPackage(),
ruleClass: ruleClass, ruleClass: ruleClass,
bzlLoadLocation: bzlLoadLocation, loads: loads,
content: content, content: content,
}, nil }, nil
} }

View File

@@ -775,7 +775,10 @@ func TestLoadStatements(t *testing.T) {
BazelTarget{ BazelTarget{
name: "foo", name: "foo",
ruleClass: "cc_library", ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
}},
}, },
}, },
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
@@ -785,12 +788,18 @@ func TestLoadStatements(t *testing.T) {
BazelTarget{ BazelTarget{
name: "foo", name: "foo",
ruleClass: "cc_library", ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
}},
}, },
BazelTarget{ BazelTarget{
name: "bar", name: "bar",
ruleClass: "cc_library", ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
}},
}, },
}, },
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
@@ -800,12 +809,18 @@ func TestLoadStatements(t *testing.T) {
BazelTarget{ BazelTarget{
name: "foo", name: "foo",
ruleClass: "cc_library", ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
}},
}, },
BazelTarget{ BazelTarget{
name: "bar", name: "bar",
ruleClass: "cc_binary", ruleClass: "cc_binary",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
}},
}, },
}, },
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`, expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`,
@@ -815,17 +830,26 @@ func TestLoadStatements(t *testing.T) {
BazelTarget{ BazelTarget{
name: "foo", name: "foo",
ruleClass: "cc_library", ruleClass: "cc_library",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_library"}},
}},
}, },
BazelTarget{ BazelTarget{
name: "bar", name: "bar",
ruleClass: "cc_binary", ruleClass: "cc_binary",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
}},
}, },
BazelTarget{ BazelTarget{
name: "baz", name: "baz",
ruleClass: "java_binary", ruleClass: "java_binary",
bzlLoadLocation: "//build/bazel/rules:java.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:java.bzl",
symbols: []BazelLoadSymbol{{symbol: "java_binary"}},
}},
}, },
}, },
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library") expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")
@@ -836,17 +860,23 @@ load("//build/bazel/rules:java.bzl", "java_binary")`,
BazelTarget{ BazelTarget{
name: "foo", name: "foo",
ruleClass: "cc_binary", ruleClass: "cc_binary",
bzlLoadLocation: "//build/bazel/rules:cc.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:cc.bzl",
symbols: []BazelLoadSymbol{{symbol: "cc_binary"}},
}},
}, },
BazelTarget{ BazelTarget{
name: "bar", name: "bar",
ruleClass: "java_binary", ruleClass: "java_binary",
bzlLoadLocation: "//build/bazel/rules:java.bzl", loads: []BazelLoad{{
file: "//build/bazel/rules:java.bzl",
symbols: []BazelLoadSymbol{{symbol: "java_binary"}},
}},
}, },
BazelTarget{ BazelTarget{
name: "baz", name: "baz",
ruleClass: "genrule", ruleClass: "genrule",
// Note: no bzlLoadLocation for native rules // Note: no loads for native rules
}, },
}, },
expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary") expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary")