Merge changes from topic "lamont-build-tools-build-flag" into main

* changes:
  Bootstrap out/release-config early
  Add crunch-flags and build-flag binaries
  release_config: cleanup how we emit results
  Print a warning on redundant overrides
  Add description to release_config_map message
This commit is contained in:
Treehugger Robot 2024-04-19 00:57:39 +00:00 committed by Gerrit Code Review
commit d4ad78f447
18 changed files with 1060 additions and 138 deletions

View file

@ -0,0 +1,32 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
blueprint_go_binary {
name: "build-flag",
deps: [
"golang-protobuf-encoding-prototext",
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
"soong-cmd-release_config-proto",
"soong-cmd-release_config-lib",
],
srcs: [
"main.go",
],
}
bootstrap_go_package {
name: "soong-cmd-release_config-build_flag",
pkgPath: "android/soong/cmd/release_config/build_flag",
deps: [
"golang-protobuf-encoding-prototext",
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
"soong-cmd-release_config-proto",
"soong-cmd-release_config-lib",
],
srcs: [
"main.go",
],
}

View file

@ -0,0 +1,229 @@
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
rc_lib "android/soong/cmd/release_config/release_config_lib"
rc_proto "android/soong/cmd/release_config/release_config_proto"
"google.golang.org/protobuf/proto"
)
type Flags struct {
// The path to the top of the workspace. Default: ".".
top string
// Pathlist of release config map textproto files.
// If not specified, then the value is (if present):
// - build/release/release_config_map.textproto
// - vendor/google_shared/build/release/release_config_map.textproto
// - vendor/google/release/release_config_map.textproto
//
// Additionally, any maps specified in the environment variable
// `PRODUCT_RELEASE_CONFIG_MAPS` are used.
maps rc_lib.StringList
// Output directory (relative to `top`).
outDir string
// Which $TARGET_RELEASE(s) should we use. Some commands will only
// accept one value, others also accept `--release --all`.
targetReleases rc_lib.StringList
// Disable warning messages
quiet bool
}
type CommandFunc func(*rc_lib.ReleaseConfigs, Flags, string, []string) error
var commandMap map[string]CommandFunc = map[string]CommandFunc{
"get": GetCommand,
"set": SetCommand,
"trace": GetCommand, // Also handled by GetCommand
}
// Find the top of the release config contribution directory.
// Returns the parent of the flag_declarations and flag_values directories.
func GetMapDir(path string) (string, error) {
for p := path; p != "."; p = filepath.Dir(p) {
switch filepath.Base(p) {
case "flag_declarations":
return filepath.Dir(p), nil
case "flag_values":
return filepath.Dir(p), nil
}
}
return "", fmt.Errorf("Could not determine directory from %s", path)
}
func MarshalFlagValue(config *rc_lib.ReleaseConfig, name string) (ret string, err error) {
fa, ok := config.FlagArtifacts[name]
if !ok {
return "", fmt.Errorf("%s not found in %s", name, config.Name)
}
return rc_lib.MarshalValue(fa.Value), nil
}
func GetReleaseArgs(configs *rc_lib.ReleaseConfigs, commonFlags Flags) ([]*rc_lib.ReleaseConfig, error) {
var all bool
relFlags := flag.NewFlagSet("set", flag.ExitOnError)
relFlags.BoolVar(&all, "all", false, "Display all flags")
relFlags.Parse(commonFlags.targetReleases)
var ret []*rc_lib.ReleaseConfig
if all {
for _, config := range configs.ReleaseConfigs {
ret = append(ret, config)
}
return ret, nil
}
for _, arg := range relFlags.Args() {
config, err := configs.GetReleaseConfig(arg)
if err != nil {
return nil, err
}
ret = append(ret, config)
}
return ret, nil
}
func GetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, args []string) error {
isTrace := cmd == "trace"
var all bool
getFlags := flag.NewFlagSet("set", flag.ExitOnError)
getFlags.BoolVar(&all, "all", false, "Display all flags")
getFlags.Parse(args)
args = getFlags.Args()
releaseConfigList, err := GetReleaseArgs(configs, commonFlags)
if err != nil {
return err
}
if isTrace && len(releaseConfigList) > 1 {
return fmt.Errorf("trace command only allows one --release argument. Got: %s", strings.Join(commonFlags.targetReleases, " "))
}
if all {
args = []string{}
for _, fa := range configs.FlagArtifacts {
args = append(args, *fa.FlagDeclaration.Name)
}
}
showName := len(releaseConfigList) > 1 || len(args) > 1
for _, config := range releaseConfigList {
var configName string
if len(releaseConfigList) > 1 {
configName = fmt.Sprintf("%s.", config.Name)
}
for _, arg := range args {
val, err := MarshalFlagValue(config, arg)
if err != nil {
return err
}
if showName {
fmt.Printf("%s%s=%s\n", configName, arg, val)
} else {
fmt.Printf("%s\n", val)
}
if isTrace {
for _, trace := range config.FlagArtifacts[arg].Traces {
fmt.Printf(" => \"%s\" in %s\n", rc_lib.MarshalValue(trace.Value), *trace.Source)
}
}
}
}
return nil
}
func SetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, args []string) error {
var valueDir string
if len(commonFlags.targetReleases) > 1 {
return fmt.Errorf("set command only allows one --release argument. Got: %s", strings.Join(commonFlags.targetReleases, " "))
}
targetRelease := commonFlags.targetReleases[0]
setFlags := flag.NewFlagSet("set", flag.ExitOnError)
setFlags.StringVar(&valueDir, "dir", "", "Directory in which to place the value")
setFlags.Parse(args)
setArgs := setFlags.Args()
if len(setArgs) != 2 {
return fmt.Errorf("set command expected flag and value, got: %s", strings.Join(setArgs, " "))
}
name := setArgs[0]
value := setArgs[1]
release, err := configs.GetReleaseConfig(targetRelease)
targetRelease = release.Name
if err != nil {
return err
}
flagArtifact, ok := release.FlagArtifacts[name]
if !ok {
return fmt.Errorf("Unknown build flag %s", name)
}
if valueDir == "" {
mapDir, err := GetMapDir(*flagArtifact.Traces[len(flagArtifact.Traces)-1].Source)
if err != nil {
return err
}
valueDir = mapDir
}
flagValue := &rc_proto.FlagValue{
Name: proto.String(name),
Value: rc_lib.UnmarshalValue(value),
}
flagPath := filepath.Join(valueDir, "flag_values", targetRelease, fmt.Sprintf("%s.textproto", name))
return rc_lib.WriteMessage(flagPath, flagValue)
}
func main() {
var err error
var commonFlags Flags
var configs *rc_lib.ReleaseConfigs
outEnv := os.Getenv("OUT_DIR")
if outEnv == "" {
outEnv = "out"
}
// Handle the common arguments
flag.StringVar(&commonFlags.top, "top", ".", "path to top of workspace")
flag.BoolVar(&commonFlags.quiet, "quiet", false, "disable warning messages")
flag.Var(&commonFlags.maps, "map", "path to a release_config_map.textproto. may be repeated")
flag.StringVar(&commonFlags.outDir, "out_dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created")
flag.Var(&commonFlags.targetReleases, "release", "TARGET_RELEASE for this build")
flag.Parse()
if commonFlags.quiet {
rc_lib.DisableWarnings()
}
if len(commonFlags.targetReleases) == 0 {
commonFlags.targetReleases = rc_lib.StringList{"trunk_staging"}
}
if err = os.Chdir(commonFlags.top); err != nil {
panic(err)
}
// Get the current state of flagging.
relName := commonFlags.targetReleases[0]
if relName == "--all" || relName == "-all" {
// If the users said `--release --all`, grab trunk staging for simplicity.
relName = "trunk_staging"
}
configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, relName)
if err != nil {
panic(err)
}
if cmd, ok := commandMap[flag.Arg(0)]; ok {
args := flag.Args()
if err = cmd(configs, commonFlags, args[0], args[1:]); err != nil {
panic(err)
}
}
}

