From 11b0fbdbf61ac09067c3b8b706af8f79ffa9bb9b Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Fri, 5 Feb 2021 02:28:22 +0900 Subject: [PATCH] cc: fix version macro for stubs When a cc module is built against a stub, compiler passes version macro of the stub lib. Version macro should be numeric, so codenames or "current" should be mapped to numbers just like how ndkstubgen maps to. * "current" -> future (10000) * codenames -> look up api_level.json * otherwise -> cast to int Bug: 179329813 Test: m / soong test / manually check the output build.ninja Change-Id: Ic0e1dd904984e161694a0b77fad5559c06a4462f --- android/api_levels.go | 20 ++++++++++-- apex/apex_test.go | 74 +++++++++++++++++++++++++++++++++++++++++++ cc/library.go | 8 +++-- 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/android/api_levels.go b/android/api_levels.go index 1b53f3f2a..2f6a9d29d 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -24,6 +24,8 @@ func init() { RegisterSingletonType("api_levels", ApiLevelsSingleton) } +const previewAPILevelBase = 9000 + // An API level, which may be a finalized (numbered) API, a preview (codenamed) // API, or the future API level (10000). Can be parsed from a string with // ApiLevelFromUser or ApiLevelOrPanic. @@ -57,6 +59,21 @@ func (this ApiLevel) FinalOrFutureInt() int { } } +// FinalOrPreviewInt distinguishes preview versions from "current" (future). +// This is for "native" stubs and should be in sync with ndkstubgen/getApiLevelsMap(). +// - "current" -> future (10000) +// - preview codenames -> preview base (9000) + index +// - otherwise -> cast to int +func (this ApiLevel) FinalOrPreviewInt() int { + if this.IsCurrent() { + return this.number + } + if this.IsPreview() { + return previewAPILevelBase + this.number + } + return this.number +} + // Returns the canonical name for this API level. For a finalized API level // this will be the API number as a string. For a preview API level this // will be the codename, or "current". @@ -282,7 +299,6 @@ var apiLevelsMapKey = NewOnceKey("ApiLevelsMap") func getApiLevelsMap(config Config) map[string]int { return config.Once(apiLevelsMapKey, func() interface{} { - baseApiLevel := 9000 apiLevelsMap := map[string]int{ "G": 9, "I": 14, @@ -302,7 +318,7 @@ func getApiLevelsMap(config Config) map[string]int { "R": 30, } for i, codename := range config.PlatformVersionActiveCodenames() { - apiLevelsMap[codename] = baseApiLevel + i + apiLevelsMap[codename] = previewAPILevelBase + i } return apiLevelsMap diff --git a/apex/apex_test.go b/apex/apex_test.go index 7f5be7ec5..85d62590e 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -994,6 +994,80 @@ func TestApexWithStubsWithMinSdkVersion(t *testing.T) { }) } +func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) { + t.Parallel() + // myapex (Z) + // mylib -----------------. + // | + // otherapex (29) | + // libstub's versions: 29 Z current + // | + // | + // libplatform ----------------' + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + native_shared_libs: ["mylib"], + min_sdk_version: "Z", // non-final + } + + cc_library { + name: "mylib", + srcs: ["mylib.cpp"], + shared_libs: ["libstub"], + apex_available: ["myapex"], + min_sdk_version: "Z", + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + apex { + name: "otherapex", + key: "myapex.key", + native_shared_libs: ["libstub"], + min_sdk_version: "29", + } + + cc_library { + name: "libstub", + srcs: ["mylib.cpp"], + stubs: { + versions: ["29", "Z", "current"], + }, + apex_available: ["otherapex"], + min_sdk_version: "29", + } + + // platform module depending on libstub from otherapex should use the latest stub("current") + cc_library { + name: "libplatform", + srcs: ["mylib.cpp"], + shared_libs: ["libstub"], + } + `, func(fs map[string][]byte, config android.Config) { + config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Z") + config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false) + config.TestProductVariables.Platform_version_active_codenames = []string{"Z"} + }) + + // Ensure that mylib from myapex is built against "min_sdk_version" stub ("Z"), which is non-final + mylibCflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"] + ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=9000 ") + mylibLdflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"] + ensureContains(t, mylibLdflags, "libstub/android_arm64_armv8-a_shared_Z/libstub.so ") + + // Ensure that libplatform is built against latest stub ("current") of mylib3 from the apex + libplatformCflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"] + ensureContains(t, libplatformCflags, "-D__LIBSTUB_API__=10000 ") // "current" maps to 10000 + libplatformLdflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"] + ensureContains(t, libplatformLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ") +} + func TestApexWithExplicitStubsDependency(t *testing.T) { ctx, _ := testApex(t, ` apex { diff --git a/cc/library.go b/cc/library.go index 29a3c696a..f185cb793 100644 --- a/cc/library.go +++ b/cc/library.go @@ -19,6 +19,7 @@ import ( "io" "path/filepath" "regexp" + "strconv" "strings" "sync" @@ -1362,8 +1363,11 @@ func (library *libraryDecorator) link(ctx ModuleContext, func (library *libraryDecorator) exportVersioningMacroIfNeeded(ctx android.BaseModuleContext) { if library.buildStubs() && library.stubsVersion() != "" && !library.skipAPIDefine { name := versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx)) - ver := library.stubsVersion() - library.reexportFlags("-D" + name + "=" + ver) + apiLevel, err := android.ApiLevelFromUser(ctx, library.stubsVersion()) + if err != nil { + ctx.ModuleErrorf("Can't export version macro: %s", err.Error()) + } + library.reexportFlags("-D" + name + "=" + strconv.Itoa(apiLevel.FinalOrPreviewInt())) } }