diff --git a/mk2rbc/Android.bp b/mk2rbc/Android.bp index 4fa3eb678..b18bfc72c 100644 --- a/mk2rbc/Android.bp +++ b/mk2rbc/Android.bp @@ -38,6 +38,7 @@ bootstrap_go_package { "soong_variables.go", "types.go", "variable.go", + "version_defaults.go", ], deps: ["androidmk-parser"], } diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go index 209e82bbd..7b5f298e2 100644 --- a/mk2rbc/cmd/mk2rbc.go +++ b/mk2rbc/cmd/mk2rbc.go @@ -81,6 +81,7 @@ var backupSuffix string var tracedVariables []string var errorLogger = errorsByType{data: make(map[string]datum)} var makefileFinder = &LinuxMakefileFinder{} +var versionDefaultsMk = filepath.Join("build", "make", "core", "version_defaults.mk") func main() { flag.Usage = func() { @@ -165,13 +166,24 @@ func main() { quit(fmt.Errorf("cannot generate configuration launcher for %s, it is not a known product", product)) } + versionDefaults, err := generateVersionDefaults() + if err != nil { + quit(err) + } ok = convertOne(path) && ok - err := writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(path), mk2rbc.MakePath2ModuleName(path))) + versionDefaultsPath := outputFilePath(versionDefaultsMk) + err = writeGenerated(versionDefaultsPath, versionDefaults) if err != nil { fmt.Fprintf(os.Stderr, "%s:%s", path, err) ok = false } + err = writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(path), versionDefaultsPath, + mk2rbc.MakePath2ModuleName(path))) + if err != nil { + fmt.Fprintf(os.Stderr, "%s:%s", path, err) + ok = false + } } else { files := flag.Args() if *allInSource { @@ -194,6 +206,15 @@ func main() { } } +func generateVersionDefaults() (string, error) { + versionSettings, err := mk2rbc.ParseVersionDefaults(filepath.Join(*rootDir, versionDefaultsMk)) + if err != nil { + return "", err + } + return mk2rbc.VersionDefaults(versionSettings), nil + +} + func quit(s interface{}) { fmt.Fprintln(os.Stderr, s) os.Exit(2) diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index b05d3409b..b9b7e2ccd 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -1618,12 +1618,12 @@ func Convert(req Request) (*StarlarkScript, error) { return starScript, nil } -func Launcher(path, name string) string { +func Launcher(mainModuleUri, versionDefaultsUri, mainModuleName string) string { var buf bytes.Buffer fmt.Fprintf(&buf, "load(%q, %q)\n", baseUri, baseName) - fmt.Fprintf(&buf, "load(%q, \"init\")\n", path) - fmt.Fprintf(&buf, "g, config = %s(%q, init)\n", cfnMain, name) - fmt.Fprintf(&buf, "%s(g, config)\n", cfnPrintVars) + fmt.Fprintf(&buf, "load(%q, \"version_defaults\")\n", versionDefaultsUri) + fmt.Fprintf(&buf, "load(%q, \"init\")\n", mainModuleUri) + fmt.Fprintf(&buf, "%s(%s(%q, init, version_defaults))\n", cfnPrintVars, cfnMain, mainModuleName) return buf.String() } diff --git a/mk2rbc/test/version_defaults.mk.test b/mk2rbc/test/version_defaults.mk.test new file mode 100644 index 000000000..166639278 --- /dev/null +++ b/mk2rbc/test/version_defaults.mk.test @@ -0,0 +1,22 @@ +INTERNAL_BUILD_ID_MAKEFILE := $(wildcard $(BUILD_SYSTEM)/build_id.mk) +ifdef INTERNAL_BUILD_ID_MAKEFILE + include $(INTERNAL_BUILD_ID_MAKEFILE) +endif + +DEFAULT_PLATFORM_VERSION := TP1A +.KATI_READONLY := DEFAULT_PLATFORM_VERSION +MIN_PLATFORM_VERSION := TP1A +MAX_PLATFORM_VERSION := TP1A +PLATFORM_VERSION_LAST_STABLE := 12 +PLATFORM_VERSION_CODENAME.SP2A := Sv2 +PLATFORM_VERSION_CODENAME.TP1A := Tiramisu +ifndef PLATFORM_SDK_VERSION + PLATFORM_SDK_VERSION := 31 +endif +.KATI_READONLY := PLATFORM_SDK_VERSION +PLATFORM_SDK_EXTENSION_VERSION := 1 +PLATFORM_BASE_SDK_EXTENSION_VERSION := 0 +ifndef PLATFORM_SECURITY_PATCH + PLATFORM_SECURITY_PATCH := 2021-10-05 +endif +include $(BUILD_SYSTEM)/version_util.mk diff --git a/mk2rbc/version_defaults.go b/mk2rbc/version_defaults.go new file mode 100644 index 000000000..27e8198a8 --- /dev/null +++ b/mk2rbc/version_defaults.go @@ -0,0 +1,109 @@ +// Copyright 2021 Google LLC +// +// 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 mk2rbc + +import ( + mkparser "android/soong/androidmk/parser" + "bytes" + "fmt" + "io/ioutil" + "os" + "sort" + "strconv" + "strings" +) + +const codenamePrefix = "PLATFORM_VERSION_CODENAME." + +// ParseVersionDefaults extracts version settings from the given file +// and returns the map. +func ParseVersionDefaults(path string) (map[string]string, error) { + contents, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + parser := mkparser.NewParser(path, bytes.NewBuffer(contents)) + nodes, errs := parser.Parse() + if len(errs) > 0 { + for _, e := range errs { + fmt.Fprintln(os.Stderr, "ERROR:", e) + } + return nil, fmt.Errorf("cannot parse %s", path) + } + + result := map[string]string{ + "DEFAULT_PLATFORM_VERSION": "", + "MAX_PLATFORM_VERSION": "", + "MIN_PLATFORM_VERSION": "A", + "PLATFORM_BASE_SDK_EXTENSION_VERSION": "", + "PLATFORM_SDK_EXTENSION_VERSION": "", + "PLATFORM_SDK_VERSION": "", + "PLATFORM_SECURITY_PATCH": "", + "PLATFORM_VERSION_LAST_STABLE": "", + } + for _, node := range nodes { + asgn, ok := node.(*mkparser.Assignment) + if !(ok && asgn.Name.Const()) { + continue + } + s := asgn.Name.Strings[0] + _, ok = result[s] + if !ok { + ok = strings.HasPrefix(s, codenamePrefix) + } + if !ok { + continue + } + v := asgn.Value + if !v.Const() { + return nil, fmt.Errorf("the value of %s should be constant", s) + } + result[s] = strings.TrimSpace(v.Strings[0]) + } + return result, nil +} + +func genericValue(s string) interface{} { + if ival, err := strconv.ParseInt(s, 0, 0); err == nil { + return ival + } + return s +} + +// VersionDefaults generates the contents of the version_defaults.rbc file +func VersionDefaults(values map[string]string) string { + var sink bytes.Buffer + var lines []string + var codenames []string + for name, value := range values { + if strings.HasPrefix(name, codenamePrefix) { + codenames = append(codenames, + fmt.Sprintf("%q: %q", strings.TrimPrefix(name, codenamePrefix), value)) + } else { + // Print numbers as such + lines = append(lines, fmt.Sprintf(" %s = %#v,\n", + strings.ToLower(name), genericValue(value))) + } + } + sort.Strings(lines) + sink.WriteString("version_defaults = struct(\n") + for _, l := range lines { + sink.WriteString(l) + } + sink.WriteString(" codenames = { ") + sink.WriteString(strings.Join(codenames, ", ")) + sink.WriteString(" }\n)\n") + return sink.String() +} diff --git a/mk2rbc/version_defaults_test.go b/mk2rbc/version_defaults_test.go new file mode 100644 index 000000000..c78fa3238 --- /dev/null +++ b/mk2rbc/version_defaults_test.go @@ -0,0 +1,60 @@ +package mk2rbc + +import ( + "path/filepath" + "reflect" + "strings" + "testing" +) + +func TestParseVersionDefaults(t *testing.T) { + testDir := getTestDirectory() + abspath := func(relPath string) string { return filepath.Join(testDir, relPath) } + actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test")) + if err != nil { + t.Fatal(err) + } + expectedProducts := map[string]string{ + "DEFAULT_PLATFORM_VERSION": "TP1A", + "MAX_PLATFORM_VERSION": "TP1A", + "MIN_PLATFORM_VERSION": "TP1A", + "PLATFORM_BASE_SDK_EXTENSION_VERSION": "0", + "PLATFORM_SDK_EXTENSION_VERSION": "1", + "PLATFORM_SDK_VERSION": "31", + "PLATFORM_SECURITY_PATCH": "2021-10-05", + "PLATFORM_VERSION_LAST_STABLE": "12", + "PLATFORM_VERSION_CODENAME.SP2A": "Sv2", + "PLATFORM_VERSION_CODENAME.TP1A": "Tiramisu", + } + if !reflect.DeepEqual(actualProducts, expectedProducts) { + t.Errorf("\nExpected: %v\n Actual: %v", expectedProducts, actualProducts) + } +} + +func TestVersionDefaults(t *testing.T) { + testDir := getTestDirectory() + abspath := func(relPath string) string { return filepath.Join(testDir, relPath) } + actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test")) + if err != nil { + t.Fatal(err) + } + expectedString := `version_defaults = struct( + default_platform_version = "TP1A", + max_platform_version = "TP1A", + min_platform_version = "TP1A", + platform_base_sdk_extension_version = 0, + platform_sdk_extension_version = 1, + platform_sdk_version = 31, + platform_security_patch = "2021-10-05", + platform_version_last_stable = 12, + codenames = { "SP2A": "Sv2", "TP1A": "Tiramisu" } +) +` + actualString := VersionDefaults(actualProducts) + if !reflect.DeepEqual(actualString, expectedString) { + t.Errorf("\nExpected: %v\nActual:\n%v", + strings.ReplaceAll(expectedString, "\n", "␤\n"), + strings.ReplaceAll(actualString, "\n", "␤\n")) + } + +}