View file

@ -0,0 +1,32 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
blueprint_go_binary {
name: "crunch-flags",
deps: [
"golang-protobuf-encoding-prototext",
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
"soong-cmd-release_config-lib",
"soong-cmd-release_config-proto",
],
srcs: [
"main.go",
],
}
bootstrap_go_package {
name: "soong-cmd-release_config-crunch_flags",
pkgPath: "android/soong/cmd/release_config/crunch_flags",
deps: [
"golang-protobuf-encoding-prototext",
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
"soong-cmd-release_config-lib",
"soong-cmd-release_config-proto",
],
srcs: [
"main.go",
],
}

View file

@ -0,0 +1,359 @@
package main
import (
"flag"
"fmt"
"io/fs"
"os"
"path/filepath"
"regexp"
"strings"
rc_lib "android/soong/cmd/release_config/release_config_lib"
rc_proto "android/soong/cmd/release_config/release_config_proto"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
)
// When a flag declaration has an initial value that is a string, the default workflow is PREBUILT.
// If the flag name starts with any of prefixes in manualFlagNamePrefixes, it is MANUAL.
var manualFlagNamePrefixes []string = []string{
"RELEASE_ACONFIG_",
"RELEASE_PLATFORM_",
}
var defaultFlagNamespace string = "android_UNKNOWN"
func RenameNext(name string) string {
if name == "next" {
return "ap3a"
}
return name
}
func WriteFile(path string, message proto.Message) error {
data, err := prototext.MarshalOptions{Multiline: true}.Marshal(message)
if err != nil {
return err
}
err = os.MkdirAll(filepath.Dir(path), 0775)
if err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}
func WalkValueFiles(dir string, Func fs.WalkDirFunc) error {
valPath := filepath.Join(dir, "build_config")
if _, err := os.Stat(valPath); err != nil {
fmt.Printf("%s not found, ignoring.\n", valPath)
return nil
}
return filepath.WalkDir(valPath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if strings.HasSuffix(d.Name(), ".scl") && d.Type().IsRegular() {
return Func(path, d, err)
}
return nil
})
}
func ProcessBuildFlags(dir string, namespaceMap map[string]string) error {
var rootAconfigModule string
path := filepath.Join(dir, "build_flags.scl")
if _, err := os.Stat(path); err != nil {
fmt.Printf("%s not found, ignoring.\n", path)
return nil
} else {
fmt.Printf("Processing %s\n", path)
}
commentRegexp, err := regexp.Compile("^[[:space:]]*#(?<comment>.+)")
if err != nil {
return err
}
declRegexp, err := regexp.Compile("^[[:space:]]*flag.\"(?<name>[A-Z_0-9]+)\",[[:space:]]*(?<container>[_A-Z]*),[[:space:]]*(?<value>(\"[^\"]*\"|[^\",)]*))")
if err != nil {
return err
}
declIn, err := os.ReadFile(path)
if err != nil {
return err
}
lines := strings.Split(string(declIn), "\n")
var description string
for _, line := range lines {
if comment := commentRegexp.FindStringSubmatch(commentRegexp.FindString(line)); comment != nil {
// Description is the text from any contiguous series of lines before a `flag()` call.
description += fmt.Sprintf(" %s", strings.TrimSpace(comment[commentRegexp.SubexpIndex("comment")]))
continue
}
matches := declRegexp.FindStringSubmatch(declRegexp.FindString(line))
if matches == nil {
// The line is neither a comment nor a `flag()` call.
// Discard any description we have gathered and process the next line.
description = ""
continue
}
declValue := matches[declRegexp.SubexpIndex("value")]
declName := matches[declRegexp.SubexpIndex("name")]
container := rc_proto.Container(rc_proto.Container_value[matches[declRegexp.SubexpIndex("container")]])
description = strings.TrimSpace(description)
var namespace string
var ok bool
if namespace, ok = namespaceMap[declName]; !ok {
namespace = defaultFlagNamespace
}
flagDeclaration := &rc_proto.FlagDeclaration{
Name: proto.String(declName),
Namespace: proto.String(namespace),
Description: proto.String(description),
Container: &container,
}
description = ""
// Most build flags are `workflow: PREBUILT`.
workflow := rc_proto.Workflow(rc_proto.Workflow_PREBUILT)
switch {
case declName == "RELEASE_ACONFIG_VALUE_SETS":
rootAconfigModule = declValue[1 : len(declValue)-1]
continue
case strings.HasPrefix(declValue, "\""):
// String values mean that the flag workflow is (most likely) either MANUAL or PREBUILT.
declValue = declValue[1 : len(declValue)-1]
flagDeclaration.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{declValue}}
for _, prefix := range manualFlagNamePrefixes {
if strings.HasPrefix(declName, prefix) {
workflow = rc_proto.Workflow(rc_proto.Workflow_MANUAL)
break
}
}
case declValue == "False" || declValue == "True":
// Boolean values are LAUNCH flags.
flagDeclaration.Value = &rc_proto.Value{Val: &rc_proto.Value_BoolValue{declValue == "True"}}
workflow = rc_proto.Workflow(rc_proto.Workflow_LAUNCH)
case declValue == "None":
// Use PREBUILT workflow with no initial value.
default:
fmt.Printf("%s: Unexpected value %s=%s\n", path, declName, declValue)
}
flagDeclaration.Workflow = &workflow
if flagDeclaration != nil {
declPath := filepath.Join(dir, "flag_declarations", fmt.Sprintf("%s.textproto", declName))
err := WriteFile(declPath, flagDeclaration)
if err != nil {
return err
}
}
}
if rootAconfigModule != "" {
rootProto := &rc_proto.ReleaseConfig{
Name: proto.String("root"),
AconfigValueSets: []string{rootAconfigModule},
}
return WriteFile(filepath.Join(dir, "release_configs", "root.textproto"), rootProto)
}
return nil
}
func ProcessBuildConfigs(dir, name string, paths []string, releaseProto *rc_proto.ReleaseConfig) error {
valRegexp, err := regexp.Compile("[[:space:]]+value.\"(?<name>[A-Z_0-9]+)\",[[:space:]]*(?<value>[^,)]*)")
if err != nil {
return err
}
for _, path := range paths {
fmt.Printf("Processing %s\n", path)
valIn, err := os.ReadFile(path)
if err != nil {
fmt.Printf("%s: error: %v\n", path, err)
return err
}
vals := valRegexp.FindAllString(string(valIn), -1)
for _, val := range vals {
matches := valRegexp.FindStringSubmatch(val)
valValue := matches[valRegexp.SubexpIndex("value")]
valName := matches[valRegexp.SubexpIndex("name")]
flagValue := &rc_proto.FlagValue{
Name: proto.String(valName),
}
switch {
case valName == "RELEASE_ACONFIG_VALUE_SETS":
flagValue = nil
if releaseProto.AconfigValueSets == nil {
releaseProto.AconfigValueSets = []string{}
}
releaseProto.AconfigValueSets = append(releaseProto.AconfigValueSets, valValue[1:len(valValue)-1])
case strings.HasPrefix(valValue, "\""):
valValue = valValue[1 : len(valValue)-1]
flagValue.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{valValue}}
case valValue == "None":
// nothing to do here.
case valValue == "True":
flagValue.Value = &rc_proto.Value{Val: &rc_proto.Value_BoolValue{true}}
case valValue == "False":
flagValue.Value = &rc_proto.Value{Val: &rc_proto.Value_BoolValue{false}}
default:
fmt.Printf("%s: Unexpected value %s=%s\n", path, valName, valValue)
}
if flagValue != nil {
valPath := filepath.Join(dir, "flag_values", RenameNext(name), fmt.Sprintf("%s.textproto", valName))
err := WriteFile(valPath, flagValue)
if err != nil {
return err
}
}
}
}
return err
}
func ProcessReleaseConfigMap(dir string, descriptionMap map[string]string) error {
path := filepath.Join(dir, "release_config_map.mk")
if _, err := os.Stat(path); err != nil {
fmt.Printf("%s not found, ignoring.\n", path)
return nil
} else {
fmt.Printf("Processing %s\n", path)
}
configRegexp, err := regexp.Compile("^..call[[:space:]]+declare-release-config,[[:space:]]+(?<name>[_a-z0-0A-Z]+),[[:space:]]+(?<files>[^,]*)(,[[:space:]]*(?<inherits>.*)|[[:space:]]*)[)]$")
if err != nil {
return err
}
aliasRegexp, err := regexp.Compile("^..call[[:space:]]+alias-release-config,[[:space:]]+(?<name>[_a-z0-9A-Z]+),[[:space:]]+(?<target>[_a-z0-9A-Z]+)")
if err != nil {
return err
}
mapIn, err := os.ReadFile(path)
if err != nil {
return err
}
cleanDir := strings.TrimLeft(dir, "../")
var defaultContainer rc_proto.Container
switch {
case strings.HasPrefix(cleanDir, "build/") || cleanDir == "vendor/google_shared/build":
defaultContainer = rc_proto.Container(rc_proto.Container_ALL)
case cleanDir == "vendor/google/release":
defaultContainer = rc_proto.Container(rc_proto.Container_ALL)
default:
defaultContainer = rc_proto.Container(rc_proto.Container_VENDOR)
}
releaseConfigMap := &rc_proto.ReleaseConfigMap{DefaultContainer: &defaultContainer}
// If we find a description for the directory, include it.
if description, ok := descriptionMap[cleanDir]; ok {
releaseConfigMap.Description = proto.String(description)
}
lines := strings.Split(string(mapIn), "\n")
for _, line := range lines {
alias := aliasRegexp.FindStringSubmatch(aliasRegexp.FindString(line))
if alias != nil {
fmt.Printf("processing alias %s\n", line)
name := alias[aliasRegexp.SubexpIndex("name")]
target := alias[aliasRegexp.SubexpIndex("target")]
if target == "next" {
if RenameNext(target) != name {
return fmt.Errorf("Unexpected name for next (%s)", RenameNext(target))
}
target, name = name, target
}
releaseConfigMap.Aliases = append(releaseConfigMap.Aliases,
&rc_proto.ReleaseAlias{
Name: proto.String(name),
Target: proto.String(target),
})
}
config := configRegexp.FindStringSubmatch(configRegexp.FindString(line))
if config == nil {
continue
}
name := config[configRegexp.SubexpIndex("name")]
releaseConfig := &rc_proto.ReleaseConfig{
Name: proto.String(RenameNext(name)),
}
configFiles := config[configRegexp.SubexpIndex("files")]
files := strings.Split(strings.ReplaceAll(configFiles, "$(local_dir)", dir+"/"), " ")
configInherits := config[configRegexp.SubexpIndex("inherits")]
if len(configInherits) > 0 {
releaseConfig.Inherits = strings.Split(configInherits, " ")
}
err := ProcessBuildConfigs(dir, name, files, releaseConfig)
if err != nil {
return err
}
releasePath := filepath.Join(dir, "release_configs", fmt.Sprintf("%s.textproto", RenameNext(name)))
err = WriteFile(releasePath, releaseConfig)
if err != nil {
return err
}
}
return WriteFile(filepath.Join(dir, "release_config_map.textproto"), releaseConfigMap)
}
func main() {
var err error
var top string
var dirs rc_lib.StringList
var namespacesFile string
var descriptionsFile string
flag.StringVar(&top, "top", ".", "path to top of workspace")
flag.Var(&dirs, "dir", "directory to process, relative to the top of the workspace")
flag.StringVar(&namespacesFile, "namespaces", "", "location of file with 'flag_name namespace' information")
flag.StringVar(&descriptionsFile, "descriptions", "", "location of file with 'directory description' information")
flag.Parse()
if err = os.Chdir(top); err != nil {
panic(err)
}
if len(dirs) == 0 {
dirs = rc_lib.StringList{"build/release", "vendor/google_shared/build/release", "vendor/google/release"}
}
namespaceMap := make(map[string]string)
if namespacesFile != "" {
data, err := os.ReadFile(namespacesFile)
if err != nil {
panic(err)
}
for idx, line := range strings.Split(string(data), "\n") {
fields := strings.Split(line, " ")
if len(fields) > 2 {
panic(fmt.Errorf("line %d: too many fields: %s", idx, line))
}
namespaceMap[fields[0]] = fields[1]
}
}
descriptionMap := make(map[string]string)
descriptionMap["build/release"] = "Published open-source flags and declarations"
if descriptionsFile != "" {
data, err := os.ReadFile(descriptionsFile)
if err != nil {
panic(err)
}
for _, line := range strings.Split(string(data), "\n") {
if strings.TrimSpace(line) != "" {
fields := strings.SplitN(line, " ", 2)
descriptionMap[fields[0]] = fields[1]
}
}
}
for _, dir := range dirs {
err = ProcessBuildFlags(dir, namespaceMap)
if err != nil {
panic(err)
}
err = ProcessReleaseConfigMap(dir, descriptionMap)
if err != nil {
panic(err)
}
}
}

