Aconfig rules
Test: m services_device_config (which runs sooong tests too) Change-Id: I432e914d01d2bff77ba68de65ae5baea527090f5
This commit is contained in:
@@ -183,6 +183,16 @@ func (c Config) MaxPageSizeSupported() string {
|
||||
return String(c.config.productVariables.DeviceMaxPageSizeSupported)
|
||||
}
|
||||
|
||||
// The release version passed to aconfig, derived from RELEASE_VERSION
|
||||
func (c Config) ReleaseVersion() string {
|
||||
return c.config.productVariables.ReleaseVersion
|
||||
}
|
||||
|
||||
// The flag values files passed to aconfig, derived from RELEASE_VERSION
|
||||
func (c Config) ReleaseDeviceConfigValueSets() []string {
|
||||
return c.config.productVariables.ReleaseDeviceConfigValueSets
|
||||
}
|
||||
|
||||
// A DeviceConfig object represents the configuration for a particular device
|
||||
// being built. For now there will only be one of these, but in the future there
|
||||
// may be multiple devices being built.
|
||||
|
@@ -473,6 +473,9 @@ type productVariables struct {
|
||||
ProductManufacturer string `json:",omitempty"`
|
||||
ProductBrand string `json:",omitempty"`
|
||||
BuildVersionTags []string `json:",omitempty"`
|
||||
|
||||
ReleaseVersion string `json:",omitempty"`
|
||||
ReleaseDeviceConfigValueSets []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func boolPtr(v bool) *bool {
|
||||
|
30
device_config/Android.bp
Normal file
30
device_config/Android.bp
Normal file
@@ -0,0 +1,30 @@
|
||||
package {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
bootstrap_go_package {
|
||||
name: "soong-device_config",
|
||||
pkgPath: "android/soong/device_config",
|
||||
deps: [
|
||||
"blueprint",
|
||||
"blueprint-pathtools",
|
||||
"sbox_proto",
|
||||
"soong",
|
||||
"soong-android",
|
||||
"soong-bazel",
|
||||
"soong-shared",
|
||||
],
|
||||
srcs: [
|
||||
"device_config_definitions.go",
|
||||
"device_config_values.go",
|
||||
"device_config_value_set.go",
|
||||
"init.go",
|
||||
//"testing.go"
|
||||
],
|
||||
/*
|
||||
testSrcs: [
|
||||
"device_config_test.go",
|
||||
],
|
||||
*/
|
||||
pluginFor: ["soong_build"],
|
||||
}
|
150
device_config/device_config_definitions.go
Normal file
150
device_config/device_config_definitions.go
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2023 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 device_config
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"fmt"
|
||||
"github.com/google/blueprint"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DefinitionsModule struct {
|
||||
android.ModuleBase
|
||||
android.DefaultableModuleBase
|
||||
|
||||
// Properties for "device_config_definitions"
|
||||
properties struct {
|
||||
// aconfig files, relative to this Android.bp file
|
||||
Srcs []string `android:"path"`
|
||||
|
||||
// Release config flag namespace
|
||||
Namespace string
|
||||
|
||||
// Values from TARGET_RELEASE / RELEASE_DEVICE_CONFIG_VALUE_SETS
|
||||
Values []string `blueprint:"mutated"`
|
||||
}
|
||||
|
||||
intermediatePath android.WritablePath
|
||||
srcJarPath android.WritablePath
|
||||
}
|
||||
|
||||
func DefinitionsFactory() android.Module {
|
||||
module := &DefinitionsModule{}
|
||||
|
||||
android.InitAndroidModule(module)
|
||||
android.InitDefaultableModule(module)
|
||||
module.AddProperties(&module.properties)
|
||||
// TODO: bp2build
|
||||
//android.InitBazelModule(module)
|
||||
|
||||
return module
|
||||
}
|
||||
|
||||
type implicitValuesTagType struct {
|
||||
blueprint.BaseDependencyTag
|
||||
}
|
||||
|
||||
var implicitValuesTag = implicitValuesTagType{}
|
||||
|
||||
func (module *DefinitionsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
// Validate Properties
|
||||
if len(module.properties.Srcs) == 0 {
|
||||
ctx.PropertyErrorf("srcs", "missing source files")
|
||||
return
|
||||
}
|
||||
if len(module.properties.Namespace) == 0 {
|
||||
ctx.PropertyErrorf("namespace", "missing namespace property")
|
||||
}
|
||||
|
||||
// Add a dependency on the device_config_value_sets defined in
|
||||
// RELEASE_DEVICE_CONFIG_VALUE_SETS, and add any device_config_values that
|
||||
// match our namespace.
|
||||
valuesFromConfig := ctx.Config().ReleaseDeviceConfigValueSets()
|
||||
ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
|
||||
}
|
||||
|
||||
func (module *DefinitionsModule) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case ".srcjar":
|
||||
return []android.Path{module.srcJarPath}, nil
|
||||
case "":
|
||||
// The default output of this module is the intermediates format, which is
|
||||
// not installable and in a private format that no other rules can handle
|
||||
// correctly.
|
||||
return []android.Path{module.intermediatePath}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported device_config_definitions module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
func joinAndPrefix(prefix string, values []string) string {
|
||||
var sb strings.Builder
|
||||
for _, v := range values {
|
||||
sb.WriteString(prefix)
|
||||
sb.WriteString(v)
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (module *DefinitionsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
// Get the values that came from the global RELEASE_DEVICE_CONFIG_VALUE_SETS flag
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
if !ctx.OtherModuleHasProvider(dep, valueSetProviderKey) {
|
||||
// Other modules get injected as dependencies too, for example the license modules
|
||||
return
|
||||
}
|
||||
depData := ctx.OtherModuleProvider(dep, valueSetProviderKey).(valueSetProviderData)
|
||||
valuesFiles, ok := depData.AvailableNamespaces[module.properties.Namespace]
|
||||
if ok {
|
||||
for _, path := range valuesFiles {
|
||||
module.properties.Values = append(module.properties.Values, path.String())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Intermediate format
|
||||
inputFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
|
||||
module.intermediatePath = android.PathForModuleOut(ctx, "intermediate.json")
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: aconfigRule,
|
||||
Inputs: inputFiles,
|
||||
Output: module.intermediatePath,
|
||||
Description: "device_config_definitions",
|
||||
Args: map[string]string{
|
||||
"release_version": ctx.Config().ReleaseVersion(),
|
||||
"namespace": module.properties.Namespace,
|
||||
"values": joinAndPrefix(" --values ", module.properties.Values),
|
||||
},
|
||||
})
|
||||
|
||||
// Generated java inside a srcjar
|
||||
module.srcJarPath = android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: srcJarRule,
|
||||
Input: module.intermediatePath,
|
||||
Output: module.srcJarPath,
|
||||
Description: "device_config.srcjar",
|
||||
})
|
||||
|
||||
// TODO: C++
|
||||
|
||||
// Phony target for debugging convenience
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: blueprint.Phony,
|
||||
Output: android.PathForPhony(ctx, ctx.ModuleName()),
|
||||
Inputs: []android.Path{module.srcJarPath}, // TODO: C++
|
||||
})
|
||||
}
|
61
device_config/device_config_test.go
Normal file
61
device_config/device_config_test.go
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2019 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.
|
||||
|
||||
package device_config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/java"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func test(t *testing.T, bp string) *android.TestResult {
|
||||
t.Helper()
|
||||
|
||||
mockFS := android.MockFS{
|
||||
"config.aconfig": nil,
|
||||
}
|
||||
|
||||
result := android.GroupFixturePreparers(
|
||||
java.PrepareForTestWithJavaDefaultModules,
|
||||
PrepareForTestWithSyspropBuildComponents,
|
||||
// TODO: Consider values files, although maybe in its own test
|
||||
// android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
|
||||
// variables.ReleaseConfigValuesBasePaths = ...
|
||||
//})
|
||||
mockFS.AddToFixture(),
|
||||
android.FixtureWithRootAndroidBp(bp),
|
||||
).RunTest(t)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func TestOutputs(t *testing.T) {
|
||||
/*result := */ test(t, `
|
||||
device_config {
|
||||
name: "my_device_config",
|
||||
srcs: ["config.aconfig"],
|
||||
}
|
||||
`)
|
||||
|
||||
// TODO: Make sure it exports a .srcjar, which is used by java libraries
|
||||
// TODO: Make sure it exports an intermediates file
|
||||
// TODO: Make sure the intermediates file is propagated to the Android.mk file
|
||||
}
|
92
device_config/device_config_value_set.go
Normal file
92
device_config/device_config_value_set.go
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright 2023 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 device_config
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
// Properties for "device_config_value_set"
|
||||
type ValueSetModule struct {
|
||||
android.ModuleBase
|
||||
android.DefaultableModuleBase
|
||||
|
||||
properties struct {
|
||||
// device_config_values modules
|
||||
Values []string
|
||||
}
|
||||
}
|
||||
|
||||
func ValueSetFactory() android.Module {
|
||||
module := &ValueSetModule{}
|
||||
|
||||
android.InitAndroidModule(module)
|
||||
android.InitDefaultableModule(module)
|
||||
module.AddProperties(&module.properties)
|
||||
// TODO: bp2build
|
||||
//android.InitBazelModule(module)
|
||||
|
||||
return module
|
||||
}
|
||||
|
||||
// Dependency tag for values property
|
||||
type valueSetType struct {
|
||||
blueprint.BaseDependencyTag
|
||||
}
|
||||
|
||||
var valueSetTag = valueSetType{}
|
||||
|
||||
// Provider published by device_config_value_set
|
||||
type valueSetProviderData struct {
|
||||
// The namespace of each of the
|
||||
// (map of namespace --> device_config_module)
|
||||
AvailableNamespaces map[string]android.Paths
|
||||
}
|
||||
|
||||
var valueSetProviderKey = blueprint.NewProvider(valueSetProviderData{})
|
||||
|
||||
func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
|
||||
for _, dep := range deps {
|
||||
_, ok := dep.(*ValuesModule)
|
||||
if !ok {
|
||||
ctx.PropertyErrorf("values", "values must be a device_config_values module")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
// Accumulate the namespaces of the values modules listed, and set that as an
|
||||
// valueSetProviderKey provider that device_config modules can read and use
|
||||
// to append values to their aconfig actions.
|
||||
namespaces := make(map[string]android.Paths)
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
if !ctx.OtherModuleHasProvider(dep, valuesProviderKey) {
|
||||
// Other modules get injected as dependencies too, for example the license modules
|
||||
return
|
||||
}
|
||||
depData := ctx.OtherModuleProvider(dep, valuesProviderKey).(valuesProviderData)
|
||||
|
||||
srcs := make([]android.Path, len(depData.Values))
|
||||
copy(srcs, depData.Values)
|
||||
namespaces[depData.Namespace] = srcs
|
||||
|
||||
})
|
||||
ctx.SetProvider(valueSetProviderKey, valueSetProviderData{
|
||||
AvailableNamespaces: namespaces,
|
||||
})
|
||||
}
|
70
device_config/device_config_values.go
Normal file
70
device_config/device_config_values.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2023 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 device_config
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
// Properties for "device_config_value"
|
||||
type ValuesModule struct {
|
||||
android.ModuleBase
|
||||
android.DefaultableModuleBase
|
||||
|
||||
properties struct {
|
||||
// aconfig files, relative to this Android.bp file
|
||||
Srcs []string `android:"path"`
|
||||
|
||||
// Release config flag namespace
|
||||
Namespace string
|
||||
}
|
||||
}
|
||||
|
||||
func ValuesFactory() android.Module {
|
||||
module := &ValuesModule{}
|
||||
|
||||
android.InitAndroidModule(module)
|
||||
android.InitDefaultableModule(module)
|
||||
module.AddProperties(&module.properties)
|
||||
// TODO: bp2build
|
||||
//android.InitBazelModule(module)
|
||||
|
||||
return module
|
||||
}
|
||||
|
||||
// Provider published by device_config_value_set
|
||||
type valuesProviderData struct {
|
||||
// The namespace that this values module values
|
||||
Namespace string
|
||||
|
||||
// The values aconfig files, relative to the root of the tree
|
||||
Values android.Paths
|
||||
}
|
||||
|
||||
var valuesProviderKey = blueprint.NewProvider(valuesProviderData{})
|
||||
|
||||
func (module *ValuesModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
if len(module.properties.Namespace) == 0 {
|
||||
ctx.PropertyErrorf("namespace", "missing namespace property")
|
||||
}
|
||||
|
||||
// Provide the our source files list to the device_config_value_set as a list of files
|
||||
providerData := valuesProviderData{
|
||||
Namespace: module.properties.Namespace,
|
||||
Values: android.PathsForModuleSrc(ctx, module.properties.Srcs),
|
||||
}
|
||||
ctx.SetProvider(valuesProviderKey, providerData)
|
||||
}
|
70
device_config/init.go
Normal file
70
device_config/init.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2023 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 device_config
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
var (
|
||||
pctx = android.NewPackageContext("android/soong/device_config")
|
||||
|
||||
// For device_config_definitions: Generate cache file
|
||||
// TODO: Restat
|
||||
aconfigRule = pctx.AndroidStaticRule("aconfig",
|
||||
blueprint.RuleParams{
|
||||
Command: `${aconfig} create-cache` +
|
||||
` --namespace ${namespace}` +
|
||||
` --declarations ${in}` +
|
||||
` ${values}` +
|
||||
` --cache ${out}.tmp` +
|
||||
` && ( if cmp -s ${out}.tmp ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
|
||||
// ` --build-id ${release_version}` +
|
||||
CommandDeps: []string{
|
||||
"${aconfig}",
|
||||
},
|
||||
Restat: true,
|
||||
}, "release_version", "namespace", "values")
|
||||
|
||||
// For device_config_definitions: Generate java file
|
||||
srcJarRule = pctx.AndroidStaticRule("aconfig_srcjar",
|
||||
blueprint.RuleParams{
|
||||
Command: `rm -rf ${out}.tmp` +
|
||||
` && mkdir -p ${out}.tmp` +
|
||||
` && ${aconfig} create-java-lib` +
|
||||
` --cache ${in}` +
|
||||
` --out ${out}.tmp` +
|
||||
` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
|
||||
` && rm -rf ${out}.tmp`,
|
||||
CommandDeps: []string{
|
||||
"$aconfig",
|
||||
"$soong_zip",
|
||||
},
|
||||
Restat: true,
|
||||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerBuildComponents(android.InitRegistrationContext)
|
||||
}
|
||||
|
||||
func registerBuildComponents(ctx android.RegistrationContext) {
|
||||
ctx.RegisterModuleType("device_config_definitions", DefinitionsFactory)
|
||||
ctx.RegisterModuleType("device_config_values", ValuesFactory)
|
||||
ctx.RegisterModuleType("device_config_value_set", ValueSetFactory)
|
||||
pctx.HostBinToolVariable("aconfig", "aconfig")
|
||||
pctx.HostBinToolVariable("soong_zip", "soong_zip")
|
||||
}
|
19
device_config/testing.go
Normal file
19
device_config/testing.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (C) 2021 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.
|
||||
|
||||
package device_config
|
||||
|
||||
import "android/soong/android"
|
||||
|
||||
var PrepareForTestWithSyspropBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
|
Reference in New Issue
Block a user