Compare commits
56 commits
c38f67a21e
...
876f0bb0d9
Author | SHA1 | Date | |
---|---|---|---|
|
876f0bb0d9 | ||
|
ac339f8e66 | ||
|
4c819d9401 | ||
|
3dccccee5e | ||
|
144754b153 | ||
|
2e6152ee86 | ||
|
f9b8137457 | ||
|
08cb1af507 | ||
|
3448cf213b | ||
|
2900689117 | ||
|
ec12b7dc1e | ||
|
831bbcdc38 | ||
|
e63689fec0 | ||
|
ce0cfaaf3f | ||
|
262fa746b8 | ||
|
fb75ec2011 | ||
|
f2ef1a3447 | ||
|
eebe034cc1 | ||
|
7a3899f93f | ||
|
3ea2ca1ede | ||
|
8cd40a7e3c | ||
|
feb21547f9 | ||
|
26e9a73798 | ||
|
4b2bb5e9ab | ||
|
24a3d377d8 | ||
|
a79bbf3bdb | ||
|
4427aab6e3 | ||
|
10ec15d67c | ||
|
989266aaff | ||
|
7889cf45fa | ||
|
3cc3ca4d62 | ||
|
bbf681deaf | ||
|
1d86a7f5e8 | ||
|
77b84c1f56 | ||
|
2dc6a269f1 | ||
|
4be39f9509 | ||
|
5b91c24c11 | ||
|
8b82c0d750 | ||
|
878adb61bf | ||
|
90d46b8e4b | ||
|
ba53cd2aba | ||
|
cd0f7bbd34 | ||
|
9d618bc55f | ||
|
d44bc5b281 | ||
|
243b54c46e | ||
|
d00a3c6c93 | ||
|
d0ee341157 | ||
|
87f74a3d2b | ||
|
17e9e9c0be | ||
|
f5c73b4700 | ||
|
34e34e8c1d | ||
|
277672eab4 | ||
|
7e2044fa35 | ||
|
a7671f2808 | ||
|
fee41a1895 | ||
|
c4ec0f2daa |
50 changed files with 1763 additions and 497 deletions
54
Android.bp
54
Android.bp
|
@ -121,18 +121,50 @@ dexpreopt_systemserver_check {
|
|||
name: "dexpreopt_systemserver_check",
|
||||
}
|
||||
|
||||
// buildinfo.prop contains common properties for system/build.prop, like ro.build.version.*
|
||||
buildinfo_prop {
|
||||
name: "buildinfo.prop",
|
||||
|
||||
// not installable because this will be included to system/build.prop
|
||||
installable: false,
|
||||
|
||||
// Currently, only microdroid can refer to buildinfo.prop
|
||||
visibility: ["//packages/modules/Virtualization/microdroid"],
|
||||
}
|
||||
|
||||
// container for apex_contributions selected using build flags
|
||||
all_apex_contributions {
|
||||
name: "all_apex_contributions",
|
||||
}
|
||||
|
||||
product_config {
|
||||
name: "product_config",
|
||||
visibility: ["//device/google/cuttlefish/system_image"],
|
||||
}
|
||||
|
||||
build_prop {
|
||||
name: "system-build.prop",
|
||||
stem: "build.prop",
|
||||
product_config: ":product_config",
|
||||
// Currently, only microdroid and cf system image can refer to system-build.prop
|
||||
visibility: [
|
||||
"//device/google/cuttlefish/system_image",
|
||||
"//packages/modules/Virtualization/microdroid",
|
||||
],
|
||||
}
|
||||
|
||||
build_prop {
|
||||
name: "system_ext-build.prop",
|
||||
stem: "build.prop",
|
||||
system_ext_specific: true,
|
||||
product_config: ":product_config",
|
||||
relative_install_path: "etc", // system_ext/etc/build.prop
|
||||
visibility: ["//visibility:private"],
|
||||
}
|
||||
|
||||
build_prop {
|
||||
name: "product-build.prop",
|
||||
stem: "build.prop",
|
||||
product_specific: true,
|
||||
product_config: ":product_config",
|
||||
relative_install_path: "etc", // product/etc/build.prop
|
||||
visibility: ["//visibility:private"],
|
||||
}
|
||||
|
||||
build_prop {
|
||||
name: "odm-build.prop",
|
||||
stem: "build.prop",
|
||||
device_specific: true,
|
||||
product_config: ":product_config",
|
||||
relative_install_path: "etc", // odm/etc/build.prop
|
||||
visibility: ["//visibility:private"],
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ bootstrap_go_package {
|
|||
"arch_list.go",
|
||||
"arch_module_context.go",
|
||||
"base_module_context.go",
|
||||
"buildinfo_prop.go",
|
||||
"build_prop.go",
|
||||
"config.go",
|
||||
"test_config.go",
|
||||
"configurable_properties.go",
|
||||
|
@ -83,6 +83,7 @@ bootstrap_go_package {
|
|||
"plugin.go",
|
||||
"prebuilt.go",
|
||||
"prebuilt_build_tool.go",
|
||||
"product_config.go",
|
||||
"proto.go",
|
||||
"provider.go",
|
||||
"raw_files.go",
|
||||
|
@ -110,6 +111,7 @@ bootstrap_go_package {
|
|||
"androidmk_test.go",
|
||||
"apex_test.go",
|
||||
"arch_test.go",
|
||||
"blueprint_e2e_test.go",
|
||||
"config_test.go",
|
||||
"configured_jars_test.go",
|
||||
"csuite_config_test.go",
|
||||
|
|
|
@ -499,6 +499,7 @@ type fillInEntriesContext interface {
|
|||
Config() Config
|
||||
moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
|
||||
ModuleType(module blueprint.Module) string
|
||||
OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
|
||||
}
|
||||
|
||||
func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
|
||||
|
@ -514,7 +515,7 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint
|
|||
if a.Include == "" {
|
||||
a.Include = "$(BUILD_PREBUILT)"
|
||||
}
|
||||
a.Required = append(a.Required, amod.RequiredModuleNames()...)
|
||||
a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...)
|
||||
a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...)
|
||||
a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...)
|
||||
|
||||
|
|
105
android/blueprint_e2e_test.go
Normal file
105
android/blueprint_e2e_test.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2024 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package android
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var testCases []struct {
|
||||
name string
|
||||
fs MockFS
|
||||
expectedError string
|
||||
} = []struct {
|
||||
name string
|
||||
fs MockFS
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "Can't reference variable before assignment",
|
||||
fs: map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
x = foo
|
||||
foo = "hello"
|
||||
`),
|
||||
},
|
||||
expectedError: "undefined variable foo",
|
||||
},
|
||||
{
|
||||
name: "Can't append to variable before assigned to",
|
||||
fs: map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
foo += "world"
|
||||
foo = "hello"
|
||||
`),
|
||||
},
|
||||
expectedError: "modified non-existent variable \"foo\" with \\+=",
|
||||
},
|
||||
{
|
||||
name: "Can't reassign variable",
|
||||
fs: map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
foo = "hello"
|
||||
foo = "world"
|
||||
`),
|
||||
},
|
||||
expectedError: "variable already set, previous assignment:",
|
||||
},
|
||||
{
|
||||
name: "Can't reassign variable in inherited scope",
|
||||
fs: map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
foo = "hello"
|
||||
`),
|
||||
"foo/Android.bp": []byte(`
|
||||
foo = "world"
|
||||
`),
|
||||
},
|
||||
expectedError: "variable already set in inherited scope, previous assignment:",
|
||||
},
|
||||
{
|
||||
name: "Can't modify variable in inherited scope",
|
||||
fs: map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
foo = "hello"
|
||||
`),
|
||||
"foo/Android.bp": []byte(`
|
||||
foo += "world"
|
||||
`),
|
||||
},
|
||||
expectedError: "modified non-local variable \"foo\" with \\+=",
|
||||
},
|
||||
{
|
||||
name: "Can't modify variable after referencing",
|
||||
fs: map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
foo = "hello"
|
||||
x = foo
|
||||
foo += "world"
|
||||
`),
|
||||
},
|
||||
expectedError: "modified variable \"foo\" with \\+= after referencing",
|
||||
},
|
||||
}
|
||||
|
||||
func TestBlueprintErrors(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fixtures := FixtureMergeMockFs(tc.fs)
|
||||
fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
|
||||
fixtures.RunTest(t)
|
||||
})
|
||||
}
|
||||
}
|
195
android/build_prop.go
Normal file
195
android/build_prop.go
Normal file
|
@ -0,0 +1,195 @@
|
|||
// Copyright 2024 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package android
|
||||
|
||||
import (
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ctx := InitRegistrationContext
|
||||
ctx.RegisterModuleType("build_prop", buildPropFactory)
|
||||
}
|
||||
|
||||
type buildPropProperties struct {
|
||||
// Output file name. Defaults to "build.prop"
|
||||
Stem *string
|
||||
|
||||
// List of prop names to exclude. This affects not only common build properties but also
|
||||
// properties in prop_files.
|
||||
Block_list []string
|
||||
|
||||
// Files to be appended at the end of build.prop. These files are appended after
|
||||
// post_process_props without any further checking.
|
||||
Footer_files []string `android:"path"`
|
||||
|
||||
// Path to a JSON file containing product configs.
|
||||
Product_config *string `android:"path"`
|
||||
|
||||
// Optional subdirectory under which this file is installed into
|
||||
Relative_install_path *string
|
||||
}
|
||||
|
||||
type buildPropModule struct {
|
||||
ModuleBase
|
||||
|
||||
properties buildPropProperties
|
||||
|
||||
outputFilePath OutputPath
|
||||
installPath InstallPath
|
||||
}
|
||||
|
||||
func (p *buildPropModule) stem() string {
|
||||
return proptools.StringDefault(p.properties.Stem, "build.prop")
|
||||
}
|
||||
|
||||
func (p *buildPropModule) propFiles(ctx ModuleContext) Paths {
|
||||
partition := p.partition(ctx.DeviceConfig())
|
||||
if partition == "system" {
|
||||
return ctx.Config().SystemPropFiles(ctx)
|
||||
} else if partition == "system_ext" {
|
||||
return ctx.Config().SystemExtPropFiles(ctx)
|
||||
} else if partition == "product" {
|
||||
return ctx.Config().ProductPropFiles(ctx)
|
||||
} else if partition == "odm" {
|
||||
return ctx.Config().OdmPropFiles(ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func shouldAddBuildThumbprint(config Config) bool {
|
||||
knownOemProperties := []string{
|
||||
"ro.product.brand",
|
||||
"ro.product.name",
|
||||
"ro.product.device",
|
||||
}
|
||||
|
||||
for _, knownProp := range knownOemProperties {
|
||||
if InList(knownProp, config.OemProperties()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Can't use PartitionTag() because PartitionTag() returns the partition this module is actually
|
||||
// installed (e.g. odm module's partition tag can be either "odm" or "vendor")
|
||||
func (p *buildPropModule) partition(config DeviceConfig) string {
|
||||
if p.SocSpecific() {
|
||||
return "vendor"
|
||||
} else if p.DeviceSpecific() {
|
||||
return "odm"
|
||||
} else if p.ProductSpecific() {
|
||||
return "product"
|
||||
} else if p.SystemExtSpecific() {
|
||||
return "system_ext"
|
||||
}
|
||||
return "system"
|
||||
}
|
||||
|
||||
var validPartitions = []string{
|
||||
"system",
|
||||
"system_ext",
|
||||
"product",
|
||||
"odm",
|
||||
}
|
||||
|
||||
func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
p.outputFilePath = PathForModuleOut(ctx, "build.prop").OutputPath
|
||||
if !ctx.Config().KatiEnabled() {
|
||||
WriteFileRule(ctx, p.outputFilePath, "# no build.prop if kati is disabled")
|
||||
ctx.SetOutputFiles(Paths{p.outputFilePath}, "")
|
||||
return
|
||||
}
|
||||
|
||||
partition := p.partition(ctx.DeviceConfig())
|
||||
if !InList(partition, validPartitions) {
|
||||
ctx.PropertyErrorf("partition", "unsupported partition %q: only %q are supported", partition, validPartitions)
|
||||
return
|
||||
}
|
||||
|
||||
rule := NewRuleBuilder(pctx, ctx)
|
||||
|
||||
config := ctx.Config()
|
||||
|
||||
cmd := rule.Command().BuiltTool("gen_build_prop")
|
||||
|
||||
cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx))
|
||||
cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx))
|
||||
// shouldn't depend on BuildFingerprintFile and BuildThumbprintFile to prevent from rebuilding
|
||||
// on every incremental build.
|
||||
cmd.FlagWithArg("--build-fingerprint-file=", config.BuildFingerprintFile(ctx).String())
|
||||
// Export build thumbprint only if the product has specified at least one oem fingerprint property
|
||||
// b/17888863
|
||||
if shouldAddBuildThumbprint(config) {
|
||||
// In the previous make implementation, a dependency was not added on the thumbprint file
|
||||
cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String())
|
||||
}
|
||||
cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME"))
|
||||
// shouldn't depend on BUILD_DATETIME_FILE to prevent from rebuilding on every incremental
|
||||
// build.
|
||||
cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE"))
|
||||
cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx))
|
||||
cmd.FlagWithInput("--product-config=", PathForModuleSrc(ctx, proptools.String(p.properties.Product_config)))
|
||||
cmd.FlagWithArg("--partition=", partition)
|
||||
cmd.FlagForEachInput("--prop-files=", p.propFiles(ctx))
|
||||
cmd.FlagWithOutput("--out=", p.outputFilePath)
|
||||
|
||||
postProcessCmd := rule.Command().BuiltTool("post_process_props")
|
||||
if ctx.DeviceConfig().BuildBrokenDupSysprop() {
|
||||
postProcessCmd.Flag("--allow-dup")
|
||||
}
|
||||
postProcessCmd.FlagWithArg("--sdk-version ", config.PlatformSdkVersion().String())
|
||||
if ctx.Config().EnableUffdGc() == "default" {
|
||||
postProcessCmd.FlagWithInput("--kernel-version-file-for-uffd-gc ", PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt"))
|
||||
} else {
|
||||
// still need to pass an empty string to kernel-version-file-for-uffd-gc
|
||||
postProcessCmd.FlagWithArg("--kernel-version-file-for-uffd-gc ", `""`)
|
||||
}
|
||||
postProcessCmd.Text(p.outputFilePath.String())
|
||||
postProcessCmd.Flags(p.properties.Block_list)
|
||||
|
||||
rule.Command().Text("echo").Text(proptools.NinjaAndShellEscape("# end of file")).FlagWithArg(">> ", p.outputFilePath.String())
|
||||
|
||||
rule.Build(ctx.ModuleName(), "generating build.prop")
|
||||
|
||||
p.installPath = PathForModuleInstall(ctx, proptools.String(p.properties.Relative_install_path))
|
||||
ctx.InstallFile(p.installPath, p.stem(), p.outputFilePath)
|
||||
|
||||
ctx.SetOutputFiles(Paths{p.outputFilePath}, "")
|
||||
}
|
||||
|
||||
func (p *buildPropModule) AndroidMkEntries() []AndroidMkEntries {
|
||||
return []AndroidMkEntries{{
|
||||
Class: "ETC",
|
||||
OutputFile: OptionalPathForPath(p.outputFilePath),
|
||||
ExtraEntries: []AndroidMkExtraEntriesFunc{
|
||||
func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
|
||||
entries.SetString("LOCAL_MODULE_PATH", p.installPath.String())
|
||||
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
|
||||
},
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
// build_prop module generates {partition}/build.prop file. At first common build properties are
|
||||
// printed based on Soong config variables. And then prop_files are printed as-is. Finally,
|
||||
// post_process_props tool is run to check if the result build.prop is valid or not.
|
||||
func buildPropFactory() Module {
|
||||
module := &buildPropModule{}
|
||||
module.AddProperties(&module.properties)
|
||||
InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
|
||||
return module
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
// Copyright 2022 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package android
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ctx := InitRegistrationContext
|
||||
ctx.RegisterModuleType("buildinfo_prop", buildinfoPropFactory)
|
||||
}
|
||||
|
||||
type buildinfoPropProperties struct {
|
||||
// Whether this module is directly installable to one of the partitions. Default: true.
|
||||
Installable *bool
|
||||
}
|
||||
|
||||
type buildinfoPropModule struct {
|
||||
ModuleBase
|
||||
|
||||
properties buildinfoPropProperties
|
||||
|
||||
outputFilePath OutputPath
|
||||
installPath InstallPath
|
||||
}
|
||||
|
||||
var _ OutputFileProducer = (*buildinfoPropModule)(nil)
|
||||
|
||||
func (p *buildinfoPropModule) installable() bool {
|
||||
return proptools.BoolDefault(p.properties.Installable, true)
|
||||
}
|
||||
|
||||
// OutputFileProducer
|
||||
func (p *buildinfoPropModule) OutputFiles(tag string) (Paths, error) {
|
||||
if tag != "" {
|
||||
return nil, fmt.Errorf("unsupported tag %q", tag)
|
||||
}
|
||||
return Paths{p.outputFilePath}, nil
|
||||
}
|
||||
|
||||
func getBuildVariant(config Config) string {
|
||||
if config.Eng() {
|
||||
return "eng"
|
||||
} else if config.Debuggable() {
|
||||
return "userdebug"
|
||||
} else {
|
||||
return "user"
|
||||
}
|
||||
}
|
||||
|
||||
func getBuildFlavor(config Config) string {
|
||||
buildFlavor := config.DeviceProduct() + "-" + getBuildVariant(config)
|
||||
if InList("address", config.SanitizeDevice()) && !strings.Contains(buildFlavor, "_asan") {
|
||||
buildFlavor += "_asan"
|
||||
}
|
||||
return buildFlavor
|
||||
}
|
||||
|
||||
func shouldAddBuildThumbprint(config Config) bool {
|
||||
knownOemProperties := []string{
|
||||
"ro.product.brand",
|
||||
"ro.product.name",
|
||||
"ro.product.device",
|
||||
}
|
||||
|
||||
for _, knownProp := range knownOemProperties {
|
||||
if InList(knownProp, config.OemProperties()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
if ctx.ModuleName() != "buildinfo.prop" || ctx.ModuleDir() != "build/soong" {
|
||||
ctx.ModuleErrorf("There can only be one buildinfo_prop module in build/soong")
|
||||
return
|
||||
}
|
||||
p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath
|
||||
if !ctx.Config().KatiEnabled() {
|
||||
WriteFileRule(ctx, p.outputFilePath, "# no buildinfo.prop if kati is disabled")
|
||||
return
|
||||
}
|
||||
|
||||
rule := NewRuleBuilder(pctx, ctx)
|
||||
|
||||
config := ctx.Config()
|
||||
buildVariant := getBuildVariant(config)
|
||||
buildFlavor := getBuildFlavor(config)
|
||||
|
||||
cmd := rule.Command().BuiltTool("buildinfo")
|
||||
|
||||
if config.BoardUseVbmetaDigestInFingerprint() {
|
||||
cmd.Flag("--use-vbmeta-digest-in-fingerprint")
|
||||
}
|
||||
|
||||
cmd.FlagWithArg("--build-flavor=", buildFlavor)
|
||||
cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx))
|
||||
cmd.FlagWithArg("--build-id=", config.BuildId())
|
||||
cmd.FlagWithArg("--build-keys=", config.BuildKeys())
|
||||
|
||||
// Note: depending on BuildNumberFile will cause the build.prop file to be rebuilt
|
||||
// every build, but that's intentional.
|
||||
cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx))
|
||||
if shouldAddBuildThumbprint(config) {
|
||||
// In the previous make implementation, a dependency was not added on the thumbprint file
|
||||
cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String())
|
||||
}
|
||||
|
||||
cmd.FlagWithArg("--build-type=", config.BuildType())
|
||||
cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME"))
|
||||
cmd.FlagWithArg("--build-variant=", buildVariant)
|
||||
cmd.FlagForEachArg("--cpu-abis=", config.DeviceAbi())
|
||||
|
||||
// Technically we should also have a dependency on BUILD_DATETIME_FILE,
|
||||
// but it can be either an absolute or relative path, which is hard to turn into
|
||||
// a Path object. So just rely on the BuildNumberFile always changing to cause
|
||||
// us to rebuild.
|
||||
cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE"))
|
||||
|
||||
if len(config.ProductLocales()) > 0 {
|
||||
cmd.FlagWithArg("--default-locale=", config.ProductLocales()[0])
|
||||
}
|
||||
|
||||
cmd.FlagForEachArg("--default-wifi-channels=", config.ProductDefaultWifiChannels())
|
||||
cmd.FlagWithArg("--device=", config.DeviceName())
|
||||
if config.DisplayBuildNumber() {
|
||||
cmd.Flag("--display-build-number")
|
||||
}
|
||||
|
||||
cmd.FlagWithArg("--platform-base-os=", config.PlatformBaseOS())
|
||||
cmd.FlagWithArg("--platform-display-version=", config.PlatformDisplayVersionName())
|
||||
cmd.FlagWithArg("--platform-min-supported-target-sdk-version=", config.PlatformMinSupportedTargetSdkVersion())
|
||||
cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx))
|
||||
cmd.FlagWithArg("--platform-preview-sdk-version=", config.PlatformPreviewSdkVersion())
|
||||
cmd.FlagWithArg("--platform-sdk-version=", config.PlatformSdkVersion().String())
|
||||
cmd.FlagWithArg("--platform-security-patch=", config.PlatformSecurityPatch())
|
||||
cmd.FlagWithArg("--platform-version=", config.PlatformVersionName())
|
||||
cmd.FlagWithArg("--platform-version-codename=", config.PlatformSdkCodename())
|
||||
cmd.FlagForEachArg("--platform-version-all-codenames=", config.PlatformVersionActiveCodenames())
|
||||
cmd.FlagWithArg("--platform-version-known-codenames=", config.PlatformVersionKnownCodenames())
|
||||
cmd.FlagWithArg("--platform-version-last-stable=", config.PlatformVersionLastStable())
|
||||
cmd.FlagWithArg("--product=", config.DeviceProduct())
|
||||
|
||||
cmd.FlagWithOutput("--out=", p.outputFilePath)
|
||||
|
||||
rule.Build(ctx.ModuleName(), "generating buildinfo props")
|
||||
|
||||
if !p.installable() {
|
||||
p.SkipInstall()
|
||||
}
|
||||
|
||||
p.installPath = PathForModuleInstall(ctx)
|
||||
ctx.InstallFile(p.installPath, p.Name(), p.outputFilePath)
|
||||
}
|
||||
|
||||
func (p *buildinfoPropModule) AndroidMkEntries() []AndroidMkEntries {
|
||||
return []AndroidMkEntries{{
|
||||
Class: "ETC",
|
||||
OutputFile: OptionalPathForPath(p.outputFilePath),
|
||||
ExtraEntries: []AndroidMkExtraEntriesFunc{
|
||||
func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
|
||||
entries.SetString("LOCAL_MODULE_PATH", p.installPath.String())
|
||||
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
|
||||
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
|
||||
},
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
// buildinfo_prop module generates a build.prop file, which contains a set of common
|
||||
// system/build.prop properties, such as ro.build.version.*. Not all properties are implemented;
|
||||
// currently this module is only for microdroid.
|
||||
func buildinfoPropFactory() Module {
|
||||
module := &buildinfoPropModule{}
|
||||
module.AddProperties(&module.properties)
|
||||
InitAndroidModule(module)
|
||||
return module
|
||||
}
|
|
@ -784,6 +784,17 @@ func (c *config) DisplayBuildNumber() bool {
|
|||
return Bool(c.productVariables.DisplayBuildNumber)
|
||||
}
|
||||
|
||||
// BuildFingerprintFile returns the path to a text file containing metadata
|
||||
// representing the current build's fingerprint.
|
||||
//
|
||||
// Rules that want to reference the build fingerprint should read from this file
|
||||
// without depending on it. They will run whenever their other dependencies
|
||||
// require them to run and get the current build fingerprint. This ensures they
|
||||
// don't rebuild on every incremental build when the build number changes.
|
||||
func (c *config) BuildFingerprintFile(ctx PathContext) Path {
|
||||
return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildFingerprintFile))
|
||||
}
|
||||
|
||||
// BuildNumberFile returns the path to a text file containing metadata
|
||||
// representing the current build's number.
|
||||
//
|
||||
|
@ -1423,6 +1434,10 @@ func (c *deviceConfig) DeviceKernelHeaderDirs() []string {
|
|||
return c.config.productVariables.DeviceKernelHeaders
|
||||
}
|
||||
|
||||
func (c *deviceConfig) TargetSpecificHeaderPath() string {
|
||||
return String(c.config.productVariables.TargetSpecificHeaderPath)
|
||||
}
|
||||
|
||||
// JavaCoverageEnabledForPath returns whether Java code coverage is enabled for
|
||||
// path. Coverage is enabled by default when the product variable
|
||||
// JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is
|
||||
|
@ -1883,6 +1898,10 @@ func (c *deviceConfig) BuildBrokenDontCheckSystemSdk() bool {
|
|||
return c.config.productVariables.BuildBrokenDontCheckSystemSdk
|
||||
}
|
||||
|
||||
func (c *deviceConfig) BuildBrokenDupSysprop() bool {
|
||||
return c.config.productVariables.BuildBrokenDupSysprop
|
||||
}
|
||||
|
||||
func (c *config) BuildWarningBadOptionalUsesLibsAllowlist() []string {
|
||||
return c.productVariables.BuildWarningBadOptionalUsesLibsAllowlist
|
||||
}
|
||||
|
@ -2078,3 +2097,31 @@ func (c *config) BoardUseVbmetaDigestInFingerprint() bool {
|
|||
func (c *config) OemProperties() []string {
|
||||
return c.productVariables.OemProperties
|
||||
}
|
||||
|
||||
func (c *config) UseDebugArt() bool {
|
||||
if c.productVariables.ArtTargetIncludeDebugBuild != nil {
|
||||
return Bool(c.productVariables.ArtTargetIncludeDebugBuild)
|
||||
}
|
||||
|
||||
return Bool(c.productVariables.Eng)
|
||||
}
|
||||
|
||||
func (c *config) SystemPropFiles(ctx PathContext) Paths {
|
||||
return PathsForSource(ctx, c.productVariables.SystemPropFiles)
|
||||
}
|
||||
|
||||
func (c *config) SystemExtPropFiles(ctx PathContext) Paths {
|
||||
return PathsForSource(ctx, c.productVariables.SystemExtPropFiles)
|
||||
}
|
||||
|
||||
func (c *config) ProductPropFiles(ctx PathContext) Paths {
|
||||
return PathsForSource(ctx, c.productVariables.ProductPropFiles)
|
||||
}
|
||||
|
||||
func (c *config) OdmPropFiles(ctx PathContext) Paths {
|
||||
return PathsForSource(ctx, c.productVariables.OdmPropFiles)
|
||||
}
|
||||
|
||||
func (c *config) EnableUffdGc() string {
|
||||
return String(c.productVariables.EnableUffdGc)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ type defaultsDependencyTag struct {
|
|||
var DefaultsDepTag defaultsDependencyTag
|
||||
|
||||
type defaultsProperties struct {
|
||||
Defaults []string
|
||||
Defaults proptools.Configurable[[]string]
|
||||
}
|
||||
|
||||
type DefaultableModuleBase struct {
|
||||
|
@ -278,13 +278,14 @@ func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
|
|||
|
||||
func defaultsDepsMutator(ctx BottomUpMutatorContext) {
|
||||
if defaultable, ok := ctx.Module().(Defaultable); ok {
|
||||
ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
|
||||
ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults.GetOrDefault(ctx, nil)...)
|
||||
}
|
||||
}
|
||||
|
||||
func defaultsMutator(ctx TopDownMutatorContext) {
|
||||
if defaultable, ok := ctx.Module().(Defaultable); ok {
|
||||
if len(defaultable.defaults().Defaults) > 0 {
|
||||
defaults := defaultable.defaults().Defaults.GetOrDefault(ctx, nil)
|
||||
if len(defaults) > 0 {
|
||||
var defaultsList []Defaults
|
||||
seen := make(map[Defaults]bool)
|
||||
|
||||
|
@ -294,7 +295,7 @@ func defaultsMutator(ctx TopDownMutatorContext) {
|
|||
if !seen[defaults] {
|
||||
seen[defaults] = true
|
||||
defaultsList = append(defaultsList, defaults)
|
||||
return len(defaults.defaults().Defaults) > 0
|
||||
return len(defaults.defaults().Defaults.GetOrDefault(ctx, nil)) > 0
|
||||
}
|
||||
} else {
|
||||
ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
|
||||
|
|
|
@ -113,7 +113,7 @@ type Module interface {
|
|||
// Get information about the properties that can contain visibility rules.
|
||||
visibilityProperties() []visibilityProperty
|
||||
|
||||
RequiredModuleNames() []string
|
||||
RequiredModuleNames(ctx ConfigAndErrorContext) []string
|
||||
HostRequiredModuleNames() []string
|
||||
TargetRequiredModuleNames() []string
|
||||
|
||||
|
@ -419,10 +419,10 @@ type commonProperties struct {
|
|||
Init_rc []string `android:"arch_variant,path"`
|
||||
|
||||
// VINTF manifest fragments to be installed if this module is installed
|
||||
Vintf_fragments []string `android:"path"`
|
||||
Vintf_fragments proptools.Configurable[[]string] `android:"path"`
|
||||
|
||||
// names of other modules to install if this module is installed
|
||||
Required []string `android:"arch_variant"`
|
||||
Required proptools.Configurable[[]string] `android:"arch_variant"`
|
||||
|
||||
// names of other modules to install on host if this module is installed
|
||||
Host_required []string `android:"arch_variant"`
|
||||
|
@ -1101,7 +1101,7 @@ func addRequiredDeps(ctx BottomUpMutatorContext) {
|
|||
hostTargets = append(hostTargets, ctx.Config().BuildOSCommonTarget)
|
||||
|
||||
if ctx.Device() {
|
||||
for _, depName := range ctx.Module().RequiredModuleNames() {
|
||||
for _, depName := range ctx.Module().RequiredModuleNames(ctx) {
|
||||
for _, target := range deviceTargets {
|
||||
addDep(target, depName)
|
||||
}
|
||||
|
@ -1114,7 +1114,7 @@ func addRequiredDeps(ctx BottomUpMutatorContext) {
|
|||
}
|
||||
|
||||
if ctx.Host() {
|
||||
for _, depName := range ctx.Module().RequiredModuleNames() {
|
||||
for _, depName := range ctx.Module().RequiredModuleNames(ctx) {
|
||||
for _, target := range hostTargets {
|
||||
// When a host module requires another host module, don't make a
|
||||
// dependency if they have different OSes (i.e. hostcross).
|
||||
|
@ -1619,8 +1619,8 @@ func (m *ModuleBase) InRecovery() bool {
|
|||
return m.base().commonProperties.ImageVariation == RecoveryVariation
|
||||
}
|
||||
|
||||
func (m *ModuleBase) RequiredModuleNames() []string {
|
||||
return m.base().commonProperties.Required
|
||||
func (m *ModuleBase) RequiredModuleNames(ctx ConfigAndErrorContext) []string {
|
||||
return m.base().commonProperties.Required.GetOrDefault(m.ConfigurableEvaluator(ctx), nil)
|
||||
}
|
||||
|
||||
func (m *ModuleBase) HostRequiredModuleNames() []string {
|
||||
|
@ -1881,7 +1881,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
|
|||
}
|
||||
}
|
||||
|
||||
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
|
||||
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments.GetOrDefault(ctx, nil))
|
||||
vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
|
||||
for _, src := range m.vintfFragmentsPaths {
|
||||
installedVintfFragment := vintfDir.Join(ctx, src.Base())
|
||||
|
@ -1992,7 +1992,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
|
|||
TargetDependencies: targetRequired,
|
||||
HostDependencies: hostRequired,
|
||||
Data: data,
|
||||
Required: m.RequiredModuleNames(),
|
||||
Required: m.RequiredModuleNames(ctx),
|
||||
}
|
||||
SetProvider(ctx, ModuleInfoJSONProvider, m.moduleInfoJSON)
|
||||
}
|
||||
|
@ -2194,6 +2194,9 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu
|
|||
switch variable {
|
||||
case "debuggable":
|
||||
return proptools.ConfigurableValueBool(ctx.Config().Debuggable())
|
||||
case "use_debug_art":
|
||||
// TODO(b/234351700): Remove once ART does not have separated debug APEX
|
||||
return proptools.ConfigurableValueBool(ctx.Config().UseDebugArt())
|
||||
default:
|
||||
// TODO(b/323382414): Might add these on a case-by-case basis
|
||||
ctx.OtherModulePropertyErrorf(m, property, fmt.Sprintf("TODO(b/323382414): Product variable %q is not yet supported in selects", variable))
|
||||
|
@ -2208,7 +2211,20 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu
|
|||
variable := condition.Arg(1)
|
||||
if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok {
|
||||
if v, ok := n[variable]; ok {
|
||||
return proptools.ConfigurableValueString(v)
|
||||
ty := ""
|
||||
if namespaces, ok := ctx.Config().productVariables.VendorVarTypes[namespace]; ok {
|
||||
ty = namespaces[variable]
|
||||
}
|
||||
switch ty {
|
||||
case "":
|
||||
// strings are the default, we don't bother writing them to the soong variables json file
|
||||
return proptools.ConfigurableValueString(v)
|
||||
case "bool":
|
||||
return proptools.ConfigurableValueBool(v == "true")
|
||||
default:
|
||||
panic("unhandled soong config variable type: " + ty)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return proptools.ConfigurableValueUndefined()
|
||||
|
|
|
@ -183,7 +183,7 @@ type ModuleContext interface {
|
|||
InstallInVendor() bool
|
||||
InstallForceOS() (*OsType, *ArchType)
|
||||
|
||||
RequiredModuleNames() []string
|
||||
RequiredModuleNames(ctx ConfigAndErrorContext) []string
|
||||
HostRequiredModuleNames() []string
|
||||
TargetRequiredModuleNames() []string
|
||||
|
||||
|
@ -755,8 +755,8 @@ func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) Optional
|
|||
return OptionalPath{}
|
||||
}
|
||||
|
||||
func (m *moduleContext) RequiredModuleNames() []string {
|
||||
return m.module.RequiredModuleNames()
|
||||
func (m *moduleContext) RequiredModuleNames(ctx ConfigAndErrorContext) []string {
|
||||
return m.module.RequiredModuleNames(ctx)
|
||||
}
|
||||
|
||||
func (m *moduleContext) HostRequiredModuleNames() []string {
|
||||
|
|
|
@ -722,7 +722,6 @@ test {
|
|||
propInfo{Name: "Arch.X86_64.A", Type: "string", Value: "x86_64 a"},
|
||||
propInfo{Name: "B", Type: "bool", Value: "true"},
|
||||
propInfo{Name: "C", Type: "string slice", Values: []string{"default_c", "c"}},
|
||||
propInfo{Name: "Defaults", Type: "string slice", Values: []string{"foo_defaults"}},
|
||||
propInfo{Name: "Embedded_prop", Type: "string", Value: "a"},
|
||||
propInfo{Name: "Name", Type: "string", Value: "foo"},
|
||||
propInfo{Name: "Nested.E", Type: "string", Value: "nested e"},
|
||||
|
@ -746,7 +745,6 @@ test {
|
|||
foo := result.ModuleForTests("foo", "").Module().base()
|
||||
|
||||
AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,6 +156,9 @@ func (r *NameResolver) addNamespace(namespace *Namespace) (err error) {
|
|||
return fmt.Errorf("a namespace must be the first module in the file")
|
||||
}
|
||||
}
|
||||
if (namespace.exportToKati) {
|
||||
r.rootNamespace.visibleNamespaces = append(r.rootNamespace.visibleNamespaces, namespace)
|
||||
}
|
||||
r.sortedNamespaces.add(namespace)
|
||||
|
||||
r.namespacesByDir.Store(namespace.Path, namespace)
|
||||
|
|
|
@ -1145,6 +1145,31 @@ func pathForSource(ctx PathContext, pathComponents ...string) (SourcePath, error
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
// pathForSourceRelaxed creates a SourcePath from pathComponents, but does not check that it exists.
|
||||
// It differs from pathForSource in that the path is allowed to exist outside of the PathContext.
|
||||
func pathForSourceRelaxed(ctx PathContext, pathComponents ...string) (SourcePath, error) {
|
||||
p := filepath.Join(pathComponents...)
|
||||
ret := SourcePath{basePath{p, ""}}
|
||||
|
||||
abs, err := filepath.Abs(ret.String())
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
buildroot, err := filepath.Abs(ctx.Config().soongOutDir)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
if strings.HasPrefix(abs, buildroot) {
|
||||
return ret, fmt.Errorf("source path %s is in output", abs)
|
||||
}
|
||||
|
||||
if pathtools.IsGlob(ret.String()) {
|
||||
return ret, fmt.Errorf("path may not contain a glob: %s", ret.String())
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// existsWithDependencies returns true if the path exists, and adds appropriate dependencies to rerun if the
|
||||
// path does not exist.
|
||||
func existsWithDependencies(ctx PathGlobContext, path SourcePath) (exists bool, err error) {
|
||||
|
@ -1190,6 +1215,31 @@ func PathForSource(ctx PathContext, pathComponents ...string) SourcePath {
|
|||
return path
|
||||
}
|
||||
|
||||
// PathForSourceRelaxed joins the provided path components. Unlike PathForSource,
|
||||
// the result is allowed to exist outside of the source dir.
|
||||
// On error, it will return a usable, but invalid SourcePath, and report a ModuleError.
|
||||
func PathForSourceRelaxed(ctx PathContext, pathComponents ...string) SourcePath {
|
||||
path, err := pathForSourceRelaxed(ctx, pathComponents...)
|
||||
if err != nil {
|
||||
reportPathError(ctx, err)
|
||||
}
|
||||
|
||||
if modCtx, ok := ctx.(ModuleContext); ok && ctx.Config().AllowMissingDependencies() {
|
||||
exists, err := existsWithDependencies(modCtx, path)
|
||||
if err != nil {
|
||||
reportPathError(ctx, err)
|
||||
}
|
||||
if !exists {
|
||||
modCtx.AddMissingDependencies([]string{path.String()})
|
||||
}
|
||||
} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
|
||||
ReportPathErrorf(ctx, "%s: %s", path, err.Error())
|
||||
} else if !exists {
|
||||
ReportPathErrorf(ctx, "source path %s does not exist", path)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// PathForArbitraryOutput creates a path for the given components. Unlike PathForOutput,
|
||||
// the path is relative to the root of the output folder, not the out/soong folder.
|
||||
func PathForArbitraryOutput(ctx PathContext, pathComponents ...string) Path {
|
||||
|
@ -1970,7 +2020,7 @@ func validatePathInternal(allowNinjaVariables bool, pathComponents ...string) (s
|
|||
}
|
||||
|
||||
path := filepath.Clean(path)
|
||||
if path == ".." || strings.HasPrefix(path, "../") || strings.HasPrefix(path, "/") {
|
||||
if path == ".." || strings.HasPrefix(path, "../") || i != initialEmpty && strings.HasPrefix(path, "/") {
|
||||
return "", fmt.Errorf("Path is outside directory: %s", path)
|
||||
}
|
||||
|
||||
|
|
58
android/product_config.go
Normal file
58
android/product_config.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2024 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package android
|
||||
|
||||
import "github.com/google/blueprint/proptools"
|
||||
|
||||
func init() {
|
||||
ctx := InitRegistrationContext
|
||||
ctx.RegisterModuleType("product_config", productConfigFactory)
|
||||
}
|
||||
|
||||
type productConfigModule struct {
|
||||
ModuleBase
|
||||
}
|
||||
|
||||
func (p *productConfigModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
if ctx.ModuleName() != "product_config" || ctx.ModuleDir() != "build/soong" {
|
||||
ctx.ModuleErrorf("There can only be one product_config module in build/soong")
|
||||
return
|
||||
}
|
||||
outputFilePath := PathForModuleOut(ctx, p.Name()+".json").OutputPath
|
||||
|
||||
// DeviceProduct can be null so calling ctx.Config().DeviceProduct() may cause null dereference
|
||||
targetProduct := proptools.String(ctx.Config().config.productVariables.DeviceProduct)
|
||||
if targetProduct != "" {
|
||||
targetProduct += "."
|
||||
}
|
||||
soongVariablesPath := PathForOutput(ctx, "soong."+targetProduct+"variables")
|
||||
extraVariablesPath := PathForOutput(ctx, "soong."+targetProduct+"extra.variables")
|
||||
|
||||
rule := NewRuleBuilder(pctx, ctx)
|
||||
rule.Command().BuiltTool("merge_json").
|
||||
Output(outputFilePath).
|
||||
Input(soongVariablesPath).
|
||||
Input(extraVariablesPath).
|
||||
rule.Build("product_config.json", "building product_config.json")
|
||||
|
||||
ctx.SetOutputFiles(Paths{outputFilePath}, "")
|
||||
}
|
||||
|
||||
// product_config module exports product variables and extra variables as a JSON file.
|
||||
func productConfigFactory() Module {
|
||||
module := &productConfigModule{}
|
||||
InitAndroidModule(module)
|
||||
return module
|
||||
}
|
|
@ -25,12 +25,14 @@ import (
|
|||
|
||||
func TestSelects(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
bp string
|
||||
provider selectsTestProvider
|
||||
providers map[string]selectsTestProvider
|
||||
vendorVars map[string]map[string]string
|
||||
expectedError string
|
||||
name string
|
||||
bp string
|
||||
fs MockFS
|
||||
provider selectsTestProvider
|
||||
providers map[string]selectsTestProvider
|
||||
vendorVars map[string]map[string]string
|
||||
vendorVarTypes map[string]map[string]string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "basic string list",
|
||||
|
@ -96,6 +98,26 @@ func TestSelects(t *testing.T) {
|
|||
my_paths: &[]string{"baz.txt"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Expression in select",
|
||||
bp: `
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
"a": "foo" + "bar",
|
||||
default: "baz",
|
||||
}),
|
||||
}
|
||||
`,
|
||||
provider: selectsTestProvider{
|
||||
my_string: proptools.StringPtr("foobar"),
|
||||
},
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"my_variable": "a",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "paths with module references",
|
||||
bp: `
|
||||
|
@ -110,20 +132,6 @@ func TestSelects(t *testing.T) {
|
|||
`,
|
||||
expectedError: `"foo" depends on undefined module "c"`,
|
||||
},
|
||||
{
|
||||
name: "Differing types",
|
||||
bp: `
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
"a": "a.cpp",
|
||||
"b": true,
|
||||
default: "c.cpp",
|
||||
}),
|
||||
}
|
||||
`,
|
||||
expectedError: `Android.bp:8:5: Found select statement with differing types "string" and "bool" in its cases`,
|
||||
},
|
||||
{
|
||||
name: "Select type doesn't match property type",
|
||||
bp: `
|
||||
|
@ -136,7 +144,7 @@ func TestSelects(t *testing.T) {
|
|||
}),
|
||||
}
|
||||
`,
|
||||
expectedError: `can't assign bool value to string property "my_string\[0\]"`,
|
||||
expectedError: `can't assign bool value to string property`,
|
||||
},
|
||||
{
|
||||
name: "String list non-default",
|
||||
|
@ -583,6 +591,31 @@ func TestSelects(t *testing.T) {
|
|||
my_string: proptools.StringPtr("t"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Select on boolean soong config variable",
|
||||
bp: `
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
true: "t",
|
||||
false: "f",
|
||||
}),
|
||||
}
|
||||
`,
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"my_variable": "true",
|
||||
},
|
||||
},
|
||||
vendorVarTypes: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"my_variable": "bool",
|
||||
},
|
||||
},
|
||||
provider: selectsTestProvider{
|
||||
my_string: proptools.StringPtr("t"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Select on boolean false",
|
||||
bp: `
|
||||
|
@ -799,10 +832,216 @@ func TestSelects(t *testing.T) {
|
|||
my_string_list: &[]string{"a.cpp", "c.cpp", "foo.cpp"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Arch variant bool",
|
||||
bp: `
|
||||
my_variable = ["b.cpp"]
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
arch_variant_configurable_bool: false,
|
||||
target: {
|
||||
bionic_arm64: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
`,
|
||||
provider: selectsTestProvider{
|
||||
arch_variant_configurable_bool: proptools.BoolPtr(false),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Simple string binding",
|
||||
bp: `
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
any @ my_binding: "hello " + my_binding,
|
||||
default: "goodbye",
|
||||
})
|
||||
}
|
||||
`,
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"my_variable": "world!",
|
||||
},
|
||||
},
|
||||
provider: selectsTestProvider{
|
||||
my_string: proptools.StringPtr("hello world!"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Any branch with binding not taken",
|
||||
bp: `
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
any @ my_binding: "hello " + my_binding,
|
||||
default: "goodbye",
|
||||
})
|
||||
}
|
||||
`,
|
||||
provider: selectsTestProvider{
|
||||
my_string: proptools.StringPtr("goodbye"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Any branch without binding",
|
||||
bp: `
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
any: "hello",
|
||||
default: "goodbye",
|
||||
})
|
||||
}
|
||||
`,
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"my_variable": "world!",
|
||||
},
|
||||
},
|
||||
provider: selectsTestProvider{
|
||||
my_string: proptools.StringPtr("hello"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Binding conflicts with file-level variable",
|
||||
bp: `
|
||||
my_binding = "asdf"
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
any @ my_binding: "hello",
|
||||
default: "goodbye",
|
||||
})
|
||||
}
|
||||
`,
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"my_variable": "world!",
|
||||
},
|
||||
},
|
||||
expectedError: "variable already set in inherited scope, previous assignment",
|
||||
},
|
||||
{
|
||||
name: "Binding in combination with file-level variable",
|
||||
bp: `
|
||||
my_var = " there "
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "my_variable"), {
|
||||
any @ my_binding: "hello" + my_var + my_binding,
|
||||
default: "goodbye",
|
||||
})
|
||||
}
|
||||
`,
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"my_variable": "world!",
|
||||
},
|
||||
},
|
||||
provider: selectsTestProvider{
|
||||
my_string: proptools.StringPtr("hello there world!"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Bindings in subdirectory inherits variable",
|
||||
fs: map[string][]byte{
|
||||
"Android.bp": []byte(`
|
||||
my_var = "abcd"
|
||||
`),
|
||||
"directoryB/Android.bp": []byte(`
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "variable_a"), {
|
||||
any @ my_binding: my_var + my_binding,
|
||||
default: "",
|
||||
}),
|
||||
}
|
||||
`),
|
||||
},
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"variable_a": "e",
|
||||
},
|
||||
},
|
||||
provider: selectsTestProvider{
|
||||
my_string: proptools.StringPtr("abcde"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Cannot modify variable after referenced by select",
|
||||
bp: `
|
||||
my_var = "foo"
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "variable_a"), {
|
||||
"a": my_var,
|
||||
default: "",
|
||||
}),
|
||||
}
|
||||
my_var += "bar"
|
||||
`,
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"variable_a": "b", // notably not the value that causes my_var to be referenced
|
||||
},
|
||||
},
|
||||
expectedError: `modified variable "my_var" with \+= after referencing`,
|
||||
},
|
||||
{
|
||||
name: "Cannot shadow variable with binding",
|
||||
bp: `
|
||||
my_var = "foo"
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
my_string: select(soong_config_variable("my_namespace", "variable_a"), {
|
||||
any @ my_var: my_var,
|
||||
default: "",
|
||||
}),
|
||||
}
|
||||
`,
|
||||
vendorVars: map[string]map[string]string{
|
||||
"my_namespace": {
|
||||
"variable_a": "a",
|
||||
},
|
||||
},
|
||||
expectedError: `variable already set in inherited scope, previous assignment:`,
|
||||
},
|
||||
{
|
||||
name: "Basic string list postprocessor",
|
||||
bp: `
|
||||
my_defaults {
|
||||
name: "defaults_a",
|
||||
my_string_list: ["a", "b", "c"],
|
||||
string_list_postprocessor_add_to_elements: "1",
|
||||
}
|
||||
my_defaults {
|
||||
name: "defaults_b",
|
||||
my_string_list: ["d", "e", "f"],
|
||||
string_list_postprocessor_add_to_elements: "2",
|
||||
}
|
||||
my_module_type {
|
||||
name: "foo",
|
||||
defaults: ["defaults_a", "defaults_b"],
|
||||
}
|
||||
`,
|
||||
provider: selectsTestProvider{
|
||||
my_string_list: &[]string{"d2", "e2", "f2", "a1", "b1", "c1"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fs := tc.fs
|
||||
if fs == nil {
|
||||
fs = make(MockFS)
|
||||
}
|
||||
if tc.bp != "" {
|
||||
fs["Android.bp"] = []byte(tc.bp)
|
||||
}
|
||||
fixtures := GroupFixturePreparers(
|
||||
PrepareForTestWithDefaults,
|
||||
PrepareForTestWithArchMutator,
|
||||
|
@ -813,12 +1052,14 @@ func TestSelects(t *testing.T) {
|
|||
}),
|
||||
FixtureModifyProductVariables(func(variables FixtureProductVariables) {
|
||||
variables.VendorVars = tc.vendorVars
|
||||
variables.VendorVarTypes = tc.vendorVarTypes
|
||||
}),
|
||||
FixtureMergeMockFs(fs),
|
||||
)
|
||||
if tc.expectedError != "" {
|
||||
fixtures = fixtures.ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(tc.expectedError))
|
||||
}
|
||||
result := fixtures.RunTestWithBp(t, tc.bp)
|
||||
result := fixtures.RunTest(t)
|
||||
|
||||
if tc.expectedError == "" {
|
||||
if len(tc.providers) == 0 {
|
||||
|
@ -846,6 +1087,7 @@ type selectsTestProvider struct {
|
|||
my_string_list *[]string
|
||||
my_paths *[]string
|
||||
replacing_string_list *[]string
|
||||
arch_variant_configurable_bool *bool
|
||||
my_nonconfigurable_bool *bool
|
||||
my_nonconfigurable_string *string
|
||||
my_nonconfigurable_string_list []string
|
||||
|
@ -870,6 +1112,7 @@ func (p *selectsTestProvider) String() string {
|
|||
my_string_list: %s,
|
||||
my_paths: %s,
|
||||
replacing_string_list %s,
|
||||
arch_variant_configurable_bool %v
|
||||
my_nonconfigurable_bool: %v,
|
||||
my_nonconfigurable_string: %s,
|
||||
my_nonconfigurable_string_list: %s,
|
||||
|
@ -879,6 +1122,7 @@ func (p *selectsTestProvider) String() string {
|
|||
p.my_string_list,
|
||||
p.my_paths,
|
||||
p.replacing_string_list,
|
||||
p.arch_variant_configurable_bool,
|
||||
p.my_nonconfigurable_bool,
|
||||
myNonconfigurableStringStr,
|
||||
p.my_nonconfigurable_string_list,
|
||||
|
@ -893,6 +1137,7 @@ type selectsMockModuleProperties struct {
|
|||
My_string_list proptools.Configurable[[]string]
|
||||
My_paths proptools.Configurable[[]string] `android:"path"`
|
||||
Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"`
|
||||
Arch_variant_configurable_bool proptools.Configurable[bool] `android:"replace_instead_of_append,arch_variant"`
|
||||
My_nonconfigurable_bool *bool
|
||||
My_nonconfigurable_string *string
|
||||
My_nonconfigurable_string_list []string
|
||||
|
@ -923,6 +1168,7 @@ func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
|||
my_string_list: optionalToPtr(p.properties.My_string_list.Get(ctx)),
|
||||
my_paths: optionalToPtr(p.properties.My_paths.Get(ctx)),
|
||||
replacing_string_list: optionalToPtr(p.properties.Replacing_string_list.Get(ctx)),
|
||||
arch_variant_configurable_bool: optionalToPtr(p.properties.Arch_variant_configurable_bool.Get(ctx)),
|
||||
my_nonconfigurable_bool: p.properties.My_nonconfigurable_bool,
|
||||
my_nonconfigurable_string: p.properties.My_nonconfigurable_string,
|
||||
my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list,
|
||||
|
@ -937,9 +1183,15 @@ func newSelectsMockModule() Module {
|
|||
return m
|
||||
}
|
||||
|
||||
type selectsMockDefaultsProperties struct {
|
||||
String_list_postprocessor_add_to_elements string
|
||||
}
|
||||
|
||||
type selectsMockModuleDefaults struct {
|
||||
ModuleBase
|
||||
DefaultsModuleBase
|
||||
myProperties selectsMockModuleProperties
|
||||
defaultsProperties selectsMockDefaultsProperties
|
||||
}
|
||||
|
||||
func (d *selectsMockModuleDefaults) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||
|
@ -949,10 +1201,22 @@ func newSelectsMockModuleDefaults() Module {
|
|||
module := &selectsMockModuleDefaults{}
|
||||
|
||||
module.AddProperties(
|
||||
&selectsMockModuleProperties{},
|
||||
&module.myProperties,
|
||||
&module.defaultsProperties,
|
||||
)
|
||||
|
||||
InitDefaultsModule(module)
|
||||
|
||||
AddLoadHook(module, func(lhc LoadHookContext) {
|
||||
if module.defaultsProperties.String_list_postprocessor_add_to_elements != "" {
|
||||
module.myProperties.My_string_list.AddPostProcessor(func(x []string) []string {
|
||||
for i := range x {
|
||||
x[i] = x[i] + module.defaultsProperties.String_list_postprocessor_add_to_elements
|
||||
}
|
||||
return x
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return module
|
||||
}
|
||||
|
|
|
@ -824,11 +824,16 @@ func (s *listVariable) printfIntoPropertyRecursive(fieldName []string, propStruc
|
|||
}
|
||||
field.Set(newField)
|
||||
case reflect.Struct:
|
||||
fieldName = append(fieldName, propStruct.Type().Field(i).Name)
|
||||
if err := s.printfIntoPropertyRecursive(fieldName, field, configValues); err != nil {
|
||||
return err
|
||||
if proptools.IsConfigurable(field.Type()) {
|
||||
fieldName = append(fieldName, propStruct.Type().Field(i).Name)
|
||||
return fmt.Errorf("soong_config_variables.%s.%s: list variables are not supported on configurable properties", s.variable, strings.Join(fieldName, "."))
|
||||
} else {
|
||||
fieldName = append(fieldName, propStruct.Type().Field(i).Name)
|
||||
if err := s.printfIntoPropertyRecursive(fieldName, field, configValues); err != nil {
|
||||
return err
|
||||
}
|
||||
fieldName = fieldName[:len(fieldName)-1]
|
||||
}
|
||||
fieldName = fieldName[:len(fieldName)-1]
|
||||
default:
|
||||
fieldName = append(fieldName, propStruct.Type().Field(i).Name)
|
||||
return fmt.Errorf("soong_config_variables.%s.%s: unsupported property type %q", s.variable, strings.Join(fieldName, "."), kind)
|
||||
|
|
|
@ -224,6 +224,10 @@ func (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext
|
|||
})
|
||||
}
|
||||
|
||||
func (ctx *TestContext) OtherModulePropertyErrorf(module Module, property string, fmt_ string, args ...interface{}) {
|
||||
panic(fmt.Sprintf(fmt_, args...))
|
||||
}
|
||||
|
||||
// registeredComponentOrder defines the order in which a sortableComponent type is registered at
|
||||
// runtime and provides support for reordering the components registered for a test in the same
|
||||
// way.
|
||||
|
|
|
@ -81,6 +81,16 @@ type variableProperties struct {
|
|||
Header_libs []string `android:"arch_variant"`
|
||||
} `android:"arch_variant"`
|
||||
|
||||
Malloc_low_memory_libc32 struct {
|
||||
Cflags []string `android:"arch_variant"`
|
||||
Shared_libs []string `android:"arch_variant"`
|
||||
Whole_static_libs []string `android:"arch_variant"`
|
||||
Static_libs []string `android:"arch_variant"`
|
||||
Exclude_static_libs []string `android:"arch_variant"`
|
||||
Srcs []string `android:"arch_variant"`
|
||||
Header_libs []string `android:"arch_variant"`
|
||||
} `android:"arch_variant"`
|
||||
|
||||
Malloc_zero_contents struct {
|
||||
Cflags []string `android:"arch_variant"`
|
||||
} `android:"arch_variant"`
|
||||
|
@ -150,6 +160,7 @@ type variableProperties struct {
|
|||
Eng struct {
|
||||
Cflags []string
|
||||
Cppflags []string
|
||||
Init_rc []string
|
||||
Lto struct {
|
||||
Never *bool
|
||||
}
|
||||
|
@ -199,11 +210,12 @@ type ProductVariables struct {
|
|||
// Suffix to add to generated Makefiles
|
||||
Make_suffix *string `json:",omitempty"`
|
||||
|
||||
BuildId *string `json:",omitempty"`
|
||||
BuildNumberFile *string `json:",omitempty"`
|
||||
BuildHostnameFile *string `json:",omitempty"`
|
||||
BuildThumbprintFile *string `json:",omitempty"`
|
||||
DisplayBuildNumber *bool `json:",omitempty"`
|
||||
BuildId *string `json:",omitempty"`
|
||||
BuildFingerprintFile *string `json:",omitempty"`
|
||||
BuildNumberFile *string `json:",omitempty"`
|
||||
BuildHostnameFile *string `json:",omitempty"`
|
||||
BuildThumbprintFile *string `json:",omitempty"`
|
||||
DisplayBuildNumber *bool `json:",omitempty"`
|
||||
|
||||
Platform_display_version_name *string `json:",omitempty"`
|
||||
Platform_version_name *string `json:",omitempty"`
|
||||
|
@ -285,6 +297,7 @@ type ProductVariables struct {
|
|||
Always_use_prebuilt_sdks *bool `json:",omitempty"`
|
||||
Skip_boot_jars_check *bool `json:",omitempty"`
|
||||
Malloc_low_memory *bool `json:",omitempty"`
|
||||
Malloc_low_memory_libc32 *bool `json:",omitempty"`
|
||||
Malloc_zero_contents *bool `json:",omitempty"`
|
||||
Malloc_pattern_fill_contents *bool `json:",omitempty"`
|
||||
Safestack *bool `json:",omitempty"`
|
||||
|
@ -362,6 +375,8 @@ type ProductVariables struct {
|
|||
|
||||
DeviceKernelHeaders []string `json:",omitempty"`
|
||||
|
||||
TargetSpecificHeaderPath *string `json:",omitempty"`
|
||||
|
||||
ExtraVndkVersions []string `json:",omitempty"`
|
||||
|
||||
NamespacesToExport []string `json:",omitempty"`
|
||||
|
@ -398,7 +413,8 @@ type ProductVariables struct {
|
|||
|
||||
PlatformSepolicyCompatVersions []string `json:",omitempty"`
|
||||
|
||||
VendorVars map[string]map[string]string `json:",omitempty"`
|
||||
VendorVars map[string]map[string]string `json:",omitempty"`
|
||||
VendorVarTypes map[string]map[string]string `json:",omitempty"`
|
||||
|
||||
Ndk_abis *bool `json:",omitempty"`
|
||||
|
||||
|
@ -458,6 +474,7 @@ type ProductVariables struct {
|
|||
BuildBrokenIncorrectPartitionImages bool `json:",omitempty"`
|
||||
BuildBrokenInputDirModules []string `json:",omitempty"`
|
||||
BuildBrokenDontCheckSystemSdk bool `json:",omitempty"`
|
||||
BuildBrokenDupSysprop bool `json:",omitempty"`
|
||||
|
||||
BuildWarningBadOptionalUsesLibsAllowlist []string `json:",omitempty"`
|
||||
|
||||
|
@ -513,6 +530,15 @@ type ProductVariables struct {
|
|||
BoardUseVbmetaDigestInFingerprint *bool `json:",omitempty"`
|
||||
|
||||
OemProperties []string `json:",omitempty"`
|
||||
|
||||
ArtTargetIncludeDebugBuild *bool `json:",omitempty"`
|
||||
|
||||
SystemPropFiles []string `json:",omitempty"`
|
||||
SystemExtPropFiles []string `json:",omitempty"`
|
||||
ProductPropFiles []string `json:",omitempty"`
|
||||
OdmPropFiles []string `json:",omitempty"`
|
||||
|
||||
EnableUffdGc *string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type PartitionQualifiedVariablesType struct {
|
||||
|
@ -617,6 +643,7 @@ func (v *ProductVariables) SetDefaultConfig() {
|
|||
AAPTPrebuiltDPI: []string{"xhdpi", "xxhdpi"},
|
||||
|
||||
Malloc_low_memory: boolPtr(false),
|
||||
Malloc_low_memory_libc32: boolPtr(false),
|
||||
Malloc_zero_contents: boolPtr(true),
|
||||
Malloc_pattern_fill_contents: boolPtr(false),
|
||||
Safestack: boolPtr(false),
|
||||
|
|
|
@ -341,9 +341,6 @@ func classifyLocalOrGlobalPath(value bpparser.Expression) (string, bpparser.Expr
|
|||
|
||||
firstOperand := v.Args[0]
|
||||
secondOperand := v.Args[1]
|
||||
if firstOperand.Type() != bpparser.StringType {
|
||||
return "global", value, nil
|
||||
}
|
||||
|
||||
if _, ok := firstOperand.(*bpparser.Operator); ok {
|
||||
return "global", value, nil
|
||||
|
@ -762,6 +759,13 @@ func cflags(ctx variableAssignmentContext) error {
|
|||
return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx)
|
||||
}
|
||||
|
||||
func exportCflags(ctx variableAssignmentContext) error {
|
||||
// The Soong replacement for EXPORT_CFLAGS doesn't need the same extra escaped quotes that were present in Make
|
||||
ctx.mkvalue = ctx.mkvalue.Clone()
|
||||
ctx.mkvalue.ReplaceLiteral(`\"`, `"`)
|
||||
return includeVariableNow(bpVariable{"export_cflags", bpparser.ListType}, ctx)
|
||||
}
|
||||
|
||||
func protoOutputParams(ctx variableAssignmentContext) error {
|
||||
// The Soong replacement for LOCAL_PROTO_JAVA_OUTPUT_PARAMS doesn't need ","
|
||||
ctx.mkvalue = ctx.mkvalue.Clone()
|
||||
|
|
|
@ -493,7 +493,6 @@ func setVariable(file *bpFile, plusequals bool, prefix, name string, value bppar
|
|||
Name: name,
|
||||
NamePos: pos,
|
||||
Value: value,
|
||||
OrigValue: value,
|
||||
EqualsPos: pos,
|
||||
Assigner: "+=",
|
||||
}
|
||||
|
@ -506,7 +505,6 @@ func setVariable(file *bpFile, plusequals bool, prefix, name string, value bppar
|
|||
Name: name,
|
||||
NamePos: pos,
|
||||
Value: value,
|
||||
OrigValue: value,
|
||||
EqualsPos: pos,
|
||||
Assigner: "=",
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ func makeToStringExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Exp
|
|||
}
|
||||
tmp := &bpparser.Variable{
|
||||
Name: name,
|
||||
Value: &bpparser.String{},
|
||||
Type_: bpparser.StringType,
|
||||
}
|
||||
|
||||
if tmp.Name == "TOP" {
|
||||
|
@ -150,7 +150,7 @@ func makeToListExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expre
|
|||
}
|
||||
listOfListValues = append(listOfListValues, &bpparser.Variable{
|
||||
Name: name,
|
||||
Value: &bpparser.List{},
|
||||
Type_: bpparser.ListType,
|
||||
})
|
||||
listValue = &bpparser.List{}
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ func makeToBoolExpression(ms *mkparser.MakeString, file *bpFile) (bpparser.Expre
|
|||
}
|
||||
return &bpparser.Variable{
|
||||
Name: name,
|
||||
Value: &bpparser.Bool{},
|
||||
Type_: bpparser.BoolType,
|
||||
}, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("non-const bool expression %s", ms.Dump())
|
||||
|
|
|
@ -218,7 +218,7 @@ func (a *apexBundle) writeRequiredModules(w io.Writer, moduleNames []string) {
|
|||
var required []string
|
||||
var targetRequired []string
|
||||
var hostRequired []string
|
||||
required = append(required, a.RequiredModuleNames()...)
|
||||
required = append(required, a.required...)
|
||||
targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...)
|
||||
hostRequired = append(hostRequired, a.HostRequiredModuleNames()...)
|
||||
for _, fi := range a.filesInfo {
|
||||
|
|
72
apex/apex.go
72
apex/apex.go
|
@ -86,7 +86,7 @@ type apexBundleProperties struct {
|
|||
|
||||
// AndroidManifest.xml file used for the zip container of this APEX bundle. If unspecified,
|
||||
// a default one is automatically generated.
|
||||
AndroidManifest *string `android:"path"`
|
||||
AndroidManifest proptools.Configurable[string] `android:"path,replace_instead_of_append"`
|
||||
|
||||
// Determines the file contexts file for setting the security contexts to files in this APEX
|
||||
// bundle. For platform APEXes, this should points to a file under /system/sepolicy Default:
|
||||
|
@ -104,7 +104,7 @@ type apexBundleProperties struct {
|
|||
// path_or_glob is a path or glob pattern for a file or set of files,
|
||||
// uid/gid are numerial values of user ID and group ID, mode is octal value
|
||||
// for the file mode, and cap is hexadecimal value for the capability.
|
||||
Canned_fs_config *string `android:"path"`
|
||||
Canned_fs_config proptools.Configurable[string] `android:"path,replace_instead_of_append"`
|
||||
|
||||
ApexNativeDependencies
|
||||
|
||||
|
@ -117,7 +117,8 @@ type apexBundleProperties struct {
|
|||
Bootclasspath_fragments []string
|
||||
|
||||
// List of systemserverclasspath fragments that are embedded inside this APEX bundle.
|
||||
Systemserverclasspath_fragments []string
|
||||
Systemserverclasspath_fragments proptools.Configurable[[]string]
|
||||
ResolvedSystemserverclasspathFragments []string `blueprint:"mutated"`
|
||||
|
||||
// List of java libraries that are embedded inside this APEX bundle.
|
||||
Java_libs []string
|
||||
|
@ -222,7 +223,8 @@ type ApexNativeDependencies struct {
|
|||
Rust_dyn_libs []string
|
||||
|
||||
// List of native executables that are embedded inside this APEX.
|
||||
Binaries []string
|
||||
Binaries proptools.Configurable[[]string]
|
||||
ResolvedBinaries []string `blueprint:"mutated"`
|
||||
|
||||
// List of native tests that are embedded inside this APEX.
|
||||
Tests []string
|
||||
|
@ -231,7 +233,8 @@ type ApexNativeDependencies struct {
|
|||
Filesystems []string
|
||||
|
||||
// List of prebuilt_etcs that are embedded inside this APEX bundle.
|
||||
Prebuilts []string
|
||||
Prebuilts proptools.Configurable[[]string]
|
||||
ResolvedPrebuilts []string `blueprint:"mutated"`
|
||||
|
||||
// List of native libraries to exclude from this APEX.
|
||||
Exclude_native_shared_libs []string
|
||||
|
@ -256,14 +259,14 @@ type ApexNativeDependencies struct {
|
|||
}
|
||||
|
||||
// Merge combines another ApexNativeDependencies into this one
|
||||
func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) {
|
||||
func (a *ApexNativeDependencies) Merge(ctx android.BaseMutatorContext, b ApexNativeDependencies) {
|
||||
a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...)
|
||||
a.Jni_libs = append(a.Jni_libs, b.Jni_libs...)
|
||||
a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
|
||||
a.Binaries = append(a.Binaries, b.Binaries...)
|
||||
a.ResolvedBinaries = append(a.ResolvedBinaries, b.Binaries.GetOrDefault(ctx, nil)...)
|
||||
a.Tests = append(a.Tests, b.Tests...)
|
||||
a.Filesystems = append(a.Filesystems, b.Filesystems...)
|
||||
a.Prebuilts = append(a.Prebuilts, b.Prebuilts...)
|
||||
a.ResolvedPrebuilts = append(a.ResolvedPrebuilts, b.Prebuilts.GetOrDefault(ctx, nil)...)
|
||||
|
||||
a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
|
||||
a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
|
||||
|
@ -339,10 +342,10 @@ type apexArchBundleProperties struct {
|
|||
// base apex.
|
||||
type overridableProperties struct {
|
||||
// List of APKs that are embedded inside this APEX.
|
||||
Apps []string
|
||||
Apps proptools.Configurable[[]string]
|
||||
|
||||
// List of prebuilt files that are embedded inside this APEX bundle.
|
||||
Prebuilts []string
|
||||
Prebuilts proptools.Configurable[[]string]
|
||||
|
||||
// List of BPF programs inside this APEX bundle.
|
||||
Bpfs []string
|
||||
|
@ -489,6 +492,9 @@ type apexBundle struct {
|
|||
javaApisUsedByModuleFile android.ModuleOutPath
|
||||
|
||||
aconfigFiles []android.Path
|
||||
|
||||
// Required modules, filled out during GenerateAndroidBuildActions and used in AndroidMk
|
||||
required []string
|
||||
}
|
||||
|
||||
// apexFileClass represents a type of file that can be included in APEX.
|
||||
|
@ -567,7 +573,7 @@ func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidM
|
|||
if module != nil {
|
||||
ret.moduleDir = ctx.OtherModuleDir(module)
|
||||
ret.partition = module.PartitionTag(ctx.DeviceConfig())
|
||||
ret.requiredModuleNames = module.RequiredModuleNames()
|
||||
ret.requiredModuleNames = module.RequiredModuleNames(ctx)
|
||||
ret.targetRequiredModuleNames = module.TargetRequiredModuleNames()
|
||||
ret.hostRequiredModuleNames = module.HostRequiredModuleNames()
|
||||
ret.multilib = module.Target().Arch.ArchType.Multilib
|
||||
|
@ -714,7 +720,7 @@ func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeM
|
|||
// this module. This is required since arch variant of an APEX bundle is 'common' but it is
|
||||
// 'arm' or 'arm64' for native shared libs.
|
||||
ctx.AddFarVariationDependencies(binVariations, executableTag,
|
||||
android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
|
||||
android.RemoveListFromList(nativeModules.ResolvedBinaries, nativeModules.Exclude_binaries)...)
|
||||
ctx.AddFarVariationDependencies(binVariations, testTag,
|
||||
android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
|
||||
ctx.AddFarVariationDependencies(libVariations, jniLibTag,
|
||||
|
@ -726,7 +732,7 @@ func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeM
|
|||
ctx.AddFarVariationDependencies(target.Variations(), fsTag,
|
||||
android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
|
||||
ctx.AddFarVariationDependencies(target.Variations(), prebuiltTag,
|
||||
android.RemoveListFromList(nativeModules.Prebuilts, nativeModules.Exclude_prebuilts)...)
|
||||
android.RemoveListFromList(nativeModules.ResolvedPrebuilts, nativeModules.Exclude_prebuilts)...)
|
||||
}
|
||||
|
||||
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
|
||||
|
@ -781,20 +787,19 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|||
|
||||
// Add native modules targeting both ABIs. When multilib.* is omitted for
|
||||
// native_shared_libs/jni_libs/tests, it implies multilib.both
|
||||
deps.Merge(a.properties.Multilib.Both)
|
||||
deps.Merge(ApexNativeDependencies{
|
||||
deps.Merge(ctx, a.properties.Multilib.Both)
|
||||
deps.Merge(ctx, ApexNativeDependencies{
|
||||
Native_shared_libs: a.properties.Native_shared_libs,
|
||||
Tests: a.properties.Tests,
|
||||
Jni_libs: a.properties.Jni_libs,
|
||||
Binaries: nil,
|
||||
})
|
||||
|
||||
// Add native modules targeting the first ABI When multilib.* is omitted for
|
||||
// binaries, it implies multilib.first
|
||||
isPrimaryAbi := i == 0
|
||||
if isPrimaryAbi {
|
||||
deps.Merge(a.properties.Multilib.First)
|
||||
deps.Merge(ApexNativeDependencies{
|
||||
deps.Merge(ctx, a.properties.Multilib.First)
|
||||
deps.Merge(ctx, ApexNativeDependencies{
|
||||
Native_shared_libs: nil,
|
||||
Tests: nil,
|
||||
Jni_libs: nil,
|
||||
|
@ -805,27 +810,27 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|||
// Add native modules targeting either 32-bit or 64-bit ABI
|
||||
switch target.Arch.ArchType.Multilib {
|
||||
case "lib32":
|
||||
deps.Merge(a.properties.Multilib.Lib32)
|
||||
deps.Merge(a.properties.Multilib.Prefer32)
|
||||
deps.Merge(ctx, a.properties.Multilib.Lib32)
|
||||
deps.Merge(ctx, a.properties.Multilib.Prefer32)
|
||||
case "lib64":
|
||||
deps.Merge(a.properties.Multilib.Lib64)
|
||||
deps.Merge(ctx, a.properties.Multilib.Lib64)
|
||||
if !has32BitTarget {
|
||||
deps.Merge(a.properties.Multilib.Prefer32)
|
||||
deps.Merge(ctx, a.properties.Multilib.Prefer32)
|
||||
}
|
||||
}
|
||||
|
||||
// Add native modules targeting a specific arch variant
|
||||
switch target.Arch.ArchType {
|
||||
case android.Arm:
|
||||
deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies)
|
||||
deps.Merge(ctx, a.archProperties.Arch.Arm.ApexNativeDependencies)
|
||||
case android.Arm64:
|
||||
deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies)
|
||||
deps.Merge(ctx, a.archProperties.Arch.Arm64.ApexNativeDependencies)
|
||||
case android.Riscv64:
|
||||
deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies)
|
||||
deps.Merge(ctx, a.archProperties.Arch.Riscv64.ApexNativeDependencies)
|
||||
case android.X86:
|
||||
deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies)
|
||||
deps.Merge(ctx, a.archProperties.Arch.X86.ApexNativeDependencies)
|
||||
case android.X86_64:
|
||||
deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies)
|
||||
deps.Merge(ctx, a.archProperties.Arch.X86_64.ApexNativeDependencies)
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType))
|
||||
}
|
||||
|
@ -839,11 +844,13 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|||
}
|
||||
}
|
||||
|
||||
a.properties.ResolvedSystemserverclasspathFragments = a.properties.Systemserverclasspath_fragments.GetOrDefault(ctx, nil)
|
||||
|
||||
// Common-arch dependencies come next
|
||||
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
|
||||
ctx.AddFarVariationDependencies(commonVariation, rroTag, a.properties.Rros...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.ResolvedSystemserverclasspathFragments...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
|
||||
|
@ -856,9 +863,9 @@ func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato
|
|||
}
|
||||
|
||||
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
|
||||
ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps.GetOrDefault(ctx, nil)...)
|
||||
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
|
||||
if prebuilts := a.overridableProperties.Prebuilts; len(prebuilts) > 0 {
|
||||
if prebuilts := a.overridableProperties.Prebuilts.GetOrDefault(ctx, nil); len(prebuilts) > 0 {
|
||||
// For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
|
||||
// regardless of the TARGET_PREFER_* setting. See b/144532908
|
||||
arches := ctx.DeviceConfig().Arches()
|
||||
|
@ -1530,7 +1537,6 @@ func (a *apexBundle) AddSanitizerDependencies(ctx android.BottomUpMutatorContext
|
|||
Native_shared_libs: []string{"libclang_rt.hwasan"},
|
||||
Tests: nil,
|
||||
Jni_libs: nil,
|
||||
Binaries: nil,
|
||||
}, target, imageVariation)
|
||||
break
|
||||
}
|
||||
|
@ -2426,6 +2432,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
a.provideApexExportsInfo(ctx)
|
||||
|
||||
a.providePrebuiltInfo(ctx)
|
||||
|
||||
a.required = a.RequiredModuleNames(ctx)
|
||||
}
|
||||
|
||||
// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file
|
||||
|
@ -2851,7 +2859,7 @@ func isStaticExecutableAllowed(apex string, exec string) bool {
|
|||
func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) {
|
||||
dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...)
|
||||
dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments...)
|
||||
dpInfo.Deps = append(dpInfo.Deps, a.properties.Systemserverclasspath_fragments...)
|
||||
dpInfo.Deps = append(dpInfo.Deps, a.properties.ResolvedSystemserverclasspathFragments...)
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -704,8 +704,9 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) {
|
|||
optFlags = append(optFlags, "--override_apk_package_name "+manifestPackageName)
|
||||
}
|
||||
|
||||
if a.properties.AndroidManifest != nil {
|
||||
androidManifestFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.AndroidManifest))
|
||||
androidManifest := a.properties.AndroidManifest.GetOrDefault(ctx, "")
|
||||
if androidManifest != "" {
|
||||
androidManifestFile := android.PathForModuleSrc(ctx, androidManifest)
|
||||
|
||||
if a.testApex {
|
||||
androidManifestFile = markManifestTestOnly(ctx, androidManifestFile)
|
||||
|
@ -1195,8 +1196,9 @@ func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext, defaultReadO
|
|||
}
|
||||
// Custom fs_config is "appended" to the last so that entries from the file are preferred
|
||||
// over default ones set above.
|
||||
if a.properties.Canned_fs_config != nil {
|
||||
cmd.Text("cat").Input(android.PathForModuleSrc(ctx, *a.properties.Canned_fs_config))
|
||||
customFsConfig := a.properties.Canned_fs_config.GetOrDefault(ctx, "")
|
||||
if customFsConfig != "" {
|
||||
cmd.Text("cat").Input(android.PathForModuleSrc(ctx, customFsConfig))
|
||||
}
|
||||
cmd.Text(")").FlagWithOutput("> ", cannedFsConfig)
|
||||
builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName()))
|
||||
|
|
|
@ -286,7 +286,7 @@ func (f *Fixer) reparse() ([]byte, error) {
|
|||
}
|
||||
|
||||
func parse(name string, r io.Reader) (*parser.File, error) {
|
||||
tree, errs := parser.Parse(name, r, parser.NewScope(nil))
|
||||
tree, errs := parser.Parse(name, r)
|
||||
if errs != nil {
|
||||
s := "parse error: "
|
||||
for _, err := range errs {
|
||||
|
|
|
@ -46,7 +46,7 @@ func buildTree(local_include_dirs []string, export_include_dirs []string) (file
|
|||
}
|
||||
`,
|
||||
printListOfStrings(local_include_dirs), printListOfStrings(export_include_dirs))
|
||||
tree, errs := parser.Parse("", strings.NewReader(input), parser.NewScope(nil))
|
||||
tree, errs := parser.Parse("", strings.NewReader(input))
|
||||
if len(errs) > 0 {
|
||||
errs = append([]error{fmt.Errorf("failed to parse:\n%s", input)}, errs...)
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ func preProcessIn(in string) (fixer *Fixer, err error) {
|
|||
return fixer, err
|
||||
}
|
||||
|
||||
tree, errs := parser.Parse("<testcase>", bytes.NewBufferString(in), parser.NewScope(nil))
|
||||
tree, errs := parser.Parse("<testcase>", bytes.NewBufferString(in))
|
||||
if errs != nil {
|
||||
return fixer, err
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ func processFile(filename string, in io.Reader, out io.Writer, fixRequest bpfix.
|
|||
return err
|
||||
}
|
||||
r := bytes.NewBuffer(append([]byte(nil), src...))
|
||||
file, errs := parser.Parse(filename, r, parser.NewScope(nil))
|
||||
file, errs := parser.Parse(filename, r)
|
||||
if len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
|
|
21
cc/cc.go
21
cc/cc.go
|
@ -981,8 +981,8 @@ func (c *Module) HiddenFromMake() bool {
|
|||
return c.Properties.HideFromMake
|
||||
}
|
||||
|
||||
func (c *Module) RequiredModuleNames() []string {
|
||||
required := android.CopyOf(c.ModuleBase.RequiredModuleNames())
|
||||
func (c *Module) RequiredModuleNames(ctx android.ConfigAndErrorContext) []string {
|
||||
required := android.CopyOf(c.ModuleBase.RequiredModuleNames(ctx))
|
||||
if c.ImageVariation().Variation == android.CoreVariation {
|
||||
required = append(required, c.Properties.Target.Platform.Required...)
|
||||
required = removeListFromList(required, c.Properties.Target.Platform.Exclude_required)
|
||||
|
@ -2468,6 +2468,23 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
variantNdkLibs := []string{}
|
||||
variantLateNdkLibs := []string{}
|
||||
if ctx.Os() == android.Android {
|
||||
rewriteHeaderLibs := func(list []string) (newHeaderLibs []string) {
|
||||
newHeaderLibs = []string{}
|
||||
for _, entry := range list {
|
||||
// Replace device_kernel_headers with generated_kernel_headers
|
||||
// for inline kernel building
|
||||
if entry == "device_kernel_headers" || entry == "qti_kernel_headers" {
|
||||
if (ctx.Config().Getenv("INLINE_KERNEL_BUILDING") == "true") {
|
||||
newHeaderLibs = append(newHeaderLibs, "generated_kernel_headers")
|
||||
continue
|
||||
}
|
||||
}
|
||||
newHeaderLibs = append(newHeaderLibs, entry)
|
||||
}
|
||||
return newHeaderLibs
|
||||
}
|
||||
deps.HeaderLibs = rewriteHeaderLibs(deps.HeaderLibs)
|
||||
|
||||
deps.SharedLibs, variantNdkLibs = FilterNdkLibs(c, ctx.Config(), deps.SharedLibs)
|
||||
deps.LateSharedLibs, variantLateNdkLibs = FilterNdkLibs(c, ctx.Config(), deps.LateSharedLibs)
|
||||
deps.ReexportSharedLibHeaders, _ = FilterNdkLibs(c, ctx.Config(), deps.ReexportSharedLibHeaders)
|
||||
|
|
|
@ -53,7 +53,7 @@ type BaseCompilerProperties struct {
|
|||
Cflags proptools.Configurable[[]string] `android:"arch_variant"`
|
||||
|
||||
// list of module-specific flags that will be used for C++ compiles
|
||||
Cppflags []string `android:"arch_variant"`
|
||||
Cppflags proptools.Configurable[[]string] `android:"arch_variant"`
|
||||
|
||||
// list of module-specific flags that will be used for C compiles
|
||||
Conlyflags []string `android:"arch_variant"`
|
||||
|
@ -363,12 +363,23 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps
|
|||
tc := ctx.toolchain()
|
||||
modulePath := ctx.ModuleDir()
|
||||
|
||||
additionalIncludeDirs := ctx.DeviceConfig().TargetSpecificHeaderPath()
|
||||
if len(additionalIncludeDirs) > 0 {
|
||||
// devices can have multiple paths in TARGET_SPECIFIC_HEADER_PATH
|
||||
// add -I in front of all of them
|
||||
if (strings.Contains(additionalIncludeDirs, " ")) {
|
||||
additionalIncludeDirs = strings.ReplaceAll(additionalIncludeDirs, " ", " -I")
|
||||
}
|
||||
flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I" + additionalIncludeDirs)
|
||||
}
|
||||
|
||||
compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
|
||||
compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...)
|
||||
|
||||
cflags := compiler.Properties.Cflags.GetOrDefault(ctx, nil)
|
||||
cppflags := compiler.Properties.Cppflags.GetOrDefault(ctx, nil)
|
||||
CheckBadCompilerFlags(ctx, "cflags", cflags)
|
||||
CheckBadCompilerFlags(ctx, "cppflags", compiler.Properties.Cppflags)
|
||||
CheckBadCompilerFlags(ctx, "cppflags", cppflags)
|
||||
CheckBadCompilerFlags(ctx, "conlyflags", compiler.Properties.Conlyflags)
|
||||
CheckBadCompilerFlags(ctx, "asflags", compiler.Properties.Asflags)
|
||||
CheckBadCompilerFlags(ctx, "vendor.cflags", compiler.Properties.Target.Vendor.Cflags)
|
||||
|
@ -381,7 +392,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps
|
|||
esc := proptools.NinjaAndShellEscapeList
|
||||
|
||||
flags.Local.CFlags = append(flags.Local.CFlags, esc(cflags)...)
|
||||
flags.Local.CppFlags = append(flags.Local.CppFlags, esc(compiler.Properties.Cppflags)...)
|
||||
flags.Local.CppFlags = append(flags.Local.CppFlags, esc(cppflags)...)
|
||||
flags.Local.ConlyFlags = append(flags.Local.ConlyFlags, esc(compiler.Properties.Conlyflags)...)
|
||||
flags.Local.AsFlags = append(flags.Local.AsFlags, esc(compiler.Properties.Asflags)...)
|
||||
flags.Local.YasmFlags = append(flags.Local.YasmFlags, esc(compiler.Properties.Asflags)...)
|
||||
|
@ -813,7 +824,7 @@ type RustBindgenClangProperties struct {
|
|||
|
||||
// list of c++ specific clang flags required to correctly interpret the headers.
|
||||
// This is provided primarily to make sure cppflags defined in cc_defaults are pulled in.
|
||||
Cppflags []string `android:"arch_variant"`
|
||||
Cppflags proptools.Configurable[[]string] `android:"arch_variant"`
|
||||
|
||||
// C standard version to use. Can be a specific version (such as "gnu11"),
|
||||
// "experimental" (which will use draft versions like C1x when available),
|
||||
|
|
|
@ -196,6 +196,9 @@ type FlagExporterProperties struct {
|
|||
// using -isystem for this module and any module that links against this module.
|
||||
Export_system_include_dirs []string `android:"arch_variant,variant_prepend"`
|
||||
|
||||
// list of plain cc flags to be used for any module that links against this module.
|
||||
Export_cflags []string `android:"arch_variant"`
|
||||
|
||||
Target struct {
|
||||
Vendor, Product struct {
|
||||
// list of exported include directories, like
|
||||
|
@ -306,6 +309,10 @@ func (f *flagExporter) exportIncludes(ctx ModuleContext) {
|
|||
f.systemDirs = append(f.systemDirs, android.PathsForModuleSrc(ctx, f.Properties.Export_system_include_dirs)...)
|
||||
}
|
||||
|
||||
func (f *flagExporter) exportExtraFlags(ctx ModuleContext) {
|
||||
f.flags = append(f.flags, f.Properties.Export_cflags...)
|
||||
}
|
||||
|
||||
// exportIncludesAsSystem registers the include directories and system include directories to be
|
||||
// exported transitively both as system include directories to modules depending on this module.
|
||||
func (f *flagExporter) exportIncludesAsSystem(ctx ModuleContext) {
|
||||
|
@ -1630,6 +1637,7 @@ func (library *libraryDecorator) link(ctx ModuleContext,
|
|||
|
||||
// Export include paths and flags to be propagated up the tree.
|
||||
library.exportIncludes(ctx)
|
||||
library.exportExtraFlags(ctx)
|
||||
library.reexportDirs(deps.ReexportedDirs...)
|
||||
library.reexportSystemDirs(deps.ReexportedSystemDirs...)
|
||||
library.reexportFlags(deps.ReexportedFlags...)
|
||||
|
|
|
@ -59,7 +59,7 @@ type vbmetaProperties struct {
|
|||
|
||||
// List of filesystem modules that this vbmeta has descriptors for. The filesystem modules
|
||||
// have to be signed (use_avb: true).
|
||||
Partitions []string
|
||||
Partitions proptools.Configurable[[]string]
|
||||
|
||||
// List of chained partitions that this vbmeta deletages the verification.
|
||||
Chained_partitions []chainedPartitionProperties
|
||||
|
@ -110,7 +110,7 @@ type vbmetaDep struct {
|
|||
var vbmetaPartitionDep = vbmetaDep{kind: "partition"}
|
||||
|
||||
func (v *vbmeta) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
ctx.AddDependency(ctx.Module(), vbmetaPartitionDep, v.properties.Partitions...)
|
||||
ctx.AddDependency(ctx.Module(), vbmetaPartitionDep, v.properties.Partitions.GetOrDefault(ctx, nil)...)
|
||||
}
|
||||
|
||||
func (v *vbmeta) installFileName() string {
|
||||
|
|
|
@ -139,7 +139,8 @@ type generatorProperties struct {
|
|||
Export_include_dirs []string
|
||||
|
||||
// list of input files
|
||||
Srcs []string `android:"path,arch_variant"`
|
||||
Srcs proptools.Configurable[[]string] `android:"path,arch_variant"`
|
||||
ResolvedSrcs []string `blueprint:"mutated"`
|
||||
|
||||
// input files to exclude
|
||||
Exclude_srcs []string `android:"path,arch_variant"`
|
||||
|
@ -396,7 +397,8 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
|
|||
}
|
||||
return srcFiles
|
||||
}
|
||||
srcFiles := addLabelsForInputs("srcs", g.properties.Srcs, g.properties.Exclude_srcs)
|
||||
g.properties.ResolvedSrcs = g.properties.Srcs.GetOrDefault(ctx, nil)
|
||||
srcFiles := addLabelsForInputs("srcs", g.properties.ResolvedSrcs, g.properties.Exclude_srcs)
|
||||
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
|
||||
|
||||
var copyFrom android.Paths
|
||||
|
@ -590,7 +592,7 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
// Collect information for opening IDE project files in java/jdeps.go.
|
||||
func (g *Module) IDEInfo(dpInfo *android.IdeInfo) {
|
||||
dpInfo.Srcs = append(dpInfo.Srcs, g.Srcs().Strings()...)
|
||||
for _, src := range g.properties.Srcs {
|
||||
for _, src := range g.properties.ResolvedSrcs {
|
||||
if strings.HasPrefix(src, ":") {
|
||||
src = strings.Trim(src, ":")
|
||||
dpInfo.Deps = append(dpInfo.Deps, src)
|
||||
|
|
|
@ -694,7 +694,7 @@ func TestGenruleDefaults(t *testing.T) {
|
|||
android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
|
||||
|
||||
expectedSrcs := []string{"in1"}
|
||||
android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.Srcs)
|
||||
android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.ResolvedSrcs)
|
||||
}
|
||||
|
||||
func TestGenruleAllowMissingDependencies(t *testing.T) {
|
||||
|
|
|
@ -1501,7 +1501,7 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
InstalledFiles: j.data,
|
||||
OutputFile: j.outputFile,
|
||||
TestConfig: j.testConfig,
|
||||
RequiredModuleNames: j.RequiredModuleNames(),
|
||||
RequiredModuleNames: j.RequiredModuleNames(ctx),
|
||||
TestSuites: j.testProperties.Test_suites,
|
||||
IsHost: true,
|
||||
LocalSdkVersion: j.sdkVersion.String(),
|
||||
|
|
|
@ -20,6 +20,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -49,7 +51,7 @@ func PhonyFactory() android.Module {
|
|||
}
|
||||
|
||||
func (p *phony) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
p.requiredModuleNames = ctx.RequiredModuleNames()
|
||||
p.requiredModuleNames = ctx.RequiredModuleNames(ctx)
|
||||
p.hostRequiredModuleNames = ctx.HostRequiredModuleNames()
|
||||
p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames()
|
||||
}
|
||||
|
@ -88,14 +90,15 @@ type PhonyRule struct {
|
|||
android.ModuleBase
|
||||
android.DefaultableModuleBase
|
||||
|
||||
properties PhonyProperties
|
||||
phonyDepsModuleNames []string
|
||||
properties PhonyProperties
|
||||
}
|
||||
|
||||
type PhonyProperties struct {
|
||||
// The Phony_deps is the set of all dependencies for this target,
|
||||
// and it can function similarly to .PHONY in a makefile.
|
||||
// Additionally, dependencies within it can even include genrule.
|
||||
Phony_deps []string
|
||||
Phony_deps proptools.Configurable[[]string]
|
||||
}
|
||||
|
||||
// The phony_rule provides functionality similar to the .PHONY in a makefile.
|
||||
|
@ -109,13 +112,14 @@ func PhonyRuleFactory() android.Module {
|
|||
}
|
||||
|
||||
func (p *PhonyRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
p.phonyDepsModuleNames = p.properties.Phony_deps.GetOrDefault(ctx, nil)
|
||||
}
|
||||
|
||||
func (p *PhonyRule) AndroidMk() android.AndroidMkData {
|
||||
return android.AndroidMkData{
|
||||
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
|
||||
if len(p.properties.Phony_deps) > 0 {
|
||||
depModulesStr := strings.Join(p.properties.Phony_deps, " ")
|
||||
if len(p.phonyDepsModuleNames) > 0 {
|
||||
depModulesStr := strings.Join(p.phonyDepsModuleNames, " ")
|
||||
fmt.Fprintln(w, ".PHONY:", name)
|
||||
fmt.Fprintln(w, name, ":", depModulesStr)
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
|
|||
if isCpp {
|
||||
cflags = append(cflags, "-x c++")
|
||||
// Add any C++ only flags.
|
||||
cflags = append(cflags, esc(b.ClangProperties.Cppflags)...)
|
||||
cflags = append(cflags, esc(b.ClangProperties.Cppflags.GetOrDefault(ctx, nil))...)
|
||||
} else {
|
||||
cflags = append(cflags, "-x c")
|
||||
}
|
||||
|
|
|
@ -292,9 +292,17 @@ python_binary_host {
|
|||
}
|
||||
|
||||
python_binary_host {
|
||||
name: "buildinfo",
|
||||
main: "buildinfo.py",
|
||||
srcs: ["buildinfo.py"],
|
||||
name: "merge_json",
|
||||
main: "merge_json.py",
|
||||
srcs: [
|
||||
"merge_json.py",
|
||||
],
|
||||
}
|
||||
|
||||
python_binary_host {
|
||||
name: "gen_build_prop",
|
||||
main: "gen_build_prop.py",
|
||||
srcs: ["gen_build_prop.py"],
|
||||
}
|
||||
|
||||
python_binary_host {
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2024 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
"""A tool for generating buildinfo.prop"""
|
||||
|
||||
import argparse
|
||||
import contextlib
|
||||
import subprocess
|
||||
|
||||
def parse_args():
|
||||
"""Parse commandline arguments."""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--use-vbmeta-digest-in-fingerprint', action='store_true')
|
||||
parser.add_argument('--build-flavor', required=True)
|
||||
parser.add_argument('--build-hostname-file', required=True, type=argparse.FileType('r')),
|
||||
parser.add_argument('--build-id', required=True)
|
||||
parser.add_argument('--build-keys', required=True)
|
||||
parser.add_argument('--build-number-file', required=True, type=argparse.FileType('r'))
|
||||
parser.add_argument('--build-thumbprint-file', type=argparse.FileType('r'))
|
||||
parser.add_argument('--build-type', required=True)
|
||||
parser.add_argument('--build-username', required=True)
|
||||
parser.add_argument('--build-variant', required=True)
|
||||
parser.add_argument('--cpu-abis', action='append', required=True)
|
||||
parser.add_argument('--date-file', required=True, type=argparse.FileType('r'))
|
||||
parser.add_argument('--default-locale')
|
||||
parser.add_argument('--default-wifi-channels', action='append', default=[])
|
||||
parser.add_argument('--device', required=True)
|
||||
parser.add_argument("--display-build-number", action='store_true')
|
||||
parser.add_argument('--platform-base-os', required=True)
|
||||
parser.add_argument('--platform-display-version', required=True)
|
||||
parser.add_argument('--platform-min-supported-target-sdk-version', required=True)
|
||||
parser.add_argument('--platform-preview-sdk-fingerprint-file',
|
||||
required=True,
|
||||
type=argparse.FileType('r'))
|
||||
parser.add_argument('--platform-preview-sdk-version', required=True)
|
||||
parser.add_argument('--platform-sdk-version', required=True)
|
||||
parser.add_argument('--platform-security-patch', required=True)
|
||||
parser.add_argument('--platform-version', required=True)
|
||||
parser.add_argument('--platform-version-codename',required=True)
|
||||
parser.add_argument('--platform-version-all-codenames', action='append', required=True)
|
||||
parser.add_argument('--platform-version-known-codenames', required=True)
|
||||
parser.add_argument('--platform-version-last-stable', required=True)
|
||||
parser.add_argument('--product', required=True)
|
||||
|
||||
parser.add_argument('--out', required=True, type=argparse.FileType('w'))
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
option = parse_args()
|
||||
|
||||
build_hostname = option.build_hostname_file.read().strip()
|
||||
build_number = option.build_number_file.read().strip()
|
||||
build_version_tags = option.build_keys
|
||||
if option.build_type == "debug":
|
||||
build_version_tags = "debug," + build_version_tags
|
||||
|
||||
raw_date = option.date_file.read().strip()
|
||||
date = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip()
|
||||
date_utc = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip()
|
||||
|
||||
# build_desc is human readable strings that describe this build. This has the same info as the
|
||||
# build fingerprint.
|
||||
# e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys"
|
||||
build_desc = f"{option.product}-{option.build_variant} {option.platform_version} " \
|
||||
f"{option.build_id} {build_number} {build_version_tags}"
|
||||
|
||||
platform_preview_sdk_fingerprint = option.platform_preview_sdk_fingerprint_file.read().strip()
|
||||
|
||||
with contextlib.redirect_stdout(option.out):
|
||||
print("# begin build properties")
|
||||
print("# autogenerated by buildinfo.py")
|
||||
|
||||
# The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest.
|
||||
if option.use_vbmeta_digest_in_fingerprint:
|
||||
print(f"ro.build.legacy.id={option.build_id}")
|
||||
else:
|
||||
print(f"ro.build.id?={option.build_id}")
|
||||
|
||||
# ro.build.display.id is shown under Settings -> About Phone
|
||||
if option.build_variant == "user":
|
||||
# User builds should show:
|
||||
# release build number or branch.buld_number non-release builds
|
||||
|
||||
# Dev. branches should have DISPLAY_BUILD_NUMBER set
|
||||
if option.display_build_number:
|
||||
print(f"ro.build.display.id?={option.build_id}.{build_number} {option.build_keys}")
|
||||
else:
|
||||
print(f"ro.build.display.id?={option.build_id} {option.build_keys}")
|
||||
else:
|
||||
# Non-user builds should show detailed build information (See build desc above)
|
||||
print(f"ro.build.display.id?={build_desc}")
|
||||
print(f"ro.build.version.incremental={build_number}")
|
||||
print(f"ro.build.version.sdk={option.platform_sdk_version}")
|
||||
print(f"ro.build.version.preview_sdk={option.platform_preview_sdk_version}")
|
||||
print(f"ro.build.version.preview_sdk_fingerprint={platform_preview_sdk_fingerprint}")
|
||||
print(f"ro.build.version.codename={option.platform_version_codename}")
|
||||
print(f"ro.build.version.all_codenames={','.join(option.platform_version_all_codenames)}")
|
||||
print(f"ro.build.version.known_codenames={option.platform_version_known_codenames}")
|
||||
print(f"ro.build.version.release={option.platform_version_last_stable}")
|
||||
print(f"ro.build.version.release_or_codename={option.platform_version}")
|
||||
print(f"ro.build.version.release_or_preview_display={option.platform_display_version}")
|
||||
print(f"ro.build.version.security_patch={option.platform_security_patch}")
|
||||
print(f"ro.build.version.base_os={option.platform_base_os}")
|
||||
print(f"ro.build.version.min_supported_target_sdk={option.platform_min_supported_target_sdk_version}")
|
||||
print(f"ro.build.date={date}")
|
||||
print(f"ro.build.date.utc={date_utc}")
|
||||
print(f"ro.build.type={option.build_variant}")
|
||||
print(f"ro.build.user={option.build_username}")
|
||||
print(f"ro.build.host={build_hostname}")
|
||||
# TODO: Remove any tag-related optional property declarations once the goals
|
||||
# from go/arc-android-sigprop-changes have been achieved.
|
||||
print(f"ro.build.tags?={build_version_tags}")
|
||||
# ro.build.flavor are used only by the test harness to distinguish builds.
|
||||
# Only add _asan for a sanitized build if it isn't already a part of the
|
||||
# flavor (via a dedicated lunch config for example).
|
||||
print(f"ro.build.flavor={option.build_flavor}")
|
||||
|
||||
# These values are deprecated, use "ro.product.cpu.abilist"
|
||||
# instead (see below).
|
||||
print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
|
||||
print(f"# use ro.product.cpu.abilist instead.")
|
||||
print(f"ro.product.cpu.abi={option.cpu_abis[0]}")
|
||||
if len(option.cpu_abis) > 1:
|
||||
print(f"ro.product.cpu.abi2={option.cpu_abis[1]}")
|
||||
|
||||
if option.default_locale:
|
||||
print(f"ro.product.locale={option.default_locale}")
|
||||
print(f"ro.wifi.channels={' '.join(option.default_wifi_channels)}")
|
||||
|
||||
print(f"# ro.build.product is obsolete; use ro.product.device")
|
||||
print(f"ro.build.product={option.device}")
|
||||
|
||||
print(f"# Do not try to parse description or thumbprint")
|
||||
print(f"ro.build.description?={build_desc}")
|
||||
if option.build_thumbprint_file:
|
||||
build_thumbprint = option.build_thumbprint_file.read().strip()
|
||||
print(f"ro.build.thumbprint={build_thumbprint}")
|
||||
|
||||
print(f"# end build properties")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -258,3 +258,19 @@ com\.google\.i18n\.phonenumbers
|
|||
# Packages used for Android in Chrome OS
|
||||
org\.chromium\.arc
|
||||
org\.chromium\.arc\..*
|
||||
|
||||
# OPLUS adds
|
||||
com\.oplus\..*
|
||||
|
||||
# QC adds
|
||||
com.qualcomm.qti
|
||||
com.quicinc.tcmiface
|
||||
com.qualcomm.wfd
|
||||
com.qualcomm.wfd.service
|
||||
org.codeaurora.ims
|
||||
org.codeaurora.internal
|
||||
qcom.fmradio
|
||||
|
||||
###################################################
|
||||
# IFAA Manager used for Alipay and/or WeChat payment
|
||||
org\.ifaa\.android\.manager.*
|
||||
|
|
645
scripts/gen_build_prop.py
Normal file
645
scripts/gen_build_prop.py
Normal file
|
@ -0,0 +1,645 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2024 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
"""A tool for generating {partition}/build.prop"""
|
||||
|
||||
import argparse
|
||||
import contextlib
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
TEST_KEY_DIR = "build/make/target/product/security"
|
||||
|
||||
def get_build_variant(product_config):
|
||||
if product_config["Eng"]:
|
||||
return "eng"
|
||||
elif product_config["Debuggable"]:
|
||||
return "userdebug"
|
||||
else:
|
||||
return "user"
|
||||
|
||||
def get_build_flavor(product_config):
|
||||
build_flavor = product_config["DeviceProduct"] + "-" + get_build_variant(product_config)
|
||||
if "address" in product_config.get("SanitizeDevice", []) and "_asan" not in build_flavor:
|
||||
build_flavor += "_asan"
|
||||
return build_flavor
|
||||
|
||||
def get_build_keys(product_config):
|
||||
default_cert = product_config.get("DefaultAppCertificate", "")
|
||||
if default_cert == "" or default_cert == os.path.join(TEST_KEY_DIR, "testKey"):
|
||||
return "test-keys"
|
||||
return "dev-keys"
|
||||
|
||||
def override_config(config):
|
||||
if "PRODUCT_BUILD_PROP_OVERRIDES" in config:
|
||||
current_key = None
|
||||
props_overrides = {}
|
||||
|
||||
for var in config["PRODUCT_BUILD_PROP_OVERRIDES"]:
|
||||
if "=" in var:
|
||||
current_key, value = var.split("=")
|
||||
props_overrides[current_key] = value
|
||||
else:
|
||||
props_overrides[current_key] += f" {var}"
|
||||
|
||||
for key, value in props_overrides.items():
|
||||
if key not in config:
|
||||
print(f"Key \"{key}\" isn't a valid prop override", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
config[key] = value
|
||||
|
||||
def parse_args():
|
||||
"""Parse commandline arguments."""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--build-fingerprint-file", required=True, type=argparse.FileType("r"))
|
||||
parser.add_argument("--build-hostname-file", required=True, type=argparse.FileType("r"))
|
||||
parser.add_argument("--build-number-file", required=True, type=argparse.FileType("r"))
|
||||
parser.add_argument("--build-thumbprint-file", type=argparse.FileType("r"))
|
||||
parser.add_argument("--build-username", required=True)
|
||||
parser.add_argument("--date-file", required=True, type=argparse.FileType("r"))
|
||||
parser.add_argument("--platform-preview-sdk-fingerprint-file", required=True, type=argparse.FileType("r"))
|
||||
parser.add_argument("--prop-files", action="append", type=argparse.FileType("r"), default=[])
|
||||
parser.add_argument("--product-config", required=True, type=argparse.FileType("r"))
|
||||
parser.add_argument("--partition", required=True)
|
||||
parser.add_argument("--build-broken-dup-sysprop", action="store_true", default=False)
|
||||
|
||||
parser.add_argument("--out", required=True, type=argparse.FileType("w"))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# post process parse_args requiring manual handling
|
||||
args.config = json.load(args.product_config)
|
||||
config = args.config
|
||||
|
||||
config["BuildFlavor"] = get_build_flavor(config)
|
||||
config["BuildKeys"] = get_build_keys(config)
|
||||
config["BuildVariant"] = get_build_variant(config)
|
||||
|
||||
config["BuildFingerprint"] = args.build_fingerprint_file.read().strip()
|
||||
config["BuildHostname"] = args.build_hostname_file.read().strip()
|
||||
config["BuildNumber"] = args.build_number_file.read().strip()
|
||||
config["BuildUsername"] = args.build_username
|
||||
|
||||
build_version_tags_list = config["BuildVersionTags"]
|
||||
if config["BuildType"] == "debug":
|
||||
build_version_tags_list.append("debug")
|
||||
build_version_tags_list.append(config["BuildKeys"])
|
||||
build_version_tags = ",".join(sorted(set(build_version_tags_list)))
|
||||
config["BuildVersionTags"] = build_version_tags
|
||||
|
||||
raw_date = args.date_file.read().strip()
|
||||
config["Date"] = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip()
|
||||
config["DateUtc"] = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip()
|
||||
|
||||
# build_desc is human readable strings that describe this build. This has the same info as the
|
||||
# build fingerprint.
|
||||
# e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys"
|
||||
config["BuildDesc"] = f"{config['DeviceProduct']}-{config['BuildVariant']} " \
|
||||
f"{config['Platform_version_name']} {config['BuildId']} " \
|
||||
f"{config['BuildNumber']} {config['BuildVersionTags']}"
|
||||
|
||||
config["PlatformPreviewSdkFingerprint"] = args.platform_preview_sdk_fingerprint_file.read().strip()
|
||||
|
||||
if args.build_thumbprint_file:
|
||||
config["BuildThumbprint"] = args.build_thumbprint_file.read().strip()
|
||||
|
||||
config["tequilaDesc"] = config["BuildDesc"]
|
||||
config["tequilaDevice"] = config["DeviceName"]
|
||||
|
||||
override_config(config)
|
||||
|
||||
append_additional_system_props(args)
|
||||
append_additional_vendor_props(args)
|
||||
append_additional_product_props(args)
|
||||
|
||||
return args
|
||||
|
||||
def generate_common_build_props(args):
|
||||
print("####################################")
|
||||
print("# from generate_common_build_props")
|
||||
print("# These properties identify this partition image.")
|
||||
print("####################################")
|
||||
|
||||
config = args.config
|
||||
partition = args.partition
|
||||
|
||||
if partition == "system":
|
||||
print(f"ro.product.{partition}.brand={config['SystemBrand']}")
|
||||
print(f"ro.product.{partition}.device={config['SystemDevice']}")
|
||||
print(f"ro.product.{partition}.manufacturer={config['SystemManufacturer']}")
|
||||
print(f"ro.product.{partition}.model={config['SystemModel']}")
|
||||
print(f"ro.product.{partition}.name={config['SystemName']}")
|
||||
else:
|
||||
print(f"ro.product.{partition}.brand={config['ProductBrand']}")
|
||||
print(f"ro.product.{partition}.device={config['DeviceName']}")
|
||||
print(f"ro.product.{partition}.manufacturer={config['ProductManufacturer']}")
|
||||
print(f"ro.product.{partition}.model={config['ProductModel']}")
|
||||
print(f"ro.product.{partition}.name={config['DeviceProduct']}")
|
||||
|
||||
if partition != "system":
|
||||
if config["ProductModelForAttestation"]:
|
||||
print(f"ro.product.model_for_attestation={config['ProductModelForAttestation']}")
|
||||
if config["ProductBrandForAttestation"]:
|
||||
print(f"ro.product.brand_for_attestation={config['ProductBrandForAttestation']}")
|
||||
if config["ProductNameForAttestation"]:
|
||||
print(f"ro.product.name_for_attestation={config['ProductNameForAttestation']}")
|
||||
if config["ProductDeviceForAttestation"]:
|
||||
print(f"ro.product.device_for_attestation={config['ProductDeviceForAttestation']}")
|
||||
if config["ProductManufacturerForAttestation"]:
|
||||
print(f"ro.product.manufacturer_for_attestation={config['ProductManufacturerForAttestation']}")
|
||||
|
||||
if config["ZygoteForce64"]:
|
||||
if partition == "vendor":
|
||||
print(f"ro.{partition}.product.cpu.abilist={config['DeviceAbiList64']}")
|
||||
print(f"ro.{partition}.product.cpu.abilist32=")
|
||||
print(f"ro.{partition}.product.cpu.abilist64={config['DeviceAbiList64']}")
|
||||
else:
|
||||
if partition == "system" or partition == "vendor" or partition == "odm":
|
||||
print(f"ro.{partition}.product.cpu.abilist={config['DeviceAbiList']}")
|
||||
print(f"ro.{partition}.product.cpu.abilist32={config['DeviceAbiList32']}")
|
||||
print(f"ro.{partition}.product.cpu.abilist64={config['DeviceAbiList64']}")
|
||||
|
||||
print(f"ro.{partition}.build.date={config['Date']}")
|
||||
print(f"ro.{partition}.build.date.utc={config['DateUtc']}")
|
||||
# Allow optional assignments for ARC forward-declarations (b/249168657)
|
||||
# TODO: Remove any tag-related inconsistencies once the goals from
|
||||
# go/arc-android-sigprop-changes have been achieved.
|
||||
print(f"ro.{partition}.build.fingerprint?={config['BuildFingerprint']}")
|
||||
print(f"ro.{partition}.build.id?={config['BuildId']}")
|
||||
print(f"ro.{partition}.build.tags?={config['BuildVersionTags']}")
|
||||
print(f"ro.{partition}.build.type={config['BuildVariant']}")
|
||||
print(f"ro.{partition}.build.version.incremental={config['BuildNumber']}")
|
||||
print(f"ro.{partition}.build.version.release={config['Platform_version_last_stable']}")
|
||||
print(f"ro.{partition}.build.version.release_or_codename={config['Platform_version_name']}")
|
||||
print(f"ro.{partition}.build.version.sdk={config['Platform_sdk_version']}")
|
||||
|
||||
def generate_build_info(args):
|
||||
print()
|
||||
print("####################################")
|
||||
print("# from gen_build_prop.py:generate_build_info")
|
||||
print("####################################")
|
||||
print("# begin build properties")
|
||||
|
||||
config = args.config
|
||||
build_flags = config["BuildFlags"]
|
||||
|
||||
print(f"ro.build.fingerprint?={config['BuildFingerprint']}")
|
||||
|
||||
# The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest.
|
||||
if config["BoardUseVbmetaDigestInFingerprint"]:
|
||||
print(f"ro.build.legacy.id={config['BuildId']}")
|
||||
else:
|
||||
print(f"ro.build.id?={config['BuildId']}")
|
||||
|
||||
# ro.build.display.id is shown under Settings -> About Phone
|
||||
if config["BuildVariant"] == "user":
|
||||
# User builds should show:
|
||||
# release build number or branch.buld_number non-release builds
|
||||
|
||||
# Dev. branches should have DISPLAY_BUILD_NUMBER set
|
||||
if config["DisplayBuildNumber"]:
|
||||
print(f"ro.build.display.id?={config['BuildId']}.{config['BuildNumber']} {config['BuildKeys']}")
|
||||
else:
|
||||
print(f"ro.build.display.id?={config['BuildId']} {config['BuildKeys']}")
|
||||
else:
|
||||
# Non-user builds should show detailed build information (See build desc above)
|
||||
print(f"ro.build.display.id?={config['tequilaDesc']}")
|
||||
print(f"ro.build.version.incremental={config['BuildNumber']}")
|
||||
print(f"ro.build.version.sdk={config['Platform_sdk_version']}")
|
||||
print(f"ro.build.version.preview_sdk={config['Platform_preview_sdk_version']}")
|
||||
print(f"ro.build.version.preview_sdk_fingerprint={config['PlatformPreviewSdkFingerprint']}")
|
||||
print(f"ro.build.version.codename={config['Platform_sdk_codename']}")
|
||||
print(f"ro.build.version.all_codenames={','.join(config['Platform_version_active_codenames'])}")
|
||||
print(f"ro.build.version.known_codenames={config['Platform_version_known_codenames']}")
|
||||
print(f"ro.build.version.release={config['Platform_version_last_stable']}")
|
||||
print(f"ro.build.version.release_or_codename={config['Platform_version_name']}")
|
||||
print(f"ro.build.version.release_or_preview_display={config['Platform_display_version_name']}")
|
||||
print(f"ro.build.version.security_patch={config['Platform_security_patch']}")
|
||||
print(f"ro.build.version.base_os={config['Platform_base_os']}")
|
||||
print(f"ro.build.version.min_supported_target_sdk={build_flags['RELEASE_PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION']}")
|
||||
print(f"ro.build.date={config['Date']}")
|
||||
print(f"ro.build.date.utc={config['DateUtc']}")
|
||||
print(f"ro.build.type={config['BuildVariant']}")
|
||||
print(f"ro.build.user={config['BuildUsername']}")
|
||||
print(f"ro.build.host={config['BuildHostname']}")
|
||||
# TODO: Remove any tag-related optional property declarations once the goals
|
||||
# from go/arc-android-sigprop-changes have been achieved.
|
||||
print(f"ro.build.tags?={config['BuildVersionTags']}")
|
||||
# ro.build.flavor are used only by the test harness to distinguish builds.
|
||||
# Only add _asan for a sanitized build if it isn't already a part of the
|
||||
# flavor (via a dedicated lunch config for example).
|
||||
print(f"ro.build.flavor={config['BuildFlavor']}")
|
||||
|
||||
print(f"ro.tequila.device={config['tequilaDevice']}")
|
||||
|
||||
# These values are deprecated, use "ro.product.cpu.abilist"
|
||||
# instead (see below).
|
||||
print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
|
||||
print(f"# use ro.product.cpu.abilist instead.")
|
||||
print(f"ro.product.cpu.abi={config['DeviceAbi'][0]}")
|
||||
if len(config["DeviceAbi"]) > 1:
|
||||
print(f"ro.product.cpu.abi2={config['DeviceAbi'][1]}")
|
||||
|
||||
if config["ProductLocales"]:
|
||||
print(f"ro.product.locale={config['ProductLocales'][0]}")
|
||||
print(f"ro.wifi.channels={' '.join(config['ProductDefaultWifiChannels'])}")
|
||||
|
||||
print(f"# ro.build.product is obsolete; use ro.product.device")
|
||||
print(f"ro.build.product={config['DeviceName']}")
|
||||
|
||||
print(f"# Do not try to parse description or thumbprint")
|
||||
print(f"ro.build.description?={config['BuildDesc']}")
|
||||
if "BuildThumbprint" in config:
|
||||
print(f"ro.build.thumbprint={config['BuildThumbprint']}")
|
||||
|
||||
print(f"# end build properties")
|
||||
|
||||
def write_properties_from_file(file):
|
||||
print()
|
||||
print("####################################")
|
||||
print(f"# from {file.name}")
|
||||
print("####################################")
|
||||
print(file.read(), end="")
|
||||
|
||||
def write_properties_from_variable(name, props, build_broken_dup_sysprop):
|
||||
print()
|
||||
print("####################################")
|
||||
print(f"# from variable {name}")
|
||||
print("####################################")
|
||||
|
||||
# Implement the legacy behavior when BUILD_BROKEN_DUP_SYSPROP is on.
|
||||
# Optional assignments are all converted to normal assignments and
|
||||
# when their duplicates the first one wins.
|
||||
if build_broken_dup_sysprop:
|
||||
processed_props = []
|
||||
seen_props = set()
|
||||
for line in props:
|
||||
line = line.replace("?=", "=")
|
||||
key, value = line.split("=", 1)
|
||||
if key in seen_props:
|
||||
continue
|
||||
seen_props.add(key)
|
||||
processed_props.append(line)
|
||||
props = processed_props
|
||||
|
||||
for line in props:
|
||||
print(line)
|
||||
|
||||
def append_additional_system_props(args):
|
||||
props = []
|
||||
|
||||
config = args.config
|
||||
|
||||
# Add the product-defined properties to the build properties.
|
||||
if not config["PropertySplitEnabled"] or not config["VendorImageFileSystemType"]:
|
||||
if "PRODUCT_PROPERTY_OVERRIDES" in config:
|
||||
props += config["PRODUCT_PROPERTY_OVERRIDES"]
|
||||
|
||||
props.append(f"ro.treble.enabled={'true' if config['FullTreble'] else 'false'}")
|
||||
# Set ro.llndk.api_level to show the maximum vendor API level that the LLNDK
|
||||
# in the system partition supports.
|
||||
if config["VendorApiLevel"]:
|
||||
props.append(f"ro.llndk.api_level={config['VendorApiLevel']}")
|
||||
|
||||
# Sets ro.actionable_compatible_property.enabled to know on runtime whether
|
||||
# the allowed list of actionable compatible properties is enabled or not.
|
||||
props.append("ro.actionable_compatible_property.enabled=true")
|
||||
|
||||
# Enable core platform API violation warnings on userdebug and eng builds.
|
||||
if config["BuildVariant"] != "user":
|
||||
props.append("persist.debug.dalvik.vm.core_platform_api_policy=just-warn")
|
||||
|
||||
# Define ro.sanitize.<name> properties for all global sanitizers.
|
||||
for sanitize_target in config["SanitizeDevice"]:
|
||||
props.append(f"ro.sanitize.{sanitize_target}=true")
|
||||
|
||||
# Sets the default value of ro.postinstall.fstab.prefix to /system.
|
||||
# Device board config should override the value to /product when needed by:
|
||||
#
|
||||
# PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product
|
||||
#
|
||||
# It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to
|
||||
# mount system_other partition.
|
||||
props.append("ro.postinstall.fstab.prefix=/system")
|
||||
|
||||
enable_target_debugging = True
|
||||
enable_dalvik_lock_contention_logging = True
|
||||
if config["BuildVariant"] == "user" or config["BuildVariant"] == "userdebug":
|
||||
# Target is secure in user builds.
|
||||
props.append("ro.secure=1")
|
||||
props.append("security.perf_harden=1")
|
||||
|
||||
if config["BuildVariant"] == "user":
|
||||
# Disable debugging in plain user builds.
|
||||
props.append("ro.adb.secure=1")
|
||||
enable_target_debugging = False
|
||||
enable_dalvik_lock_contention_logging = False
|
||||
else:
|
||||
# Disable debugging in userdebug builds if PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG
|
||||
# is set.
|
||||
if config["ProductNotDebuggableInUserdebug"]:
|
||||
enable_target_debugging = False
|
||||
|
||||
# Disallow mock locations by default for user builds
|
||||
props.append("ro.allow.mock.location=0")
|
||||
else:
|
||||
# Turn on checkjni for non-user builds.
|
||||
props.append("ro.kernel.android.checkjni=1")
|
||||
# Set device insecure for non-user builds.
|
||||
props.append("ro.secure=0")
|
||||
# Allow mock locations by default for non user builds
|
||||
props.append("ro.allow.mock.location=1")
|
||||
|
||||
if enable_dalvik_lock_contention_logging:
|
||||
# Enable Dalvik lock contention logging.
|
||||
props.append("dalvik.vm.lockprof.threshold=500")
|
||||
|
||||
if enable_target_debugging:
|
||||
# Target is more debuggable and adbd is on by default
|
||||
props.append("ro.debuggable=1")
|
||||
else:
|
||||
# Target is less debuggable and adbd is off by default
|
||||
props.append("ro.debuggable=0")
|
||||
|
||||
if config["BuildVariant"] == "eng":
|
||||
if "ro.setupwizard.mode=ENABLED" in props:
|
||||
# Don't require the setup wizard on eng builds
|
||||
props = list(filter(lambda x: not x.startswith("ro.setupwizard.mode="), props))
|
||||
props.append("ro.setupwizard.mode=OPTIONAL")
|
||||
|
||||
if not config["SdkBuild"]:
|
||||
# To speedup startup of non-preopted builds, don't verify or compile the boot image.
|
||||
props.append("dalvik.vm.image-dex2oat-filter=extract")
|
||||
# b/323566535
|
||||
props.append("init.svc_debug.no_fatal.zygote=true")
|
||||
|
||||
if config["SdkBuild"]:
|
||||
props.append("xmpp.auto-presence=true")
|
||||
props.append("ro.config.nocheckin=yes")
|
||||
|
||||
props.append("net.bt.name=Android")
|
||||
|
||||
# This property is set by flashing debug boot image, so default to false.
|
||||
props.append("ro.force.debuggable=0")
|
||||
|
||||
config["ADDITIONAL_SYSTEM_PROPERTIES"] = props
|
||||
|
||||
def append_additional_vendor_props(args):
|
||||
props = []
|
||||
|
||||
config = args.config
|
||||
build_flags = config["BuildFlags"]
|
||||
|
||||
# Add cpu properties for bionic and ART.
|
||||
props.append(f"ro.bionic.arch={config['DeviceArch']}")
|
||||
props.append(f"ro.bionic.cpu_variant={config['DeviceCpuVariantRuntime']}")
|
||||
props.append(f"ro.bionic.2nd_arch={config['DeviceSecondaryArch']}")
|
||||
props.append(f"ro.bionic.2nd_cpu_variant={config['DeviceSecondaryCpuVariantRuntime']}")
|
||||
|
||||
props.append(f"persist.sys.dalvik.vm.lib.2=libart.so")
|
||||
props.append(f"dalvik.vm.isa.{config['DeviceArch']}.variant={config['Dex2oatTargetCpuVariantRuntime']}")
|
||||
if config["Dex2oatTargetInstructionSetFeatures"]:
|
||||
props.append(f"dalvik.vm.isa.{config['DeviceArch']}.features={config['Dex2oatTargetInstructionSetFeatures']}")
|
||||
|
||||
if config["DeviceSecondaryArch"]:
|
||||
props.append(f"dalvik.vm.isa.{config['DeviceSecondaryArch']}.variant={config['SecondaryDex2oatCpuVariantRuntime']}")
|
||||
if config["SecondaryDex2oatInstructionSetFeatures"]:
|
||||
props.append(f"dalvik.vm.isa.{config['DeviceSecondaryArch']}.features={config['SecondaryDex2oatInstructionSetFeatures']}")
|
||||
|
||||
# Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger
|
||||
# mode (via libminui).
|
||||
if config["RecoveryDefaultRotation"]:
|
||||
props.append(f"ro.minui.default_rotation={config['RecoveryDefaultRotation']}")
|
||||
|
||||
if config["RecoveryDefaultTouchRotation"]:
|
||||
props.append(f"ro.minui.default_touch_rotation={config['RecoveryDefaultTouchRotation']}")
|
||||
|
||||
if config["RecoveryOverscanPercent"]:
|
||||
props.append(f"ro.minui.overscan_percent={config['RecoveryOverscanPercent']}")
|
||||
|
||||
if config["RecoveryPixelFormat"]:
|
||||
props.append(f"ro.minui.pixel_format={config['RecoveryPixelFormat']}")
|
||||
|
||||
if "UseDynamicPartitions" in config:
|
||||
props.append(f"ro.boot.dynamic_partitions={'true' if config['UseDynamicPartitions'] else 'false'}")
|
||||
|
||||
if "RetrofitDynamicPartitions" in config:
|
||||
props.append(f"ro.boot.dynamic_partitions_retrofit={'true' if config['RetrofitDynamicPartitions'] else 'false'}")
|
||||
|
||||
if config["ShippingApiLevel"]:
|
||||
props.append(f"ro.product.first_api_level={config['ShippingApiLevel']}")
|
||||
|
||||
if config["ShippingVendorApiLevel"]:
|
||||
props.append(f"ro.vendor.api_level={config['ShippingVendorApiLevel']}")
|
||||
|
||||
if config["BuildVariant"] != "user" and config["BuildDebugfsRestrictionsEnabled"]:
|
||||
props.append(f"ro.product.debugfs_restrictions.enabled=true")
|
||||
|
||||
# Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
|
||||
# This must not be defined for the non-GRF devices.
|
||||
# The values of the GRF properties will be verified by post_process_props.py
|
||||
if config["BoardShippingApiLevel"]:
|
||||
props.append(f"ro.board.first_api_level={config['BoardShippingApiLevel']}")
|
||||
|
||||
# Build system set BOARD_API_LEVEL to show the api level of the vendor API surface.
|
||||
# This must not be altered outside of build system.
|
||||
if config["VendorApiLevel"]:
|
||||
props.append(f"ro.board.api_level={config['VendorApiLevel']}")
|
||||
|
||||
# RELEASE_BOARD_API_LEVEL_FROZEN is true when the vendor API surface is frozen.
|
||||
if build_flags["RELEASE_BOARD_API_LEVEL_FROZEN"]:
|
||||
props.append(f"ro.board.api_frozen=true")
|
||||
|
||||
# Set build prop. This prop is read by ota_from_target_files when generating OTA,
|
||||
# to decide if VABC should be disabled.
|
||||
if config["DontUseVabcOta"]:
|
||||
props.append(f"ro.vendor.build.dont_use_vabc=true")
|
||||
|
||||
# Set the flag in vendor. So VTS would know if the new fingerprint format is in use when
|
||||
# the system images are replaced by GSI.
|
||||
if config["BoardUseVbmetaDigestInFingerprint"]:
|
||||
props.append(f"ro.vendor.build.fingerprint_has_digest=1")
|
||||
|
||||
props.append(f"ro.vendor.build.security_patch={config['VendorSecurityPatch']}")
|
||||
props.append(f"ro.product.board={config['BootloaderBoardName']}")
|
||||
props.append(f"ro.board.platform={config['BoardPlatform']}")
|
||||
props.append(f"ro.hwui.use_vulkan={'true' if config['UsesVulkan'] else 'false'}")
|
||||
|
||||
if config["ScreenDensity"]:
|
||||
props.append(f"ro.sf.lcd_density={config['ScreenDensity']}")
|
||||
|
||||
if "AbOtaUpdater" in config:
|
||||
props.append(f"ro.build.ab_update={'true' if config['AbOtaUpdater'] else 'false'}")
|
||||
if config["AbOtaUpdater"]:
|
||||
props.append(f"ro.vendor.build.ab_ota_partitions={config['AbOtaPartitions']}")
|
||||
|
||||
config["ADDITIONAL_VENDOR_PROPERTIES"] = props
|
||||
|
||||
def append_additional_product_props(args):
|
||||
props = []
|
||||
|
||||
config = args.config
|
||||
|
||||
# Add the system server compiler filter if they are specified for the product.
|
||||
if config["SystemServerCompilerFilter"]:
|
||||
props.append(f"dalvik.vm.systemservercompilerfilter={config['SystemServerCompilerFilter']}")
|
||||
|
||||
# Add the 16K developer args if it is defined for the product.
|
||||
props.append(f"ro.product.build.16k_page.enabled={'true' if config['Product16KDeveloperOption'] else 'false'}")
|
||||
|
||||
props.append(f"ro.product.page_size={16384 if config['TargetBoots16K'] else 4096}")
|
||||
|
||||
props.append(f"ro.build.characteristics={config['AAPTCharacteristics']}")
|
||||
|
||||
if "AbOtaUpdater" in config and config["AbOtaUpdater"]:
|
||||
props.append(f"ro.product.ab_ota_partitions={config['AbOtaPartitions']}")
|
||||
|
||||
# Set this property for VTS to skip large page size tests on unsupported devices.
|
||||
props.append(f"ro.product.cpu.pagesize.max={config['DeviceMaxPageSizeSupported']}")
|
||||
|
||||
if config["NoBionicPageSizeMacro"]:
|
||||
props.append(f"ro.product.build.no_bionic_page_size_macro=true")
|
||||
|
||||
# This is a temporary system property that controls the ART module. The plan is
|
||||
# to remove it by Aug 2025, at which time Mainline updates of the ART module
|
||||
# will ignore it as well.
|
||||
# If the value is "default", it will be mangled by post_process_props.py.
|
||||
props.append(f"ro.dalvik.vm.enable_uffd_gc={config['EnableUffdGc']}")
|
||||
|
||||
config["ADDITIONAL_PRODUCT_PROPERTIES"] = props
|
||||
|
||||
def build_system_prop(args):
|
||||
config = args.config
|
||||
|
||||
# Order matters here. When there are duplicates, the last one wins.
|
||||
# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
|
||||
variables = [
|
||||
"ADDITIONAL_SYSTEM_PROPERTIES",
|
||||
"PRODUCT_SYSTEM_PROPERTIES",
|
||||
# TODO(b/117892318): deprecate this
|
||||
"PRODUCT_SYSTEM_DEFAULT_PROPERTIES",
|
||||
]
|
||||
|
||||
if not config["PropertySplitEnabled"]:
|
||||
variables += [
|
||||
"ADDITIONAL_VENDOR_PROPERTIES",
|
||||
"PRODUCT_VENDOR_PROPERTIES",
|
||||
]
|
||||
|
||||
build_prop(args, gen_build_info=True, gen_common_build_props=True, variables=variables)
|
||||
|
||||
def build_system_ext_prop(args):
|
||||
config = args.config
|
||||
|
||||
# Order matters here. When there are duplicates, the last one wins.
|
||||
# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
|
||||
variables = ["PRODUCT_SYSTEM_EXT_PROPERTIES"]
|
||||
|
||||
build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
|
||||
|
||||
'''
|
||||
def build_vendor_prop(args):
|
||||
config = args.config
|
||||
|
||||
# Order matters here. When there are duplicates, the last one wins.
|
||||
# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
|
||||
variables = []
|
||||
if config["PropertySplitEnabled"]:
|
||||
variables += [
|
||||
"ADDITIONAL_VENDOR_PROPERTIES",
|
||||
"PRODUCT_VENDOR_PROPERTIES",
|
||||
# TODO(b/117892318): deprecate this
|
||||
"PRODUCT_DEFAULT_PROPERTY_OVERRIDES",
|
||||
"PRODUCT_PROPERTY_OVERRIDES",
|
||||
]
|
||||
|
||||
build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
|
||||
'''
|
||||
|
||||
def build_product_prop(args):
|
||||
config = args.config
|
||||
|
||||
# Order matters here. When there are duplicates, the last one wins.
|
||||
# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
|
||||
variables = [
|
||||
"ADDITIONAL_PRODUCT_PROPERTIES",
|
||||
"PRODUCT_PRODUCT_PROPERTIES",
|
||||
]
|
||||
|
||||
gen_common_build_props = True
|
||||
|
||||
# Skip common /product properties generation if device released before R and
|
||||
# has no product partition. This is the first part of the check.
|
||||
if config["Shipping_api_level"] and int(config["Shipping_api_level"]) < 30:
|
||||
gen_common_build_props = False
|
||||
|
||||
# The second part of the check - always generate common properties for the
|
||||
# devices with product partition regardless of shipping level.
|
||||
if config["UsesProductImage"]:
|
||||
gen_common_build_props = True
|
||||
|
||||
build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
|
||||
|
||||
if config["OemProperties"]:
|
||||
print("####################################")
|
||||
print("# PRODUCT_OEM_PROPERTIES")
|
||||
print("####################################")
|
||||
|
||||
for prop in config["OemProperties"]:
|
||||
print(f"import /oem/oem.prop {prop}")
|
||||
|
||||
def build_odm_prop(args):
|
||||
variables = ["ADDITIONAL_ODM_PROPERTIES", "PRODUCT_ODM_PROPERTIES"]
|
||||
build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
|
||||
|
||||
def build_prop(args, gen_build_info, gen_common_build_props, variables):
|
||||
config = args.config
|
||||
|
||||
if gen_common_build_props:
|
||||
generate_common_build_props(args)
|
||||
|
||||
if gen_build_info:
|
||||
generate_build_info(args)
|
||||
|
||||
for prop_file in args.prop_files:
|
||||
write_properties_from_file(prop_file)
|
||||
|
||||
for variable in variables:
|
||||
if variable in config:
|
||||
write_properties_from_variable(variable, config[variable], args.build_broken_dup_sysprop)
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
with contextlib.redirect_stdout(args.out):
|
||||
match args.partition:
|
||||
case "system":
|
||||
build_system_prop(args)
|
||||
case "system_ext":
|
||||
build_system_ext_prop(args)
|
||||
case "odm":
|
||||
build_odm_prop(args)
|
||||
case "product":
|
||||
build_product_prop(args)
|
||||
# case "vendor": # NOT IMPLEMENTED
|
||||
# build_vendor_prop(args)
|
||||
case _:
|
||||
sys.exit(f"not supported partition {args.partition}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
62
scripts/merge_json.py
Normal file
62
scripts/merge_json.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2024 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
"""A tool for merging two or more JSON files."""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
import sys
|
||||
|
||||
def parse_args():
|
||||
"""Parse commandline arguments."""
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("output", help="output JSON file", type=argparse.FileType("w"))
|
||||
parser.add_argument("input", help="input JSON files", nargs="+", type=argparse.FileType("r"))
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
"""Program entry point."""
|
||||
args = parse_args()
|
||||
merged_dict = {}
|
||||
has_error = False
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
for json_file in args.input:
|
||||
try:
|
||||
data = json.load(json_file)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error(f"Error parsing JSON in file: {json_file.name}. Reason: {e}")
|
||||
has_error = True
|
||||
continue
|
||||
|
||||
for key, value in data.items():
|
||||
if key not in merged_dict:
|
||||
merged_dict[key] = value
|
||||
elif merged_dict[key] == value:
|
||||
logger.warning(f"Duplicate key '{key}' with identical values found.")
|
||||
else:
|
||||
logger.error(f"Conflicting values for key '{key}': {merged_dict[key]} != {value}")
|
||||
has_error = True
|
||||
|
||||
if has_error:
|
||||
sys.exit(1)
|
||||
|
||||
json.dump(merged_dict, args.output)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -129,12 +129,12 @@ func (c *hostFakeSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
if !seen[outFile] {
|
||||
seen[outFile] = true
|
||||
outputs = append(outputs, WriteStringToFileRule(ctx, "", outFile))
|
||||
jsonData = append(jsonData, hostSnapshotFakeJsonFlags{*hostJsonDesc(module), false})
|
||||
jsonData = append(jsonData, hostSnapshotFakeJsonFlags{*hostJsonDesc(ctx, module), false})
|
||||
}
|
||||
}
|
||||
})
|
||||
// Update any module prebuilt information
|
||||
for idx, _ := range jsonData {
|
||||
for idx := range jsonData {
|
||||
if _, ok := prebuilts[jsonData[idx].ModuleName]; ok {
|
||||
// Prebuilt exists for this module
|
||||
jsonData[idx].Prebuilt = true
|
||||
|
|
|
@ -101,7 +101,7 @@ func (f *hostSnapshot) CreateMetaData(ctx android.ModuleContext, fileName string
|
|||
|
||||
// Create JSON file based on the direct dependencies
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
desc := hostJsonDesc(dep)
|
||||
desc := hostJsonDesc(ctx, dep)
|
||||
if desc != nil {
|
||||
jsonData = append(jsonData, *desc)
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ func hostRelativePathString(m android.Module) string {
|
|||
|
||||
// Create JSON description for given module, only create descriptions for binary modules
|
||||
// and rust_proc_macro modules which provide a valid HostToolPath
|
||||
func hostJsonDesc(m android.Module) *SnapshotJsonFlags {
|
||||
func hostJsonDesc(ctx android.ConfigAndErrorContext, m android.Module) *SnapshotJsonFlags {
|
||||
path := hostToolPath(m)
|
||||
relPath := hostRelativePathString(m)
|
||||
procMacro := false
|
||||
|
@ -226,7 +226,7 @@ func hostJsonDesc(m android.Module) *SnapshotJsonFlags {
|
|||
props := &SnapshotJsonFlags{
|
||||
ModuleStemName: moduleStem,
|
||||
Filename: path.String(),
|
||||
Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames()...),
|
||||
Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames(ctx)...),
|
||||
RelativeInstallPath: relPath,
|
||||
RustProcMacro: procMacro,
|
||||
CrateName: crateName,
|
||||
|
|
|
@ -79,7 +79,7 @@ func SetupOutDir(ctx Context, config Config) {
|
|||
if username, ok = config.environ.Get("BUILD_USERNAME"); !ok {
|
||||
ctx.Fatalln("Missing BUILD_USERNAME")
|
||||
}
|
||||
buildNumber = fmt.Sprintf("eng.%.6s.00000000.000000", username)
|
||||
buildNumber = fmt.Sprintf("eng.%.6s", username)
|
||||
writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", username)
|
||||
}
|
||||
// Write the build number to a file so it can be read back in
|
||||
|
|
|
@ -125,11 +125,13 @@ func installClean(ctx Context, config Config) {
|
|||
hostCommonOut("obj/PACKAGING"),
|
||||
productOut("*.img"),
|
||||
productOut("*.zip"),
|
||||
productOut("*.zip.sha256sum"),
|
||||
productOut("android-info.txt"),
|
||||
productOut("misc_info.txt"),
|
||||
productOut("apex"),
|
||||
productOut("kernel"),
|
||||
productOut("kernel-*"),
|
||||
productOut("recovery_kernel"),
|
||||
productOut("data"),
|
||||
productOut("skin"),
|
||||
productOut("obj/NOTICE_FILES"),
|
||||
|
@ -160,7 +162,8 @@ func installClean(ctx Context, config Config) {
|
|||
productOut("odm_dlkm"),
|
||||
productOut("sysloader"),
|
||||
productOut("testcases"),
|
||||
productOut("symbols"))
|
||||
productOut("symbols"),
|
||||
productOut("install"))
|
||||
}
|
||||
|
||||
// Since products and build variants (unfortunately) shared the same
|
||||
|
|
|
@ -1488,6 +1488,15 @@ func (c *configImpl) SoongVarsFile() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *configImpl) SoongExtraVarsFile() string {
|
||||
targetProduct, err := c.TargetProductOrErr()
|
||||
if err != nil {
|
||||
return filepath.Join(c.SoongOutDir(), "soong.extra.variables")
|
||||
} else {
|
||||
return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".extra.variables")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *configImpl) SoongNinjaFile() string {
|
||||
targetProduct, err := c.TargetProductOrErr()
|
||||
if err != nil {
|
||||
|
|
|
@ -147,6 +147,7 @@ func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_
|
|||
var BannerVars = []string{
|
||||
"PLATFORM_VERSION_CODENAME",
|
||||
"PLATFORM_VERSION",
|
||||
"TEQUILA_VERSION",
|
||||
"PRODUCT_SOURCE_ROOT_DIRS",
|
||||
"TARGET_PRODUCT",
|
||||
"TARGET_BUILD_VARIANT",
|
||||
|
@ -164,6 +165,8 @@ var BannerVars = []string{
|
|||
"BUILD_ID",
|
||||
"OUT_DIR",
|
||||
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE",
|
||||
"GMS_MAKEFILE",
|
||||
"PRODUCT_SOONG_NAMESPACES",
|
||||
}
|
||||
|
||||
func Banner(make_vars map[string]string) string {
|
||||
|
@ -242,7 +245,6 @@ func runMakeProductConfig(ctx Context, config Config) {
|
|||
"HOST_CROSS_ARCH",
|
||||
"HOST_CROSS_2ND_ARCH",
|
||||
"HOST_BUILD_TYPE",
|
||||
"PRODUCT_SOONG_NAMESPACES",
|
||||
|
||||
"DEFAULT_WARNING_BUILD_MODULE_TYPES",
|
||||
"DEFAULT_ERROR_BUILD_MODULE_TYPES",
|
||||
|
|
|
@ -228,6 +228,13 @@ func (c *Cmd) wrapSandbox() {
|
|||
sandboxArgs = append(sandboxArgs, "-N")
|
||||
}
|
||||
|
||||
if ccacheExec := os.Getenv("CCACHE_EXEC"); ccacheExec != "" {
|
||||
bytes, err := exec.Command(ccacheExec, "-k", "cache_dir").Output()
|
||||
if err == nil {
|
||||
sandboxArgs = append(sandboxArgs, "-B", strings.TrimSpace(string(bytes)))
|
||||
}
|
||||
}
|
||||
|
||||
// Stop nsjail from parsing arguments
|
||||
sandboxArgs = append(sandboxArgs, "--")
|
||||
|
||||
|
|
|
@ -694,6 +694,7 @@ func runSoong(ctx Context, config Config) {
|
|||
}
|
||||
}
|
||||
distFile(ctx, config, config.SoongVarsFile(), "soong")
|
||||
distFile(ctx, config, config.SoongExtraVarsFile(), "soong")
|
||||
|
||||
if !config.SkipKati() {
|
||||
distGzipFile(ctx, config, config.SoongAndroidMk(), "soong")
|
||||
|
|
|
@ -64,7 +64,8 @@ func testForDanglingRules(ctx Context, config Config) {
|
|||
outDir := config.OutDir()
|
||||
modulePathsDir := filepath.Join(outDir, ".module_paths")
|
||||
rawFilesDir := filepath.Join(outDir, "soong", "raw")
|
||||
variablesFilePath := filepath.Join(outDir, "soong", "soong.variables")
|
||||
variablesFilePath := config.SoongVarsFile()
|
||||
extraVariablesFilePath := config.SoongExtraVarsFile()
|
||||
|
||||
// dexpreopt.config is an input to the soong_docs action, which runs the
|
||||
// soong_build primary builder. However, this file is created from $(shell)
|
||||
|
@ -95,6 +96,7 @@ func testForDanglingRules(ctx Context, config Config) {
|
|||
if strings.HasPrefix(line, modulePathsDir) ||
|
||||
strings.HasPrefix(line, rawFilesDir) ||
|
||||
line == variablesFilePath ||
|
||||
line == extraVariablesFilePath ||
|
||||
line == dexpreoptConfigFilePath ||
|
||||
line == buildDatetimeFilePath ||
|
||||
line == bpglob ||
|
||||
|
|
Loading…
Reference in a new issue