View file

@ -16,25 +16,44 @@ package main
import (
"flag"
"fmt"
"os"
"path/filepath"
rc_lib "android/soong/cmd/release_config/release_config_lib"
)
func main() {
var top string
var quiet bool
var releaseConfigMapPaths rc_lib.StringList
var targetRelease string
var outputDir string
var err error
var configs *rc_lib.ReleaseConfigs
var json, pb, textproto bool
var product string
defaultRelease := os.Getenv("TARGET_RELEASE")
if defaultRelease == "" {
defaultRelease = "trunk_staging"
}
flag.StringVar(&top, "top", ".", "path to top of workspace")
flag.StringVar(&product, "product", os.Getenv("TARGET_PRODUCT"), "TARGET_PRODUCT for the build")
flag.BoolVar(&quiet, "quiet", false, "disable warning messages")
flag.Var(&releaseConfigMapPaths, "map", "path to a release_config_map.textproto. may be repeated")
flag.StringVar(&targetRelease, "release", "trunk_staging", "TARGET_RELEASE for this build")
flag.StringVar(&targetRelease, "release", defaultRelease, "TARGET_RELEASE for this build")
flag.StringVar(&outputDir, "out_dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created")
flag.BoolVar(&textproto, "textproto", true, "write artifacts as text protobuf")
flag.BoolVar(&json, "json", true, "write artifacts as json")
flag.BoolVar(&pb, "pb", true, "write artifacts as binary protobuf")
flag.Parse()
if quiet {
rc_lib.DisableWarnings()
}
if err = os.Chdir(top); err != nil {
panic(err)
}
@ -42,16 +61,36 @@ func main() {
if err != nil {
panic(err)
}
config, err := configs.GetReleaseConfig(targetRelease)
if err != nil {
panic(err)
}
releaseName := config.Name
err = os.MkdirAll(outputDir, 0775)
if err != nil {
panic(err)
}
err = configs.DumpMakefile(outputDir, targetRelease)
makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, releaseName))
err = configs.WriteMakefile(makefilePath, targetRelease)
if err != nil {
panic(err)
}
err = configs.DumpArtifact(outputDir)
if err != nil {
panic(err)
if json {
err = configs.WriteArtifact(outputDir, product, "json")
if err != nil {
panic(err)
}
}
if pb {
err = configs.WriteArtifact(outputDir, product, "pb")
if err != nil {
panic(err)
}
}
if textproto {
err = configs.WriteArtifact(outputDir, product, "textproto")
if err != nil {
panic(err)
}
}
}

