Merge "Fix bp2build-progress generating an empty converted_modules list, and duplicate module names."
diff --git a/android/paths.go b/android/paths.go
index 763cd7c..2e378ba 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -263,38 +263,56 @@
// OptionalPath is a container that may or may not contain a valid Path.
type OptionalPath struct {
- valid bool
- path Path
+ path Path // nil if invalid.
+ invalidReason string // Not applicable if path != nil. "" if the reason is unknown.
}
// OptionalPathForPath returns an OptionalPath containing the path.
func OptionalPathForPath(path Path) OptionalPath {
- if path == nil {
- return OptionalPath{}
- }
- return OptionalPath{valid: true, path: path}
+ return OptionalPath{path: path}
+}
+
+// InvalidOptionalPath returns an OptionalPath that is invalid with the given reason.
+func InvalidOptionalPath(reason string) OptionalPath {
+
+ return OptionalPath{invalidReason: reason}
}
// Valid returns whether there is a valid path
func (p OptionalPath) Valid() bool {
- return p.valid
+ return p.path != nil
}
// Path returns the Path embedded in this OptionalPath. You must be sure that
// there is a valid path, since this method will panic if there is not.
func (p OptionalPath) Path() Path {
- if !p.valid {
- panic("Requesting an invalid path")
+ if p.path == nil {
+ msg := "Requesting an invalid path"
+ if p.invalidReason != "" {
+ msg += ": " + p.invalidReason
+ }
+ panic(msg)
}
return p.path
}
+// InvalidReason returns the reason that the optional path is invalid, or "" if it is valid.
+func (p OptionalPath) InvalidReason() string {
+ if p.path != nil {
+ return ""
+ }
+ if p.invalidReason == "" {
+ return "unknown"
+ }
+ return p.invalidReason
+}
+
// AsPaths converts the OptionalPath into Paths.
//
// It returns nil if this is not valid, or a single length slice containing the Path embedded in
// this OptionalPath.
func (p OptionalPath) AsPaths() Paths {
- if !p.valid {
+ if p.path == nil {
return nil
}
return Paths{p.path}
@@ -303,7 +321,7 @@
// RelativeToTop returns an OptionalPath with the path that was embedded having been replaced by the
// result of calling Path.RelativeToTop on it.
func (p OptionalPath) RelativeToTop() OptionalPath {
- if !p.valid {
+ if p.path == nil {
return p
}
p.path = p.path.RelativeToTop()
@@ -312,7 +330,7 @@
// String returns the string version of the Path, or "" if it isn't valid.
func (p OptionalPath) String() string {
- if p.valid {
+ if p.path != nil {
return p.path.String()
} else {
return ""
@@ -1077,6 +1095,7 @@
path, err := pathForSource(ctx, pathComponents...)
if err != nil {
reportPathError(ctx, err)
+ // No need to put the error message into the returned path since it has been reported already.
return OptionalPath{}
}
@@ -1091,7 +1110,7 @@
return OptionalPath{}
}
if !exists {
- return OptionalPath{}
+ return InvalidOptionalPath(path.String() + " does not exist")
}
return OptionalPathForPath(path)
}
@@ -1127,6 +1146,7 @@
relDir = srcPath.path
} else {
ReportPathErrorf(ctx, "Cannot find relative path for %s(%s)", reflect.TypeOf(path).Name(), path)
+ // No need to put the error message into the returned path since it has been reported already.
return OptionalPath{}
}
dir := filepath.Join(p.srcDir, p.path, relDir)
@@ -1140,7 +1160,7 @@
return OptionalPath{}
}
if len(paths) == 0 {
- return OptionalPath{}
+ return InvalidOptionalPath(dir + " does not exist")
}
relPath := Rel(ctx, p.srcDir, paths[0])
return OptionalPathForPath(PathForSource(ctx, relPath))
diff --git a/android/paths_test.go b/android/paths_test.go
index f4e4ce1..3f4625d 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -137,26 +137,35 @@
func TestOptionalPath(t *testing.T) {
var path OptionalPath
- checkInvalidOptionalPath(t, path)
+ checkInvalidOptionalPath(t, path, "unknown")
path = OptionalPathForPath(nil)
- checkInvalidOptionalPath(t, path)
+ checkInvalidOptionalPath(t, path, "unknown")
+
+ path = InvalidOptionalPath("foo")
+ checkInvalidOptionalPath(t, path, "foo")
+
+ path = InvalidOptionalPath("")
+ checkInvalidOptionalPath(t, path, "unknown")
path = OptionalPathForPath(PathForTesting("path"))
checkValidOptionalPath(t, path, "path")
}
-func checkInvalidOptionalPath(t *testing.T, path OptionalPath) {
+func checkInvalidOptionalPath(t *testing.T, path OptionalPath, expectedInvalidReason string) {
t.Helper()
if path.Valid() {
- t.Errorf("Uninitialized OptionalPath should not be valid")
+ t.Errorf("Invalid OptionalPath should not be valid")
+ }
+ if path.InvalidReason() != expectedInvalidReason {
+ t.Errorf("Wrong invalid reason: expected %q, got %q", expectedInvalidReason, path.InvalidReason())
}
if path.String() != "" {
- t.Errorf("Uninitialized OptionalPath String() should return \"\", not %q", path.String())
+ t.Errorf("Invalid OptionalPath String() should return \"\", not %q", path.String())
}
paths := path.AsPaths()
if len(paths) != 0 {
- t.Errorf("Uninitialized OptionalPath AsPaths() should return empty Paths, not %q", paths)
+ t.Errorf("Invalid OptionalPath AsPaths() should return empty Paths, not %q", paths)
}
defer func() {
if r := recover(); r == nil {
@@ -171,6 +180,9 @@
if !path.Valid() {
t.Errorf("Initialized OptionalPath should not be invalid")
}
+ if path.InvalidReason() != "" {
+ t.Errorf("Initialized OptionalPath should not have an invalid reason, got: %q", path.InvalidReason())
+ }
if path.String() != expectedString {
t.Errorf("Initialized OptionalPath String() should return %q, not %q", expectedString, path.String())
}
diff --git a/android/testing.go b/android/testing.go
index 7a89fc4..b9d8fa8 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -808,7 +808,7 @@
}
func (b baseTestingComponent) maybeBuildParamsFromOutput(file string) (TestingBuildParams, []string) {
- var searchedOutputs []string
+ searchedOutputs := WritablePaths(nil)
for _, p := range b.provider.BuildParamsForTests() {
outputs := append(WritablePaths(nil), p.Outputs...)
outputs = append(outputs, p.ImplicitOutputs...)
@@ -819,10 +819,17 @@
if f.String() == file || f.Rel() == file || PathRelativeToTop(f) == file {
return b.newTestingBuildParams(p), nil
}
- searchedOutputs = append(searchedOutputs, f.Rel())
+ searchedOutputs = append(searchedOutputs, f)
}
}
- return TestingBuildParams{}, searchedOutputs
+
+ formattedOutputs := []string{}
+ for _, f := range searchedOutputs {
+ formattedOutputs = append(formattedOutputs,
+ fmt.Sprintf("%s (rel=%s)", PathRelativeToTop(f), f.Rel()))
+ }
+
+ return TestingBuildParams{}, formattedOutputs
}
func (b baseTestingComponent) buildParamsFromOutput(file string) TestingBuildParams {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index bcbf1ad..2a2a1f4 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2187,6 +2187,7 @@
name string
expectedError string
bp string
+ preparer android.FixturePreparer
}{
{
name: "Non-updatable apex with non-stable dep",
@@ -2258,6 +2259,30 @@
`,
},
{
+ name: "Updatable apex with non-stable legacy core platform dep",
+ expectedError: `\Qcannot depend on "myjar-uses-legacy": non stable SDK core_platform_current - uses legacy core platform\E`,
+ bp: `
+ apex {
+ name: "myapex",
+ java_libs: ["myjar-uses-legacy"],
+ key: "myapex.key",
+ updatable: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ java_library {
+ name: "myjar-uses-legacy",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "core_platform",
+ apex_available: ["myapex"],
+ }
+ `,
+ preparer: java.FixtureUseLegacyCorePlatformApi("myjar-uses-legacy"),
+ },
+ {
name: "Updatable apex with non-stable transitive dep",
// This is not actually detecting that the transitive dependency is unstable, rather it is
// detecting that the transitive dependency is building against a wider API surface than the
@@ -2293,12 +2318,22 @@
}
for _, test := range testCases {
+ if test.name != "Updatable apex with non-stable legacy core platform dep" {
+ continue
+ }
t.Run(test.name, func(t *testing.T) {
- if test.expectedError == "" {
- testApex(t, test.bp)
- } else {
- testApexError(t, test.expectedError, test.bp)
+ errorHandler := android.FixtureExpectsNoErrors
+ if test.expectedError != "" {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
}
+ android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ android.OptionalFixturePreparer(test.preparer),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, test.bp)
})
}
}
diff --git a/cmd/run_with_timeout/run_with_timeout_test.go b/cmd/run_with_timeout/run_with_timeout_test.go
index ed6ec11..6729e61 100644
--- a/cmd/run_with_timeout/run_with_timeout_test.go
+++ b/cmd/run_with_timeout/run_with_timeout_test.go
@@ -50,7 +50,7 @@
args: args{
command: "echo",
args: []string{"foo"},
- timeout: 1 * time.Second,
+ timeout: 10 * time.Second,
},
wantStdout: "foo\n",
},
@@ -58,7 +58,7 @@
name: "timed out",
args: args{
command: "sh",
- args: []string{"-c", "sleep 1 && echo foo"},
+ args: []string{"-c", "sleep 10 && echo foo"},
timeout: 1 * time.Millisecond,
},
wantStderr: ".*: process timed out after .*\n",
@@ -68,7 +68,7 @@
name: "on_timeout command",
args: args{
command: "sh",
- args: []string{"-c", "sleep 1 && echo foo"},
+ args: []string{"-c", "sleep 10 && echo foo"},
timeout: 1 * time.Millisecond,
onTimeoutCmd: "echo bar",
},
diff --git a/java/base.go b/java/base.go
index 86022c3..78aaa19 100644
--- a/java/base.go
+++ b/java/base.go
@@ -382,7 +382,7 @@
return nil
}
if sdkVersion.Kind == android.SdkCorePlatform {
- if useLegacyCorePlatformApiByName(j.BaseModuleName()) {
+ if useLegacyCorePlatformApi(ctx, j.BaseModuleName()) {
return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion)
} else {
// Treat stable core platform as stable.
@@ -643,6 +643,11 @@
} else if j.shouldInstrumentStatic(ctx) {
ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
}
+
+ if j.useCompose() {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
+ "androidx.compose.compiler_compiler-hosted")
+ }
}
func hasSrcExt(srcs []string, ext string) bool {
@@ -911,6 +916,12 @@
if ctx.Device() {
kotlincFlags = append(kotlincFlags, "-no-jdk")
}
+
+ for _, plugin := range deps.kotlinPlugins {
+ kotlincFlags = append(kotlincFlags, "-Xplugin="+plugin.String())
+ }
+ flags.kotlincDeps = append(flags.kotlincDeps, deps.kotlinPlugins...)
+
if len(kotlincFlags) > 0 {
// optimization.
ctx.Variable(pctx, "kotlincFlags", strings.Join(kotlincFlags, " "))
@@ -1325,6 +1336,10 @@
j.outputFile = outputFile.WithoutRel()
}
+func (j *Module) useCompose() bool {
+ return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs)
+}
+
// Returns a copy of the supplied flags, but with all the errorprone-related
// fields copied to the regular build's fields.
func enableErrorproneFlags(flags javaBuilderFlags) javaBuilderFlags {
@@ -1755,6 +1770,8 @@
deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...)
case kotlinAnnotationsTag:
deps.kotlinAnnotations = dep.HeaderJars
+ case kotlinPluginTag:
+ deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...)
case syspropPublicStubDepTag:
// This is a sysprop implementation library, forward the JavaInfoProvider from
// the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
diff --git a/java/builder.go b/java/builder.go
index ea011b8..ae124a3 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -263,6 +263,7 @@
kotlincFlags string
kotlincClasspath classpath
+ kotlincDeps android.Paths
proto android.ProtoFlags
}
diff --git a/java/dex.go b/java/dex.go
index 667800f..8045b5c 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -32,6 +32,9 @@
// list of module-specific flags that will be used for dex compiles
Dxflags []string `android:"arch_variant"`
+ // A list of files containing rules that specify the classes to keep in the main dex file.
+ Main_dex_rules []string `android:"path"`
+
Optimize struct {
// If false, disable all optimization. Defaults to true for android_app and android_test
// modules, false for java_library and java_test modules.
@@ -164,13 +167,20 @@
}, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir",
"r8Flags", "zipFlags", "tmpJar"}, []string{"implicits"})
-func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion android.SdkSpec) []string {
- flags := d.dexProperties.Dxflags
+func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
+ minSdkVersion android.SdkSpec) (flags []string, deps android.Paths) {
+
+ flags = d.dexProperties.Dxflags
// Translate all the DX flags to D8 ones until all the build files have been migrated
// to D8 flags. See: b/69377755
flags = android.RemoveListFromList(flags,
[]string{"--core-library", "--dex", "--multi-dex"})
+ for _, f := range android.PathsForModuleSrc(ctx, d.dexProperties.Main_dex_rules) {
+ flags = append(flags, "--main-dex-rules", f.String())
+ deps = append(deps, f)
+ }
+
if ctx.Config().Getenv("NO_OPTIMIZE_DX") != "" {
flags = append(flags, "--debug")
}
@@ -187,7 +197,7 @@
}
flags = append(flags, "--min-api "+strconv.Itoa(effectiveVersion.FinalOrFutureInt()))
- return flags
+ return flags, deps
}
func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) {
@@ -286,7 +296,7 @@
zipFlags += " -L 0"
}
- commonFlags := d.dexCommonFlags(ctx, minSdkVersion)
+ commonFlags, commonDeps := d.dexCommonFlags(ctx, minSdkVersion)
useR8 := d.effectiveOptimizeEnabled()
if useR8 {
@@ -298,6 +308,7 @@
proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip")
d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
r8Flags, r8Deps := d.r8Flags(ctx, flags)
+ r8Deps = append(r8Deps, commonDeps...)
rule := r8
args := map[string]string{
"r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
@@ -324,6 +335,7 @@
})
} else {
d8Flags, d8Deps := d8Flags(flags)
+ d8Deps = append(d8Deps, commonDeps...)
rule := d8
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_D8") {
rule = d8RE
diff --git a/java/java.go b/java/java.go
index e2665ef..2ca4ac8 100644
--- a/java/java.go
+++ b/java/java.go
@@ -286,6 +286,7 @@
frameworkResTag = dependencyTag{name: "framework-res"}
kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
+ kotlinPluginTag = dependencyTag{name: "kotlin-plugin"}
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
certificateTag = dependencyTag{name: "certificate"}
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
@@ -380,6 +381,7 @@
aidlPreprocess android.OptionalPath
kotlinStdlib android.Paths
kotlinAnnotations android.Paths
+ kotlinPlugins android.Paths
disableTurbine bool
}
diff --git a/java/kotlin.go b/java/kotlin.go
index 3a6fc0f..e4f1bc1 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -81,6 +81,7 @@
var deps android.Paths
deps = append(deps, flags.kotlincClasspath...)
+ deps = append(deps, flags.kotlincDeps...)
deps = append(deps, srcJars...)
deps = append(deps, commonSrcFiles...)
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index db30696..cac0af3 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -281,3 +281,46 @@
})
}
}
+
+func TestKotlinCompose(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "androidx.compose.runtime_runtime",
+ }
+
+ java_library_host {
+ name: "androidx.compose.compiler_compiler-hosted",
+ }
+
+ java_library {
+ name: "withcompose",
+ srcs: ["a.kt"],
+ static_libs: ["androidx.compose.runtime_runtime"],
+ }
+
+ java_library {
+ name: "nocompose",
+ srcs: ["a.kt"],
+ }
+ `)
+
+ buildOS := result.Config.BuildOS.String()
+
+ composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted", buildOS+"_common").Rule("combineJar").Output
+ withCompose := result.ModuleForTests("withcompose", "android_common")
+ noCompose := result.ModuleForTests("nocompose", "android_common")
+
+ android.AssertStringListContains(t, "missing compose compiler dependency",
+ withCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String())
+
+ android.AssertStringDoesContain(t, "missing compose compiler plugin",
+ withCompose.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+composeCompiler.String())
+
+ android.AssertStringListDoesNotContain(t, "unexpected compose compiler dependency",
+ noCompose.Rule("kotlinc").Implicits.Strings(), composeCompiler.String())
+
+ android.AssertStringDoesNotContain(t, "unexpected compose compiler plugin",
+ noCompose.VariablesForTestsRelativeToTop()["kotlincFlags"], "-Xplugin="+composeCompiler.String())
+}
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 8c401a7..7749310 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -163,17 +163,27 @@
}
}
-func useLegacyCorePlatformApi(ctx android.EarlyModuleContext) bool {
- return useLegacyCorePlatformApiByName(ctx.ModuleName())
+var legacyCorePlatformApiLookupKey = android.NewOnceKey("legacyCorePlatformApiLookup")
+
+func getLegacyCorePlatformApiLookup(config android.Config) map[string]struct{} {
+ return config.Once(legacyCorePlatformApiLookupKey, func() interface{} {
+ return legacyCorePlatformApiLookup
+ }).(map[string]struct{})
}
-func useLegacyCorePlatformApiByName(name string) bool {
- _, found := legacyCorePlatformApiLookup[name]
+// useLegacyCorePlatformApi checks to see whether the supplied module name is in the list of modules
+// that are able to use the legacy core platform API and returns true if it does, false otherwise.
+//
+// This method takes the module name separately from the context as this may be being called for a
+// module that is not the target of the supplied context.
+func useLegacyCorePlatformApi(ctx android.EarlyModuleContext, moduleName string) bool {
+ lookup := getLegacyCorePlatformApiLookup(ctx.Config())
+ _, found := lookup[moduleName]
return found
}
func corePlatformSystemModules(ctx android.EarlyModuleContext) string {
- if useLegacyCorePlatformApi(ctx) {
+ if useLegacyCorePlatformApi(ctx, ctx.ModuleName()) {
return config.LegacyCorePlatformSystemModules
} else {
return config.StableCorePlatformSystemModules
@@ -181,7 +191,7 @@
}
func corePlatformBootclasspathLibraries(ctx android.EarlyModuleContext) []string {
- if useLegacyCorePlatformApi(ctx) {
+ if useLegacyCorePlatformApi(ctx, ctx.ModuleName()) {
return config.LegacyCorePlatformBootclasspathLibraries
} else {
return config.StableCorePlatformBootclasspathLibraries
diff --git a/java/testing.go b/java/testing.go
index d8a77cf..a642753 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -229,6 +229,26 @@
)
}
+// FixtureUseLegacyCorePlatformApi prepares the fixture by setting the exception list of those
+// modules that are allowed to use the legacy core platform API to be the ones supplied.
+func FixtureUseLegacyCorePlatformApi(moduleNames ...string) android.FixturePreparer {
+ lookup := make(map[string]struct{})
+ for _, moduleName := range moduleNames {
+ lookup[moduleName] = struct{}{}
+ }
+ return android.FixtureModifyConfig(func(config android.Config) {
+ // Try and set the legacyCorePlatformApiLookup in the config, the returned value will be the
+ // actual value that is set.
+ cached := config.Once(legacyCorePlatformApiLookupKey, func() interface{} {
+ return lookup
+ })
+ // Make sure that the cached value is the one we need.
+ if !reflect.DeepEqual(cached, lookup) {
+ panic(fmt.Errorf("attempting to set legacyCorePlatformApiLookupKey to %q but it has already been set to %q", lookup, cached))
+ }
+ })
+}
+
// registerRequiredBuildComponentsForTest registers the build components used by
// PrepareForTestWithJavaDefaultModules.
//
diff --git a/mk2rbc/Android.bp b/mk2rbc/Android.bp
index 4fa3eb6..b18bfc7 100644
--- a/mk2rbc/Android.bp
+++ b/mk2rbc/Android.bp
@@ -38,6 +38,7 @@
"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 209e82b..7b5f298 100644
--- a/mk2rbc/cmd/mk2rbc.go
+++ b/mk2rbc/cmd/mk2rbc.go
@@ -81,6 +81,7 @@
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 @@
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 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 b05d340..b9b7e2c 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -1618,12 +1618,12 @@
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 0000000..1666392
--- /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 0000000..27e8198
--- /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 0000000..c78fa32
--- /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"))
+ }
+
+}
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 71fe358..b4936b8 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -358,7 +358,7 @@
# the check has failed.
if args.enforce_uses_libraries_status:
with open(args.enforce_uses_libraries_status, 'w') as f:
- if not errmsg is not None:
+ if errmsg is not None:
f.write('%s\n' % errmsg)
if args.extract_target_sdk_version: