release_config: make the code more sharable
This will allow the `build-flag` command to use release_config_lib code. Bug: 328495189 Test: manual Change-Id: If068597b1d68c52c941788931997b7f77c73d2b3
This commit is contained in:
@@ -1,30 +0,0 @@
|
|||||||
package {
|
|
||||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
|
||||||
}
|
|
||||||
|
|
||||||
bootstrap_go_package {
|
|
||||||
name: "release-config",
|
|
||||||
pkgPath: "android/soong/cmd/release_config",
|
|
||||||
deps: [
|
|
||||||
"golang-protobuf-encoding-prototext",
|
|
||||||
"golang-protobuf-reflect-protoreflect",
|
|
||||||
"golang-protobuf-runtime-protoimpl",
|
|
||||||
"soong-cmd-release-config-proto",
|
|
||||||
],
|
|
||||||
srcs: [
|
|
||||||
"main.go",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
bootstrap_go_package {
|
|
||||||
name: "soong-cmd-release-config-proto",
|
|
||||||
pkgPath: "android/soong/cmd/release_config/release_config_proto",
|
|
||||||
deps: [
|
|
||||||
"golang-protobuf-reflect-protoreflect",
|
|
||||||
"golang-protobuf-runtime-protoimpl",
|
|
||||||
],
|
|
||||||
srcs: [
|
|
||||||
"release_config_proto/build_flags_out.pb.go",
|
|
||||||
"release_config_proto/build_flags_src.pb.go",
|
|
||||||
],
|
|
||||||
}
|
|
18
cmd/release_config/release_config/Android.bp
Normal file
18
cmd/release_config/release_config/Android.bp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package {
|
||||||
|
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrap_go_package {
|
||||||
|
name: "soong-cmd-release_config-release_config",
|
||||||
|
pkgPath: "android/soong/cmd/release_config/release_config",
|
||||||
|
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",
|
||||||
|
],
|
||||||
|
}
|
57
cmd/release_config/release_config/main.go
Normal file
57
cmd/release_config/release_config/main.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// 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 main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
rc_lib "android/soong/cmd/release_config/release_config_lib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var top string
|
||||||
|
var releaseConfigMapPaths rc_lib.StringList
|
||||||
|
var targetRelease string
|
||||||
|
var outputDir string
|
||||||
|
var err error
|
||||||
|
var configs *rc_lib.ReleaseConfigs
|
||||||
|
|
||||||
|
flag.StringVar(&top, "top", ".", "path to top of workspace")
|
||||||
|
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(&outputDir, "out_dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if err = os.Chdir(top); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
configs, err = rc_lib.ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = os.MkdirAll(outputDir, 0775)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = configs.DumpMakefile(outputDir, targetRelease)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = configs.DumpArtifact(outputDir)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
36
cmd/release_config/release_config_lib/Android.bp
Normal file
36
cmd/release_config/release_config_lib/Android.bp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// 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 {
|
||||||
|
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrap_go_package {
|
||||||
|
name: "soong-cmd-release_config-lib",
|
||||||
|
pkgPath: "android/soong/release_config/release_config_lib",
|
||||||
|
deps: [
|
||||||
|
"golang-protobuf-encoding-prototext",
|
||||||
|
"golang-protobuf-reflect-protoreflect",
|
||||||
|
"golang-protobuf-runtime-protoimpl",
|
||||||
|
"soong-cmd-release_config-proto",
|
||||||
|
],
|
||||||
|
srcs: [
|
||||||
|
"flag_artifact.go",
|
||||||
|
"flag_declaration.go",
|
||||||
|
"flag_value.go",
|
||||||
|
"release_config.go",
|
||||||
|
"release_configs.go",
|
||||||
|
"util.go",
|
||||||
|
],
|
||||||
|
}
|
89
cmd/release_config/release_config_lib/flag_artifact.go
Normal file
89
cmd/release_config/release_config_lib/flag_artifact.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// 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 release_config_lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"android/soong/cmd/release_config/release_config_proto"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FlagArtifact struct {
|
||||||
|
FlagDeclaration *release_config_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
|
||||||
|
|
||||||
|
// Assigned value
|
||||||
|
Value *release_config_proto.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key is flag name.
|
||||||
|
type FlagArtifacts map[string]*FlagArtifact
|
||||||
|
|
||||||
|
func (src *FlagArtifact) Clone() *FlagArtifact {
|
||||||
|
value := &release_config_proto.Value{}
|
||||||
|
proto.Merge(value, src.Value)
|
||||||
|
return &FlagArtifact{
|
||||||
|
FlagDeclaration: src.FlagDeclaration,
|
||||||
|
Traces: src.Traces,
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (src FlagArtifacts) Clone() (dst FlagArtifacts) {
|
||||||
|
if dst == nil {
|
||||||
|
dst = make(FlagArtifacts)
|
||||||
|
}
|
||||||
|
for k, v := range src {
|
||||||
|
dst[k] = v.Clone()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
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})
|
||||||
|
if fa.Value.GetObsolete() {
|
||||||
|
return fmt.Errorf("Attempting to set obsolete flag %s. Trace=%v", name, fa.Traces)
|
||||||
|
}
|
||||||
|
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:
|
||||||
|
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}}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Invalid type for flag_value: %T. Trace=%v", val, fa.Traces)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fa *FlagArtifact) Marshal() (*release_config_proto.FlagArtifact, error) {
|
||||||
|
return &release_config_proto.FlagArtifact{
|
||||||
|
FlagDeclaration: fa.FlagDeclaration,
|
||||||
|
Value: fa.Value,
|
||||||
|
Traces: fa.Traces,
|
||||||
|
}, nil
|
||||||
|
}
|
27
cmd/release_config/release_config_lib/flag_declaration.go
Normal file
27
cmd/release_config/release_config_lib/flag_declaration.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// 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 release_config_lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"android/soong/cmd/release_config/release_config_proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FlagDeclarationFactory(protoPath string) (fd *release_config_proto.FlagDeclaration) {
|
||||||
|
fd = &release_config_proto.FlagDeclaration{}
|
||||||
|
if protoPath != "" {
|
||||||
|
LoadTextproto(protoPath, fd)
|
||||||
|
}
|
||||||
|
return fd
|
||||||
|
}
|
56
cmd/release_config/release_config_lib/flag_value.go
Normal file
56
cmd/release_config/release_config_lib/flag_value.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// 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 release_config_lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"android/soong/cmd/release_config/release_config_proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FlagValue struct {
|
||||||
|
// The path providing this value.
|
||||||
|
path string
|
||||||
|
|
||||||
|
// Protobuf
|
||||||
|
proto release_config_proto.FlagValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func FlagValueFactory(protoPath string) (fv *FlagValue) {
|
||||||
|
fv = &FlagValue{path: protoPath}
|
||||||
|
if protoPath != "" {
|
||||||
|
LoadTextproto(protoPath, &fv.proto)
|
||||||
|
}
|
||||||
|
return fv
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalValue(value *release_config_proto.Value) string {
|
||||||
|
switch val := value.Val.(type) {
|
||||||
|
case *release_config_proto.Value_UnspecifiedValue:
|
||||||
|
// Value was never set.
|
||||||
|
return ""
|
||||||
|
case *release_config_proto.Value_StringValue:
|
||||||
|
return val.StringValue
|
||||||
|
case *release_config_proto.Value_BoolValue:
|
||||||
|
if val.BoolValue {
|
||||||
|
return "true"
|
||||||
|
}
|
||||||
|
// False ==> empty string
|
||||||
|
return ""
|
||||||
|
case *release_config_proto.Value_Obsolete:
|
||||||
|
return " #OBSOLETE"
|
||||||
|
default:
|
||||||
|
// Flagged as error elsewhere, so return empty string here.
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
67
cmd/release_config/release_config_lib/flag_value_test.go
Normal file
67
cmd/release_config/release_config_lib/flag_value_test.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// 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 release_config_lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
rc_proto "android/soong/cmd/release_config/release_config_proto"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type testCaseFlagValue struct {
|
||||||
|
protoPath string
|
||||||
|
name string
|
||||||
|
data []byte
|
||||||
|
expected rc_proto.FlagValue
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc testCaseFlagValue) assertProtoEqual(t *testing.T, expected, actual proto.Message) {
|
||||||
|
if !proto.Equal(expected, actual) {
|
||||||
|
t.Errorf("Expected %q found %q", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFlagValue(t *testing.T) {
|
||||||
|
testCases := []testCaseFlagValue{
|
||||||
|
{
|
||||||
|
name: "stringVal",
|
||||||
|
protoPath: "build/release/flag_values/test/RELEASE_FOO.textproto",
|
||||||
|
data: []byte(`name: "RELEASE_FOO" value {string_value: "BAR"}`),
|
||||||
|
expected: rc_proto.FlagValue{
|
||||||
|
Name: proto.String("RELEASE_FOO"),
|
||||||
|
Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{"BAR"}},
|
||||||
|
},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
var err error
|
||||||
|
tempdir := t.TempDir()
|
||||||
|
path := filepath.Join(tempdir, tc.protoPath)
|
||||||
|
if err = os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err = os.WriteFile(path, tc.data, 0644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
actual := FlagValueFactory(path)
|
||||||
|
tc.assertProtoEqual(t, &tc.expected, &actual.proto)
|
||||||
|
}
|
||||||
|
}
|
154
cmd/release_config/release_config_lib/release_config.go
Normal file
154
cmd/release_config/release_config_lib/release_config.go
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
// 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 release_config_lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"android/soong/cmd/release_config/release_config_proto"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// One directory's contribution to the a release config.
|
||||||
|
type ReleaseConfigContribution struct {
|
||||||
|
// Paths to files providing this config.
|
||||||
|
path string
|
||||||
|
|
||||||
|
// The index of the config directory where this release config
|
||||||
|
// contribution was declared.
|
||||||
|
// Flag values cannot be set in a location with a lower index.
|
||||||
|
DeclarationIndex int
|
||||||
|
|
||||||
|
// Protobufs relevant to the config.
|
||||||
|
proto release_config_proto.ReleaseConfig
|
||||||
|
|
||||||
|
FlagValues []*FlagValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// A generated release config.
|
||||||
|
type ReleaseConfig struct {
|
||||||
|
// the Name of the release config
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// The index of the config directory where this release config was
|
||||||
|
// first declared.
|
||||||
|
// Flag values cannot be set in a location with a lower index.
|
||||||
|
DeclarationIndex int
|
||||||
|
|
||||||
|
// What contributes to this config.
|
||||||
|
Contributions []*ReleaseConfigContribution
|
||||||
|
|
||||||
|
// Aliases for this release
|
||||||
|
OtherNames []string
|
||||||
|
|
||||||
|
// The names of release configs that we inherit
|
||||||
|
InheritNames []string
|
||||||
|
|
||||||
|
// Unmarshalled flag artifacts
|
||||||
|
FlagArtifacts FlagArtifacts
|
||||||
|
|
||||||
|
// Generated release config
|
||||||
|
ReleaseConfigArtifact *release_config_proto.ReleaseConfigArtifact
|
||||||
|
|
||||||
|
// We have begun compiling this release config.
|
||||||
|
compileInProgress bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReleaseConfigFactory(name string, index int) (c *ReleaseConfig) {
|
||||||
|
return &ReleaseConfig{Name: name, DeclarationIndex: index}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) error {
|
||||||
|
if config.ReleaseConfigArtifact != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if config.compileInProgress {
|
||||||
|
return fmt.Errorf("Loop detected for release config %s", config.Name)
|
||||||
|
}
|
||||||
|
config.compileInProgress = true
|
||||||
|
|
||||||
|
// Generate any configs we need to inherit. This will detect loops in
|
||||||
|
// the config.
|
||||||
|
contributionsToApply := []*ReleaseConfigContribution{}
|
||||||
|
myInherits := []string{}
|
||||||
|
myInheritsSet := make(map[string]bool)
|
||||||
|
for _, inherit := range config.InheritNames {
|
||||||
|
if _, ok := myInheritsSet[inherit]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
myInherits = append(myInherits, inherit)
|
||||||
|
myInheritsSet[inherit] = true
|
||||||
|
iConfig, err := configs.GetReleaseConfig(inherit)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
iConfig.GenerateReleaseConfig(configs)
|
||||||
|
contributionsToApply = append(contributionsToApply, iConfig.Contributions...)
|
||||||
|
}
|
||||||
|
contributionsToApply = append(contributionsToApply, config.Contributions...)
|
||||||
|
|
||||||
|
myAconfigValueSets := []string{}
|
||||||
|
myFlags := configs.FlagArtifacts.Clone()
|
||||||
|
myDirsMap := make(map[int]bool)
|
||||||
|
for _, contrib := range contributionsToApply {
|
||||||
|
myAconfigValueSets = append(myAconfigValueSets, contrib.proto.AconfigValueSets...)
|
||||||
|
myDirsMap[contrib.DeclarationIndex] = true
|
||||||
|
for _, value := range contrib.FlagValues {
|
||||||
|
fa, ok := myFlags[*value.proto.Name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Setting value for undefined flag %s in %s\n", *value.proto.Name, value.path)
|
||||||
|
}
|
||||||
|
myDirsMap[fa.DeclarationIndex] = true
|
||||||
|
if fa.DeclarationIndex > contrib.DeclarationIndex {
|
||||||
|
// 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 err := fa.UpdateValue(*value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
directories := []string{}
|
||||||
|
for idx, confDir := range configs.ConfigDirs {
|
||||||
|
if _, ok := myDirsMap[idx]; ok {
|
||||||
|
directories = append(directories, confDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.FlagArtifacts = myFlags
|
||||||
|
config.ReleaseConfigArtifact = &release_config_proto.ReleaseConfigArtifact{
|
||||||
|
Name: proto.String(config.Name),
|
||||||
|
OtherNames: config.OtherNames,
|
||||||
|
FlagArtifacts: func() []*release_config_proto.FlagArtifact {
|
||||||
|
ret := []*release_config_proto.FlagArtifact{}
|
||||||
|
for _, flag := range myFlags {
|
||||||
|
ret = append(ret, &release_config_proto.FlagArtifact{
|
||||||
|
FlagDeclaration: flag.FlagDeclaration,
|
||||||
|
Traces: flag.Traces,
|
||||||
|
Value: flag.Value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}(),
|
||||||
|
AconfigValueSets: myAconfigValueSets,
|
||||||
|
Inherits: myInherits,
|
||||||
|
Directories: directories,
|
||||||
|
}
|
||||||
|
|
||||||
|
config.compileInProgress = false
|
||||||
|
return nil
|
||||||
|
}
|
@@ -12,12 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package main
|
package release_config_lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmp"
|
"cmp"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
@@ -31,105 +30,6 @@ import (
|
|||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var verboseFlag bool
|
|
||||||
|
|
||||||
type StringList []string
|
|
||||||
|
|
||||||
func (l *StringList) Set(v string) error {
|
|
||||||
*l = append(*l, v)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *StringList) String() string {
|
|
||||||
return fmt.Sprintf("%v", *l)
|
|
||||||
}
|
|
||||||
|
|
||||||
var releaseConfigMapPaths StringList
|
|
||||||
|
|
||||||
func DumpProtos(outDir string, message proto.Message) error {
|
|
||||||
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, "", " ") })
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadTextproto(path string, message proto.Message) error {
|
|
||||||
data, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ret := prototext.Unmarshal(data, message)
|
|
||||||
if verboseFlag {
|
|
||||||
debug, _ := prototext.Marshal(message)
|
|
||||||
fmt.Printf("%s: %s\n", path, debug)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func WalkTextprotoFiles(root string, subdir string, Func fs.WalkDirFunc) error {
|
|
||||||
path := filepath.Join(root, subdir)
|
|
||||||
if _, err := os.Stat(path); err != nil {
|
|
||||||
// Missing subdirs are not an error.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(d.Name(), ".textproto") && d.Type().IsRegular() {
|
|
||||||
return Func(path, d, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type FlagValue struct {
|
|
||||||
// The path providing this value.
|
|
||||||
path string
|
|
||||||
|
|
||||||
// Protobuf
|
|
||||||
proto release_config_proto.FlagValue
|
|
||||||
}
|
|
||||||
|
|
||||||
func FlagValueFactory(protoPath string) (fv *FlagValue) {
|
|
||||||
fv = &FlagValue{path: protoPath}
|
|
||||||
if protoPath != "" {
|
|
||||||
LoadTextproto(protoPath, &fv.proto)
|
|
||||||
}
|
|
||||||
return fv
|
|
||||||
}
|
|
||||||
|
|
||||||
// One directory's contribution to the a release config.
|
|
||||||
type ReleaseConfigContribution struct {
|
|
||||||
// Paths to files providing this config.
|
|
||||||
path string
|
|
||||||
|
|
||||||
// The index of the config directory where this release config
|
|
||||||
// contribution was declared.
|
|
||||||
// Flag values cannot be set in a location with a lower index.
|
|
||||||
DeclarationIndex int
|
|
||||||
|
|
||||||
// Protobufs relevant to the config.
|
|
||||||
proto release_config_proto.ReleaseConfig
|
|
||||||
|
|
||||||
FlagValues []*FlagValue
|
|
||||||
}
|
|
||||||
|
|
||||||
// A single release_config_map.textproto and its associated data.
|
// A single release_config_map.textproto and its associated data.
|
||||||
// Used primarily for debugging.
|
// Used primarily for debugging.
|
||||||
type ReleaseConfigMap struct {
|
type ReleaseConfigMap struct {
|
||||||
@@ -143,51 +43,6 @@ type ReleaseConfigMap struct {
|
|||||||
FlagDeclarations []release_config_proto.FlagDeclaration
|
FlagDeclarations []release_config_proto.FlagDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
// A generated release config.
|
|
||||||
type ReleaseConfig struct {
|
|
||||||
// the Name of the release config
|
|
||||||
Name string
|
|
||||||
|
|
||||||
// The index of the config directory where this release config was
|
|
||||||
// first declared.
|
|
||||||
// Flag values cannot be set in a location with a lower index.
|
|
||||||
DeclarationIndex int
|
|
||||||
|
|
||||||
// What contributes to this config.
|
|
||||||
Contributions []*ReleaseConfigContribution
|
|
||||||
|
|
||||||
// Aliases for this release
|
|
||||||
OtherNames []string
|
|
||||||
|
|
||||||
// The names of release configs that we inherit
|
|
||||||
InheritNames []string
|
|
||||||
|
|
||||||
// Unmarshalled flag artifacts
|
|
||||||
FlagArtifacts FlagArtifacts
|
|
||||||
|
|
||||||
// Generated release config
|
|
||||||
ReleaseConfigArtifact *release_config_proto.ReleaseConfigArtifact
|
|
||||||
|
|
||||||
// We have begun compiling this release config.
|
|
||||||
compileInProgress bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type FlagArtifact struct {
|
|
||||||
FlagDeclaration *release_config_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
|
|
||||||
|
|
||||||
// Assigned value
|
|
||||||
Value *release_config_proto.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key is flag name.
|
|
||||||
type FlagArtifacts map[string]*FlagArtifact
|
|
||||||
|
|
||||||
type ReleaseConfigDirMap map[string]int
|
type ReleaseConfigDirMap map[string]int
|
||||||
|
|
||||||
// The generated release configs.
|
// The generated release configs.
|
||||||
@@ -215,28 +70,27 @@ type ReleaseConfigs struct {
|
|||||||
ConfigDirIndexes ReleaseConfigDirMap
|
ConfigDirIndexes ReleaseConfigDirMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (src *FlagArtifact) Clone() *FlagArtifact {
|
func (configs *ReleaseConfigs) DumpArtifact(outDir string) error {
|
||||||
value := &release_config_proto.Value{}
|
message := &configs.Artifact
|
||||||
proto.Merge(value, src.Value)
|
basePath := filepath.Join(outDir, "all_release_configs")
|
||||||
return &FlagArtifact{
|
writer := func(suffix string, marshal func() ([]byte, error)) error {
|
||||||
FlagDeclaration: src.FlagDeclaration,
|
data, err := marshal()
|
||||||
Traces: src.Traces,
|
if err != nil {
|
||||||
Value: value,
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
func (src FlagArtifacts) Clone() (dst FlagArtifacts) {
|
err = writer("pb", func() ([]byte, error) { return proto.Marshal(message) })
|
||||||
if dst == nil {
|
if err != nil {
|
||||||
dst = make(FlagArtifacts)
|
return err
|
||||||
}
|
|
||||||
for k, v := range src {
|
|
||||||
dst[k] = v.Clone()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReleaseConfigFactory(name string, index int) (c *ReleaseConfig) {
|
return writer("json", func() ([]byte, error) { return json.MarshalIndent(message, "", " ") })
|
||||||
return &ReleaseConfig{Name: name, DeclarationIndex: index}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReleaseConfigsFactory() (c *ReleaseConfigs) {
|
func ReleaseConfigsFactory() (c *ReleaseConfigs) {
|
||||||
@@ -260,14 +114,6 @@ func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func FlagDeclarationFactory(protoPath string) (fd *release_config_proto.FlagDeclaration) {
|
|
||||||
fd = &release_config_proto.FlagDeclaration{}
|
|
||||||
if protoPath != "" {
|
|
||||||
LoadTextproto(protoPath, fd)
|
|
||||||
}
|
|
||||||
return fd
|
|
||||||
}
|
|
||||||
|
|
||||||
func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error {
|
func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error {
|
||||||
m := ReleaseConfigMapFactory(path)
|
m := ReleaseConfigMapFactory(path)
|
||||||
if m.proto.DefaultContainer == nil {
|
if m.proto.DefaultContainer == nil {
|
||||||
@@ -490,167 +336,17 @@ func (configs *ReleaseConfigs) GenerateReleaseConfigs(targetRelease string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MarshalValue(value *release_config_proto.Value) string {
|
|
||||||
switch val := value.Val.(type) {
|
|
||||||
case *release_config_proto.Value_UnspecifiedValue:
|
|
||||||
// Value was never set.
|
|
||||||
return ""
|
|
||||||
case *release_config_proto.Value_StringValue:
|
|
||||||
return val.StringValue
|
|
||||||
case *release_config_proto.Value_BoolValue:
|
|
||||||
if val.BoolValue {
|
|
||||||
return "true"
|
|
||||||
}
|
|
||||||
// False ==> empty string
|
|
||||||
return ""
|
|
||||||
case *release_config_proto.Value_Obsolete:
|
|
||||||
return " #OBSOLETE"
|
|
||||||
default:
|
|
||||||
// Flagged as error elsewhere, so return empty string here.
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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})
|
|
||||||
if fa.Value.GetObsolete() {
|
|
||||||
return fmt.Errorf("Attempting to set obsolete flag %s. Trace=%v", name, fa.Traces)
|
|
||||||
}
|
|
||||||
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:
|
|
||||||
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}}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Invalid type for flag_value: %T. Trace=%v", val, fa.Traces)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fa *FlagArtifact) Marshal() (*release_config_proto.FlagArtifact, error) {
|
|
||||||
return &release_config_proto.FlagArtifact{
|
|
||||||
FlagDeclaration: fa.FlagDeclaration,
|
|
||||||
Value: fa.Value,
|
|
||||||
Traces: fa.Traces,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) error {
|
|
||||||
if config.ReleaseConfigArtifact != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if config.compileInProgress {
|
|
||||||
return fmt.Errorf("Loop detected for release config %s", config.Name)
|
|
||||||
}
|
|
||||||
config.compileInProgress = true
|
|
||||||
|
|
||||||
// Generate any configs we need to inherit. This will detect loops in
|
|
||||||
// the config.
|
|
||||||
contributionsToApply := []*ReleaseConfigContribution{}
|
|
||||||
myInherits := []string{}
|
|
||||||
myInheritsSet := make(map[string]bool)
|
|
||||||
for _, inherit := range config.InheritNames {
|
|
||||||
if _, ok := myInheritsSet[inherit]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
myInherits = append(myInherits, inherit)
|
|
||||||
myInheritsSet[inherit] = true
|
|
||||||
iConfig, err := configs.GetReleaseConfig(inherit)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
iConfig.GenerateReleaseConfig(configs)
|
|
||||||
contributionsToApply = append(contributionsToApply, iConfig.Contributions...)
|
|
||||||
}
|
|
||||||
contributionsToApply = append(contributionsToApply, config.Contributions...)
|
|
||||||
|
|
||||||
myAconfigValueSets := []string{}
|
|
||||||
myFlags := configs.FlagArtifacts.Clone()
|
|
||||||
myDirsMap := make(map[int]bool)
|
|
||||||
for _, contrib := range contributionsToApply {
|
|
||||||
myAconfigValueSets = append(myAconfigValueSets, contrib.proto.AconfigValueSets...)
|
|
||||||
myDirsMap[contrib.DeclarationIndex] = true
|
|
||||||
for _, value := range contrib.FlagValues {
|
|
||||||
fa, ok := myFlags[*value.proto.Name]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("Setting value for undefined flag %s in %s\n", *value.proto.Name, value.path)
|
|
||||||
}
|
|
||||||
myDirsMap[fa.DeclarationIndex] = true
|
|
||||||
if fa.DeclarationIndex > contrib.DeclarationIndex {
|
|
||||||
// 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 err := fa.UpdateValue(*value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
directories := []string{}
|
|
||||||
for idx, confDir := range configs.ConfigDirs {
|
|
||||||
if _, ok := myDirsMap[idx]; ok {
|
|
||||||
directories = append(directories, confDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.FlagArtifacts = myFlags
|
|
||||||
config.ReleaseConfigArtifact = &release_config_proto.ReleaseConfigArtifact{
|
|
||||||
Name: proto.String(config.Name),
|
|
||||||
OtherNames: config.OtherNames,
|
|
||||||
FlagArtifacts: func() []*release_config_proto.FlagArtifact {
|
|
||||||
ret := []*release_config_proto.FlagArtifact{}
|
|
||||||
for _, flag := range myFlags {
|
|
||||||
ret = append(ret, &release_config_proto.FlagArtifact{
|
|
||||||
FlagDeclaration: flag.FlagDeclaration,
|
|
||||||
Traces: flag.Traces,
|
|
||||||
Value: flag.Value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}(),
|
|
||||||
AconfigValueSets: myAconfigValueSets,
|
|
||||||
Inherits: myInherits,
|
|
||||||
Directories: directories,
|
|
||||||
}
|
|
||||||
|
|
||||||
config.compileInProgress = false
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDefaultOutDir() string {
|
|
||||||
outEnv := os.Getenv("OUT_DIR")
|
|
||||||
if outEnv == "" {
|
|
||||||
outEnv = "out"
|
|
||||||
}
|
|
||||||
return filepath.Join(outEnv, "soong", "release-config")
|
|
||||||
}
|
|
||||||
func GetDefaultMapPaths() StringList {
|
|
||||||
var defaultMapPaths StringList
|
|
||||||
defaultLocations := StringList{
|
|
||||||
"build/release/release_config_map.textproto",
|
|
||||||
"vendor/google_shared/build/release/release_config_map.textproto",
|
|
||||||
"vendor/google/release/release_config_map.textproto",
|
|
||||||
}
|
|
||||||
for _, path := range defaultLocations {
|
|
||||||
if _, err := os.Stat(path); err == nil {
|
|
||||||
defaultMapPaths = append(defaultMapPaths, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prodMaps := os.Getenv("PRODUCT_RELEASE_CONFIG_MAPS")
|
|
||||||
if prodMaps != "" {
|
|
||||||
defaultMapPaths = append(defaultMapPaths, strings.Split(prodMaps, " ")...)
|
|
||||||
}
|
|
||||||
return defaultMapPaths
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string) (*ReleaseConfigs, error) {
|
func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string) (*ReleaseConfigs, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
if len(releaseConfigMapPaths) == 0 {
|
||||||
|
releaseConfigMapPaths = GetDefaultMapPaths()
|
||||||
|
if len(releaseConfigMapPaths) == 0 {
|
||||||
|
return nil, fmt.Errorf("No maps found")
|
||||||
|
}
|
||||||
|
fmt.Printf("No --map argument provided. Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map "))
|
||||||
|
}
|
||||||
|
|
||||||
configs := ReleaseConfigsFactory()
|
configs := ReleaseConfigsFactory()
|
||||||
for idx, releaseConfigMapPath := range releaseConfigMapPaths {
|
for idx, releaseConfigMapPath := range releaseConfigMapPaths {
|
||||||
// Maintain an ordered list of release config directories.
|
// Maintain an ordered list of release config directories.
|
||||||
@@ -667,36 +363,3 @@ func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease strin
|
|||||||
err = configs.GenerateReleaseConfigs(targetRelease)
|
err = configs.GenerateReleaseConfigs(targetRelease)
|
||||||
return configs, err
|
return configs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
|
||||||
var targetRelease string
|
|
||||||
var outputDir string
|
|
||||||
|
|
||||||
flag.BoolVar(&verboseFlag, "debug", false, "print debugging information")
|
|
||||||
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(&outputDir, "out_dir", GetDefaultOutDir(), "basepath for the output. Multiple formats are created")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if len(releaseConfigMapPaths) == 0 {
|
|
||||||
releaseConfigMapPaths = GetDefaultMapPaths()
|
|
||||||
if len(releaseConfigMapPaths) == 0 {
|
|
||||||
panic(fmt.Errorf("No maps found"))
|
|
||||||
}
|
|
||||||
fmt.Printf("No --map argument provided. Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map "))
|
|
||||||
}
|
|
||||||
|
|
||||||
configs, err := ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = os.MkdirAll(outputDir, 0775)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = configs.DumpMakefile(outputDir, targetRelease)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
DumpProtos(outputDir, &configs.Artifact)
|
|
||||||
}
|
|
90
cmd/release_config/release_config_lib/util.go
Normal file
90
cmd/release_config/release_config_lib/util.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// 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 release_config_lib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StringList []string
|
||||||
|
|
||||||
|
func (l *StringList) Set(v string) error {
|
||||||
|
*l = append(*l, v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *StringList) String() string {
|
||||||
|
return fmt.Sprintf("%v", *l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadTextproto(path string, message proto.Message) error {
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ret := prototext.Unmarshal(data, message)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func WalkTextprotoFiles(root string, subdir string, Func fs.WalkDirFunc) error {
|
||||||
|
path := filepath.Join(root, subdir)
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
// Missing subdirs are not an error.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(d.Name(), ".textproto") && d.Type().IsRegular() {
|
||||||
|
return Func(path, d, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDefaultOutDir() string {
|
||||||
|
outEnv := os.Getenv("OUT_DIR")
|
||||||
|
if outEnv == "" {
|
||||||
|
outEnv = "out"
|
||||||
|
}
|
||||||
|
return filepath.Join(outEnv, "soong", "release-config")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDefaultMapPaths() StringList {
|
||||||
|
var defaultMapPaths StringList
|
||||||
|
defaultLocations := StringList{
|
||||||
|
"build/release/release_config_map.textproto",
|
||||||
|
"vendor/google_shared/build/release/release_config_map.textproto",
|
||||||
|
"vendor/google/release/release_config_map.textproto",
|
||||||
|
}
|
||||||
|
for _, path := range defaultLocations {
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
defaultMapPaths = append(defaultMapPaths, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prodMaps := os.Getenv("PRODUCT_RELEASE_CONFIG_MAPS")
|
||||||
|
if prodMaps != "" {
|
||||||
|
defaultMapPaths = append(defaultMapPaths, strings.Split(prodMaps, " ")...)
|
||||||
|
}
|
||||||
|
return defaultMapPaths
|
||||||
|
}
|
@@ -17,7 +17,7 @@ package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bootstrap_go_package {
|
bootstrap_go_package {
|
||||||
name: "soong-release_config_proto",
|
name: "soong-cmd-release_config-proto",
|
||||||
pkgPath: "android/soong/release_config/release_config_proto",
|
pkgPath: "android/soong/release_config/release_config_proto",
|
||||||
deps: [
|
deps: [
|
||||||
"golang-protobuf-reflect-protoreflect",
|
"golang-protobuf-reflect-protoreflect",
|
||||||
|
Reference in New Issue
Block a user