View file

@ -18,7 +18,7 @@ package {
bootstrap_go_package {
name: "soong-cmd-release_config-lib",
pkgPath: "android/soong/release_config/release_config_lib",
pkgPath: "android/soong/cmd/release_config/release_config_lib",
deps: [
"golang-protobuf-encoding-prototext",
"golang-protobuf-reflect-protoreflect",

View file

@ -17,29 +17,37 @@ package release_config_lib
import (
"fmt"
"android/soong/cmd/release_config/release_config_proto"
rc_proto "android/soong/cmd/release_config/release_config_proto"
"google.golang.org/protobuf/proto"
)
// A flag artifact, with its final value and declaration/override history.
type FlagArtifact struct {
FlagDeclaration *release_config_proto.FlagDeclaration
// The flag_declaration message.
FlagDeclaration *rc_proto.FlagDeclaration
// The index of the config directory where this flag was declared.
// Flag values cannot be set in a location with a lower index.
DeclarationIndex int
Traces []*release_config_proto.Tracepoint
// A history of value assignments and overrides.
Traces []*rc_proto.Tracepoint
// Assigned value
Value *release_config_proto.Value
// The value of the flag.
Value *rc_proto.Value
}
// Key is flag name.
type FlagArtifacts map[string]*FlagArtifact
// Create a clone of the flag artifact.
//
// Returns:
//
// *FlagArtifact: the copy of the artifact.
func (src *FlagArtifact) Clone() *FlagArtifact {
value := &release_config_proto.Value{}
value := &rc_proto.Value{}
proto.Merge(value, src.Value)
return &FlagArtifact{
FlagDeclaration: src.FlagDeclaration,
@ -48,6 +56,11 @@ func (src *FlagArtifact) Clone() *FlagArtifact {
}
}
// Clone FlagArtifacts.
//
// Returns:
//
// FlagArtifacts: a copy of the source FlagArtifacts.
func (src FlagArtifacts) Clone() (dst FlagArtifacts) {
if dst == nil {
dst = make(FlagArtifacts)
@ -58,30 +71,47 @@ func (src FlagArtifacts) Clone() (dst FlagArtifacts) {
return
}
// Update the value of a flag.
//
// This appends to flagArtifact.Traces, and updates flagArtifact.Value.
//
// Args:
//
// flagValue FlagValue: the value to assign
//
// Returns:
//
// error: any error encountered
func (fa *FlagArtifact) UpdateValue(flagValue FlagValue) error {
name := *flagValue.proto.Name
fa.Traces = append(fa.Traces, &release_config_proto.Tracepoint{Source: proto.String(flagValue.path), Value: flagValue.proto.Value})
fa.Traces = append(fa.Traces, &rc_proto.Tracepoint{Source: proto.String(flagValue.path), Value: flagValue.proto.Value})
if fa.Value.GetObsolete() {
return fmt.Errorf("Attempting to set obsolete flag %s. Trace=%v", name, fa.Traces)
}
var newValue *rc_proto.Value
switch val := flagValue.proto.Value.Val.(type) {
case *release_config_proto.Value_StringValue:
fa.Value = &release_config_proto.Value{Val: &release_config_proto.Value_StringValue{val.StringValue}}
case *release_config_proto.Value_BoolValue:
fa.Value = &release_config_proto.Value{Val: &release_config_proto.Value_BoolValue{val.BoolValue}}
case *release_config_proto.Value_Obsolete:
case *rc_proto.Value_StringValue:
newValue = &rc_proto.Value{Val: &rc_proto.Value_StringValue{val.StringValue}}
case *rc_proto.Value_BoolValue:
newValue = &rc_proto.Value{Val: &rc_proto.Value_BoolValue{val.BoolValue}}
case *rc_proto.Value_Obsolete:
if !val.Obsolete {
return fmt.Errorf("%s: Cannot set obsolete=false. Trace=%v", name, fa.Traces)
}
fa.Value = &release_config_proto.Value{Val: &release_config_proto.Value_Obsolete{true}}
newValue = &rc_proto.Value{Val: &rc_proto.Value_Obsolete{true}}
default:
return fmt.Errorf("Invalid type for flag_value: %T. Trace=%v", val, fa.Traces)
}
if proto.Equal(newValue, fa.Value) {
warnf("%s: redundant override (set in %s)\n", flagValue.path, *fa.Traces[len(fa.Traces)-2].Source)
}
fa.Value = newValue
return nil
}
func (fa *FlagArtifact) Marshal() (*release_config_proto.FlagArtifact, error) {
return &release_config_proto.FlagArtifact{
// Marshal the FlagArtifact into a flag_artifact message.
func (fa *FlagArtifact) Marshal() (*rc_proto.FlagArtifact, error) {
return &rc_proto.FlagArtifact{
FlagDeclaration: fa.FlagDeclaration,
Value: fa.Value,
Traces: fa.Traces,

View file

@ -15,13 +15,13 @@
package release_config_lib
import (
"android/soong/cmd/release_config/release_config_proto"
rc_proto "android/soong/cmd/release_config/release_config_proto"
)
func FlagDeclarationFactory(protoPath string) (fd *release_config_proto.FlagDeclaration) {
fd = &release_config_proto.FlagDeclaration{}
func FlagDeclarationFactory(protoPath string) (fd *rc_proto.FlagDeclaration) {
fd = &rc_proto.FlagDeclaration{}
if protoPath != "" {
LoadTextproto(protoPath, fd)
LoadMessage(protoPath, fd)
}
return fd
}

View file

@ -15,7 +15,9 @@
package release_config_lib
import (
"android/soong/cmd/release_config/release_config_proto"
"strings"
rc_proto "android/soong/cmd/release_config/release_config_proto"
)
type FlagValue struct {
@ -23,31 +25,46 @@ type FlagValue struct {
path string
// Protobuf
proto release_config_proto.FlagValue
proto rc_proto.FlagValue
}
func FlagValueFactory(protoPath string) (fv *FlagValue) {
fv = &FlagValue{path: protoPath}
if protoPath != "" {
LoadTextproto(protoPath, &fv.proto)
LoadMessage(protoPath, &fv.proto)
}
return fv
}
func MarshalValue(value *release_config_proto.Value) string {
func UnmarshalValue(str string) *rc_proto.Value {
ret := &rc_proto.Value{}
switch v := strings.ToLower(str); v {
case "true":
ret = &rc_proto.Value{Val: &rc_proto.Value_BoolValue{true}}
case "false":
ret = &rc_proto.Value{Val: &rc_proto.Value_BoolValue{false}}
case "##obsolete":
ret = &rc_proto.Value{Val: &rc_proto.Value_Obsolete{true}}
default:
ret = &rc_proto.Value{Val: &rc_proto.Value_StringValue{str}}
}
return ret
}
func MarshalValue(value *rc_proto.Value) string {
switch val := value.Val.(type) {
case *release_config_proto.Value_UnspecifiedValue:
case *rc_proto.Value_UnspecifiedValue:
// Value was never set.
return ""
case *release_config_proto.Value_StringValue:
case *rc_proto.Value_StringValue:
return val.StringValue
case *release_config_proto.Value_BoolValue:
case *rc_proto.Value_BoolValue:
if val.BoolValue {
return "true"
}
// False ==> empty string
return ""
case *release_config_proto.Value_Obsolete:
case *rc_proto.Value_Obsolete:
return " #OBSOLETE"
default:
// Flagged as error elsewhere, so return empty string here.

View file

@ -16,8 +16,9 @@ package release_config_lib
import (
"fmt"
"strings"
"android/soong/cmd/release_config/release_config_proto"
rc_proto "android/soong/cmd/release_config/release_config_proto"
"google.golang.org/protobuf/proto"
)
@ -33,7 +34,7 @@ type ReleaseConfigContribution struct {
DeclarationIndex int
// Protobufs relevant to the config.
proto release_config_proto.ReleaseConfig
proto rc_proto.ReleaseConfig
FlagValues []*FlagValue
}
@ -61,7 +62,7 @@ type ReleaseConfig struct {
FlagArtifacts FlagArtifacts
// Generated release config
ReleaseConfigArtifact *release_config_proto.ReleaseConfigArtifact
ReleaseConfigArtifact *rc_proto.ReleaseConfigArtifact
// We have begun compiling this release config.
compileInProgress bool
@ -79,12 +80,18 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
return fmt.Errorf("Loop detected for release config %s", config.Name)
}
config.compileInProgress = true
isRoot := config.Name == "root"
// Generate any configs we need to inherit. This will detect loops in
// the config.
contributionsToApply := []*ReleaseConfigContribution{}
myInherits := []string{}
myInheritsSet := make(map[string]bool)
// If there is a "root" release config, it is the start of every inheritance chain.
_, err := configs.GetReleaseConfig("root")
if err == nil && !isRoot {
config.InheritNames = append([]string{"root"}, config.InheritNames...)
}
for _, inherit := range config.InheritNames {
if _, ok := myInheritsSet[inherit]; ok {
continue
@ -101,10 +108,46 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
contributionsToApply = append(contributionsToApply, config.Contributions...)
myAconfigValueSets := []string{}
myAconfigValueSetsMap := map[string]bool{}
myFlags := configs.FlagArtifacts.Clone()
workflowManual := rc_proto.Workflow(rc_proto.Workflow_MANUAL)
container := rc_proto.Container(rc_proto.Container_ALL)
releaseAconfigValueSets := FlagArtifact{
FlagDeclaration: &rc_proto.FlagDeclaration{
Name: proto.String("RELEASE_ACONFIG_VALUE_SETS"),
Namespace: proto.String("android_UNKNOWN"),
Description: proto.String("Aconfig value sets assembled by release-config"),
Workflow: &workflowManual,
Container: &container,
Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{""}},
},
DeclarationIndex: -1,
Traces: []*rc_proto.Tracepoint{
&rc_proto.Tracepoint{
Source: proto.String("$release-config"),
Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{""}},
},
},
}
myFlags["RELEASE_ACONFIG_VALUE_SETS"] = &releaseAconfigValueSets
myDirsMap := make(map[int]bool)
for _, contrib := range contributionsToApply {
myAconfigValueSets = append(myAconfigValueSets, contrib.proto.AconfigValueSets...)
if len(contrib.proto.AconfigValueSets) > 0 {
contribAconfigValueSets := []string{}
for _, v := range contrib.proto.AconfigValueSets {
if _, ok := myAconfigValueSetsMap[v]; !ok {
contribAconfigValueSets = append(contribAconfigValueSets, v)
myAconfigValueSetsMap[v] = true
}
}
myAconfigValueSets = append(myAconfigValueSets, contribAconfigValueSets...)
releaseAconfigValueSets.Traces = append(
releaseAconfigValueSets.Traces,
&rc_proto.Tracepoint{
Source: proto.String(contrib.path),
Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.Join(contribAconfigValueSets, " ")}},
})
}
myDirsMap[contrib.DeclarationIndex] = true
for _, value := range contrib.FlagValues {
fa, ok := myFlags[*value.proto.Name]
@ -116,27 +159,32 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
// Setting location is to the left of declaration.
return fmt.Errorf("Setting value for flag %s not allowed in %s\n", *value.proto.Name, value.path)
}
if isRoot && *fa.FlagDeclaration.Workflow != workflowManual {
// The "root" release config can only contain workflow: MANUAL flags.
return fmt.Errorf("Setting value for non-MANUAL flag %s is not allowed in %s", *value.proto.Name, value.path)
}
if err := fa.UpdateValue(*value); err != nil {
return err
}
}
}
releaseAconfigValueSets.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.Join(myAconfigValueSets, " ")}}
directories := []string{}
for idx, confDir := range configs.ConfigDirs {
for idx, confDir := range configs.configDirs {
if _, ok := myDirsMap[idx]; ok {
directories = append(directories, confDir)
}
}
config.FlagArtifacts = myFlags
config.ReleaseConfigArtifact = &release_config_proto.ReleaseConfigArtifact{
config.ReleaseConfigArtifact = &rc_proto.ReleaseConfigArtifact{
Name: proto.String(config.Name),
OtherNames: config.OtherNames,
FlagArtifacts: func() []*release_config_proto.FlagArtifact {
ret := []*release_config_proto.FlagArtifact{}
FlagArtifacts: func() []*rc_proto.FlagArtifact {
ret := []*rc_proto.FlagArtifact{}
for _, flag := range myFlags {
ret = append(ret, &release_config_proto.FlagArtifact{
ret = append(ret, &rc_proto.FlagArtifact{
FlagDeclaration: flag.FlagDeclaration,
Traces: flag.Traces,
Value: flag.Value,

View file

@ -16,7 +16,6 @@ package release_config_lib
import (
"cmp"
"encoding/json"
"fmt"
"io/fs"
"os"
@ -24,9 +23,8 @@ import (
"slices"
"strings"
"android/soong/cmd/release_config/release_config_proto"
rc_proto "android/soong/cmd/release_config/release_config_proto"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
)
@ -37,10 +35,13 @@ type ReleaseConfigMap struct {
path string
// Data received
proto release_config_proto.ReleaseConfigMap
proto rc_proto.ReleaseConfigMap
// Map of name:contribution for release config contributions.
ReleaseConfigContributions map[string]*ReleaseConfigContribution
FlagDeclarations []release_config_proto.FlagDeclaration
// Flags declared this directory's flag_declarations/*.textproto
FlagDeclarations []rc_proto.FlagDeclaration
}
type ReleaseConfigDirMap map[string]int
@ -56,50 +57,51 @@ type ReleaseConfigs struct {
// Dictionary of flag_name:FlagDeclaration, with no overrides applied.
FlagArtifacts FlagArtifacts
// Generated release configs artifact
Artifact rc_proto.ReleaseConfigsArtifact
// Dictionary of name:ReleaseConfig
// Use `GetReleaseConfigs(name)` to get a release config.
ReleaseConfigs map[string]*ReleaseConfig
// Generated release configs
Artifact release_config_proto.ReleaseConfigsArtifact
// Map of directory to *ReleaseConfigMap
releaseConfigMapsMap map[string]*ReleaseConfigMap
// The list of config directories used.
ConfigDirs []string
configDirs []string
// A map from the config directory to its order in the list of config
// directories.
ConfigDirIndexes ReleaseConfigDirMap
configDirIndexes ReleaseConfigDirMap
}
func (configs *ReleaseConfigs) DumpArtifact(outDir string) error {
message := &configs.Artifact
basePath := filepath.Join(outDir, "all_release_configs")
writer := func(suffix string, marshal func() ([]byte, error)) error {
data, err := marshal()
if err != nil {
return err
}
return os.WriteFile(fmt.Sprintf("%s.%s", basePath, suffix), data, 0644)
}
err := writer("textproto", func() ([]byte, error) { return prototext.MarshalOptions{Multiline: true}.Marshal(message) })
if err != nil {
return err
}
err = writer("pb", func() ([]byte, error) { return proto.Marshal(message) })
if err != nil {
return err
}
return writer("json", func() ([]byte, error) { return json.MarshalIndent(message, "", " ") })
// Write the "all_release_configs" artifact.
//
// The file will be in "{outDir}/all_release_configs-{product}.{format}"
//
// Args:
//
// outDir string: directory path. Will be created if not present.
// product string: TARGET_PRODUCT for the release_configs.
// format string: one of "json", "pb", or "textproto"
//
// Returns:
//
// error: Any error encountered.
func (configs *ReleaseConfigs) WriteArtifact(outDir, product, format string) error {
return WriteMessage(
filepath.Join(outDir, fmt.Sprintf("all_release_configs-%s.%s", product, format)),
&configs.Artifact)
}
func ReleaseConfigsFactory() (c *ReleaseConfigs) {
return &ReleaseConfigs{
Aliases: make(map[string]*string),
FlagArtifacts: make(map[string]*FlagArtifact),
ReleaseConfigs: make(map[string]*ReleaseConfig),
ConfigDirs: []string{},
ConfigDirIndexes: make(ReleaseConfigDirMap),
Aliases: make(map[string]*string),
FlagArtifacts: make(map[string]*FlagArtifact),
ReleaseConfigs: make(map[string]*ReleaseConfig),
releaseConfigMapsMap: make(map[string]*ReleaseConfigMap),
configDirs: []string{},
configDirIndexes: make(ReleaseConfigDirMap),
}
}
@ -109,7 +111,7 @@ func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) {
ReleaseConfigContributions: make(map[string]*ReleaseConfigContribution),
}
if protoPath != "" {
LoadTextproto(protoPath, &m.proto)
LoadMessage(protoPath, &m.proto)
}
return m
}
@ -145,7 +147,7 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
}
// If the input didn't specify a value, create one (== UnspecifiedValue).
if flagDeclaration.Value == nil {
flagDeclaration.Value = &release_config_proto.Value{Val: &release_config_proto.Value_UnspecifiedValue{false}}
flagDeclaration.Value = &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}}
}
m.FlagDeclarations = append(m.FlagDeclarations, *flagDeclaration)
name := *flagDeclaration.Name
@ -156,7 +158,7 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
}
// Set the initial value in the flag artifact.
configs.FlagArtifacts[name].UpdateValue(
FlagValue{path: path, proto: release_config_proto.FlagValue{
FlagValue{path: path, proto: rc_proto.FlagValue{
Name: proto.String(name), Value: flagDeclaration.Value}})
return nil
})
@ -166,7 +168,7 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
err = WalkTextprotoFiles(dir, "release_configs", func(path string, d fs.DirEntry, err error) error {
releaseConfigContribution := &ReleaseConfigContribution{path: path, DeclarationIndex: ConfigDirIndex}
LoadTextproto(path, &releaseConfigContribution.proto)
LoadMessage(path, &releaseConfigContribution.proto)
name := *releaseConfigContribution.proto.Name
if fmt.Sprintf("%s.textproto", name) != filepath.Base(path) {
return fmt.Errorf("%s incorrectly declares release config %s", path, name)
@ -197,6 +199,7 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex
return err
}
configs.ReleaseConfigMaps = append(configs.ReleaseConfigMaps, m)
configs.releaseConfigMapsMap[dir] = m
return nil
}
@ -212,16 +215,23 @@ func (configs *ReleaseConfigs) GetReleaseConfig(name string) (*ReleaseConfig, er
return nil, fmt.Errorf("Missing config %s. Trace=%v", name, trace)
}
func (configs *ReleaseConfigs) DumpMakefile(outDir, targetRelease string) error {
outFile := filepath.Join(outDir, "release_config.mk")
// Write the makefile for this targetRelease.
func (configs *ReleaseConfigs) WriteMakefile(outFile, targetRelease string) error {
makeVars := make(map[string]string)
var allReleaseNames []string
for _, v := range configs.ReleaseConfigs {
allReleaseNames = append(allReleaseNames, v.Name)
allReleaseNames = append(allReleaseNames, v.OtherNames...)
}
config, err := configs.GetReleaseConfig(targetRelease)
if err != nil {
return err
}
myFlagArtifacts := config.FlagArtifacts.Clone()
// Sort the flags by name first.
names := []string{}
for k, _ := range config.FlagArtifacts {
for k, _ := range myFlagArtifacts {
names = append(names, k)
}
slices.SortFunc(names, func(a, b string) int {
@ -237,12 +247,12 @@ func (configs *ReleaseConfigs) DumpMakefile(outDir, targetRelease string) error
}
for _, name := range names {
flag := config.FlagArtifacts[name]
flag := myFlagArtifacts[name]
decl := flag.FlagDeclaration
// cName := strings.ToLower(release_config_proto.Container_name[decl.GetContainer()])
// cName := strings.ToLower(rc_proto.Container_name[decl.GetContainer()])
cName := strings.ToLower(decl.Container.String())
if cName == strings.ToLower(release_config_proto.Container_ALL.String()) {
if cName == strings.ToLower(rc_proto.Container_ALL.String()) {
partitions["product"] = append(partitions["product"], name)
partitions["system"] = append(partitions["system"], name)
partitions["system_ext"] = append(partitions["system_ext"], name)
@ -277,7 +287,13 @@ func (configs *ReleaseConfigs) DumpMakefile(outDir, targetRelease string) error
// _ALL_RELEASE_FLAGS.PARTITIONS.*
// all _ALL_RELEASE_FLAGS.*, sorted by name
// Final flag values, sorted by name.
data := fmt.Sprintf("_ALL_RELEASE_FLAGS :=$= %s\n", strings.Join(names, " "))
data := fmt.Sprintf("# TARGET_RELEASE=%s\n", config.Name)
if targetRelease != config.Name {
data += fmt.Sprintf("# User specified TARGET_RELEASE=%s\n", targetRelease)
}
// The variable _all_release_configs will get deleted during processing, so do not mark it read-only.
data += fmt.Sprintf("_all_release_configs := %s\n", strings.Join(allReleaseNames, " "))
data += fmt.Sprintf("_ALL_RELEASE_FLAGS :=$= %s\n", strings.Join(names, " "))
for _, pName := range pNames {
data += fmt.Sprintf("_ALL_RELEASE_FLAGS.PARTITIONS.%s :=$= %s\n", pName, strings.Join(partitions[pName], " "))
}
@ -285,8 +301,6 @@ func (configs *ReleaseConfigs) DumpMakefile(outDir, targetRelease string) error
data += fmt.Sprintf("%s :=$= %s\n", vName, makeVars[vName])
}
data += "\n\n# Values for all build flags\n"
data += fmt.Sprintf("RELEASE_ACONFIG_VALUE_SETS :=$= %s\n",
strings.Join(config.ReleaseConfigArtifact.AconfigValueSets, " "))
for _, name := range names {
data += fmt.Sprintf("%s :=$= %s\n", name, makeVars[name])
}
@ -321,10 +335,10 @@ func (configs *ReleaseConfigs) GenerateReleaseConfigs(targetRelease string) erro
if err != nil {
return err
}
configs.Artifact = release_config_proto.ReleaseConfigsArtifact{
configs.Artifact = rc_proto.ReleaseConfigsArtifact{
ReleaseConfig: releaseConfig.ReleaseConfigArtifact,
OtherReleaseConfigs: func() []*release_config_proto.ReleaseConfigArtifact {
orc := []*release_config_proto.ReleaseConfigArtifact{}
OtherReleaseConfigs: func() []*rc_proto.ReleaseConfigArtifact {
orc := []*rc_proto.ReleaseConfigArtifact{}
for name, config := range configs.ReleaseConfigs {
if name != releaseConfig.Name {
orc = append(orc, config.ReleaseConfigArtifact)
@ -332,6 +346,13 @@ func (configs *ReleaseConfigs) GenerateReleaseConfigs(targetRelease string) erro
}
return orc
}(),
ReleaseConfigMapsMap: func() map[string]*rc_proto.ReleaseConfigMap {
ret := make(map[string]*rc_proto.ReleaseConfigMap)
for k, v := range configs.releaseConfigMapsMap {
ret[k] = &v.proto
}
return ret
}(),
}
return nil
}
@ -351,8 +372,8 @@ func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease strin
for idx, releaseConfigMapPath := range releaseConfigMapPaths {
// Maintain an ordered list of release config directories.
configDir := filepath.Dir(releaseConfigMapPath)
configs.ConfigDirIndexes[configDir] = idx
configs.ConfigDirs = append(configs.ConfigDirs, configDir)
configs.configDirIndexes[configDir] = idx
configs.configDirs = append(configs.configDirs, configDir)
err = configs.LoadReleaseConfigMap(releaseConfigMapPath, idx)
if err != nil {
return nil, err

View file

@ -15,6 +15,7 @@
package release_config_lib
import (
"encoding/json"
"fmt"
"io/fs"
"os"
@ -25,6 +26,8 @@ import (
"google.golang.org/protobuf/proto"
)
var disableWarnings bool
type StringList []string
func (l *StringList) Set(v string) error {
@ -36,15 +39,66 @@ func (l *StringList) String() string {
return fmt.Sprintf("%v", *l)
}
func LoadTextproto(path string, message proto.Message) error {
// Write a marshalled message to a file.
//
// Marshal the message based on the extension of the path we are writing it to.
//
// Args:
//
// path string: the path of the file to write to. Directories are not created.
// Supported extensions are: ".json", ".pb", and ".textproto".
// message proto.Message: the message to write.
//
// Returns:
//
// error: any error encountered.
func WriteMessage(path string, message proto.Message) (err error) {
var data []byte
switch filepath.Ext(path) {
case ".json":
data, err = json.MarshalIndent(message, "", " ")
case ".pb":
data, err = proto.Marshal(message)
case ".textproto":
data, err = prototext.MarshalOptions{Multiline: true}.Marshal(message)
default:
return fmt.Errorf("Unknown message format for %s", path)
}
if err != nil {
return err
}
return os.WriteFile(path, data, 0644)
}
// Read a message from a file.
//
// The message is unmarshalled based on the extension of the file read.
//
// Args:
//
// path string: the path of the file to read.
// message proto.Message: the message to unmarshal the message into.
//
// Returns:
//
// error: any error encountered.
func LoadMessage(path string, message proto.Message) error {
data, err := os.ReadFile(path)
if err != nil {
return err
}
ret := prototext.Unmarshal(data, message)
return ret
switch filepath.Ext(path) {
case ".json":
return json.Unmarshal(data, message)
case ".pb":
return proto.Unmarshal(data, message)
case ".textproto":
return prototext.Unmarshal(data, message)
}
return fmt.Errorf("Unknown message format for %s", path)
}
// Call Func for any textproto files found in {root}/{subdir}.
func WalkTextprotoFiles(root string, subdir string, Func fs.WalkDirFunc) error {
path := filepath.Join(root, subdir)
if _, err := os.Stat(path); err != nil {
@ -62,6 +116,19 @@ func WalkTextprotoFiles(root string, subdir string, Func fs.WalkDirFunc) error {
})
}
// Turn off all warning output
func DisableWarnings() {
disableWarnings = true
}
func warnf(format string, args ...any) (n int, err error) {
if !disableWarnings {
return fmt.Printf(format, args...)
}
return 0, nil
}
// Returns the default value for release config artifacts.
func GetDefaultOutDir() string {
outEnv := os.Getenv("OUT_DIR")
if outEnv == "" {
@ -70,6 +137,7 @@ func GetDefaultOutDir() string {
return filepath.Join(outEnv, "soong", "release-config")
}
// Return the default list of map files to use.
func GetDefaultMapPaths() StringList {
var defaultMapPaths StringList
defaultLocations := StringList{

View file

@ -18,7 +18,7 @@ package {
bootstrap_go_package {
name: "soong-cmd-release_config-proto",
pkgPath: "android/soong/release_config/release_config_proto",
pkgPath: "android/soong/cmd/release_config/release_config_proto",
deps: [
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",

View file

@ -259,6 +259,8 @@ type ReleaseConfigsArtifact struct {
ReleaseConfig *ReleaseConfigArtifact `protobuf:"bytes,1,opt,name=release_config,json=releaseConfig" json:"release_config,omitempty"`
// All other release configs defined for this TARGET_PRODUCT.
OtherReleaseConfigs []*ReleaseConfigArtifact `protobuf:"bytes,2,rep,name=other_release_configs,json=otherReleaseConfigs" json:"other_release_configs,omitempty"`
// Map of release_config_artifact.directories to release_config_map message.
ReleaseConfigMapsMap map[string]*ReleaseConfigMap `protobuf:"bytes,3,rep,name=release_config_maps_map,json=releaseConfigMapsMap" json:"release_config_maps_map,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
func (x *ReleaseConfigsArtifact) Reset() {
@ -307,6 +309,13 @@ func (x *ReleaseConfigsArtifact) GetOtherReleaseConfigs() []*ReleaseConfigArtifa
return nil
}
func (x *ReleaseConfigsArtifact) GetReleaseConfigMapsMap() map[string]*ReleaseConfigMap {
if x != nil {
return x.ReleaseConfigMapsMap
}
return nil
}
var File_build_flags_out_proto protoreflect.FileDescriptor
var file_build_flags_out_proto_rawDesc = []byte{
@ -352,7 +361,7 @@ var file_build_flags_out_proto_rawDesc = []byte{
0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08,
0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65,
0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64,
0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x22, 0xe3, 0x01, 0x0a, 0x18, 0x72,
0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x22, 0xe8, 0x03, 0x0a, 0x18, 0x72,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x5f, 0x61,
0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x5c, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
@ -367,10 +376,26 @@ var file_build_flags_out_proto_rawDesc = []byte{
0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x13, 0x6f, 0x74, 0x68,
0x65, 0x72, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73,
0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x87, 0x01, 0x0a, 0x17, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x50, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c,
0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x1a, 0x79, 0x0a, 0x19, 0x52, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d,
0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f,
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@ -385,28 +410,32 @@ func file_build_flags_out_proto_rawDescGZIP() []byte {
return file_build_flags_out_proto_rawDescData
}
var file_build_flags_out_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_build_flags_out_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_build_flags_out_proto_goTypes = []interface{}{
(*Tracepoint)(nil), // 0: android.release_config_proto.tracepoint
(*FlagArtifact)(nil), // 1: android.release_config_proto.flag_artifact
(*ReleaseConfigArtifact)(nil), // 2: android.release_config_proto.release_config_artifact
(*ReleaseConfigsArtifact)(nil), // 3: android.release_config_proto.release_configs_artifact
(*Value)(nil), // 4: android.release_config_proto.value
(*FlagDeclaration)(nil), // 5: android.release_config_proto.flag_declaration
nil, // 4: android.release_config_proto.release_configs_artifact.ReleaseConfigMapsMapEntry
(*Value)(nil), // 5: android.release_config_proto.value
(*FlagDeclaration)(nil), // 6: android.release_config_proto.flag_declaration
(*ReleaseConfigMap)(nil), // 7: android.release_config_proto.release_config_map
}
var file_build_flags_out_proto_depIdxs = []int32{
4, // 0: android.release_config_proto.tracepoint.value:type_name -> android.release_config_proto.value
5, // 1: android.release_config_proto.flag_artifact.flag_declaration:type_name -> android.release_config_proto.flag_declaration
4, // 2: android.release_config_proto.flag_artifact.value:type_name -> android.release_config_proto.value
5, // 0: android.release_config_proto.tracepoint.value:type_name -> android.release_config_proto.value
6, // 1: android.release_config_proto.flag_artifact.flag_declaration:type_name -> android.release_config_proto.flag_declaration
5, // 2: android.release_config_proto.flag_artifact.value:type_name -> android.release_config_proto.value
0, // 3: android.release_config_proto.flag_artifact.traces:type_name -> android.release_config_proto.tracepoint
1, // 4: android.release_config_proto.release_config_artifact.flag_artifacts:type_name -> android.release_config_proto.flag_artifact
2, // 5: android.release_config_proto.release_configs_artifact.release_config:type_name -> android.release_config_proto.release_config_artifact
2, // 6: android.release_config_proto.release_configs_artifact.other_release_configs:type_name -> android.release_config_proto.release_config_artifact
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
4, // 7: android.release_config_proto.release_configs_artifact.release_config_maps_map:type_name -> android.release_config_proto.release_configs_artifact.ReleaseConfigMapsMapEntry
7, // 8: android.release_config_proto.release_configs_artifact.ReleaseConfigMapsMapEntry.value:type_name -> android.release_config_proto.release_config_map
9, // [9:9] is the sub-list for method output_type
9, // [9:9] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
}
func init() { file_build_flags_out_proto_init() }
@ -471,7 +500,7 @@ func file_build_flags_out_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_build_flags_out_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumMessages: 5,
NumExtensions: 0,
NumServices: 0,
},

View file

@ -82,5 +82,8 @@ message release_configs_artifact {
// All other release configs defined for this TARGET_PRODUCT.
repeated release_config_artifact other_release_configs = 2;
// Map of release_config_artifact.directories to release_config_map message.
map<string, release_config_map> release_config_maps_map = 3;
}

View file

@ -568,6 +568,8 @@ type ReleaseConfigMap struct {
// Any aliases.
Aliases []*ReleaseAlias `protobuf:"bytes,1,rep,name=aliases" json:"aliases,omitempty"`
// Description of this map and its intended use.
Description *string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"`
// The default container for flags declared here.
DefaultContainer *Container `protobuf:"varint,3,opt,name=default_container,json=defaultContainer,enum=android.release_config_proto.Container" json:"default_container,omitempty"`
}
@ -611,6 +613,13 @@ func (x *ReleaseConfigMap) GetAliases() []*ReleaseAlias {
return nil
}
func (x *ReleaseConfigMap) GetDescription() string {
if x != nil && x.Description != nil {
return *x.Description
}
return ""
}
func (x *ReleaseConfigMap) GetDefaultContainer() Container {
if x != nil && x.DefaultContainer != nil {
return *x.DefaultContainer
@ -671,33 +680,35 @@ var file_build_flags_src_proto_rawDesc = []byte{
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, 0x0a, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb1, 0x01, 0x0a, 0x12, 0x72, 0x65, 0x6c,
0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x12, 0x72, 0x65, 0x6c,
0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x12,
0x45, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x2b, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x07, 0x61,
0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x54, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0e, 0x32, 0x27, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65,
0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x10, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2a, 0x4a, 0x0a, 0x08,
0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x4e, 0x53, 0x50,
0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c,
0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06,
0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x64, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
0x46, 0x49, 0x45, 0x44, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x10, 0x00,
0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f,
0x44, 0x55, 0x43, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d,
0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x45, 0x58, 0x54,
0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45, 0x4e, 0x44, 0x4f, 0x52, 0x10, 0x05, 0x42, 0x33,
0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f,
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72,
0x6f, 0x74, 0x6f,
0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73,
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x54, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61,
0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65,
0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x10, 0x64, 0x65,
0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2a, 0x4a,
0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x4e,
0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
0x6f, 0x77, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01,
0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a,
0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x64, 0x0a, 0x09, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x53, 0x50, 0x45,
0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50,
0x52, 0x4f, 0x44, 0x55, 0x43, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x59, 0x53, 0x54,
0x45, 0x4d, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x45,
0x58, 0x54, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45, 0x4e, 0x44, 0x4f, 0x52, 0x10, 0x05,
0x42, 0x33, 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
0x67, 0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x2f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (

View file

@ -144,6 +144,9 @@ message release_config_map {
// Any aliases.
repeated release_alias aliases = 1;
// Description of this map and its intended use.
optional string description = 2;
// The default container for flags declared here.
optional container default_container = 3;

View file

@ -35,6 +35,7 @@ source ${TOP}/build/soong/scripts/microfactory.bash
soong_build_go soong_ui android/soong/cmd/soong_ui
soong_build_go mk2rbc android/soong/mk2rbc/mk2rbc
soong_build_go rbcrun rbcrun/rbcrun
soong_build_go release-config android/soong/cmd/release_config/release_config
cd ${TOP}
exec "$(getoutdir)/soong_ui" "$@"