diff --git a/Android.bp b/Android.bp index 9c2bb4366..fe776df54 100644 --- a/Android.bp +++ b/Android.bp @@ -186,6 +186,7 @@ bootstrap_go_package { "cc/rs.go", "cc/sanitize.go", "cc/sabi.go", + "cc/sdk.go", "cc/snapshot_utils.go", "cc/stl.go", "cc/strip.go", diff --git a/android/neverallow.go b/android/neverallow.go index 8fcfb8a6e..547230c08 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -53,6 +53,7 @@ func init() { AddNeverAllowRules(createLibcoreRules()...) AddNeverAllowRules(createMediaRules()...) AddNeverAllowRules(createJavaDeviceForHostRules()...) + AddNeverAllowRules(createCcSdkVariantRules()...) } // Add a NeverAllow rule to the set of rules to apply. @@ -175,6 +176,37 @@ func createJavaDeviceForHostRules() []Rule { } } +func createCcSdkVariantRules() []Rule { + sdkVersionOnlyWhitelist := []string{ + // derive_sdk_prefer32 has stem: "derive_sdk" which conflicts with the derive_sdk. + // This sometimes works because the APEX modules that contain derive_sdk and + // derive_sdk_prefer32 suppress the platform installation rules, but fails when + // the APEX modules contain the SDK variant and the platform variant still exists. + "frameworks/base/apex/sdkextensions/derive_sdk", + } + + platformVariantPropertiesWhitelist := []string{ + // android_native_app_glue and libRSSupport use native_window.h but target old + // sdk versions (minimum and 9 respectively) where libnativewindow didn't exist, + // so they can't add libnativewindow to shared_libs to get the header directory + // for the platform variant. Allow them to use the platform variant + // property to set shared_libs. + "prebuilts/ndk", + "frameworks/rs", + } + + return []Rule{ + NeverAllow(). + NotIn(sdkVersionOnlyWhitelist...). + WithMatcher("sdk_variant_only", isSetMatcherInstance). + Because("sdk_variant_only can only be used in whitelisted projects"), + NeverAllow(). + NotIn(platformVariantPropertiesWhitelist...). + WithMatcher("platform.shared_libs", isSetMatcherInstance). + Because("platform variant properties can only be used in whitelisted projects"), + } +} + func neverallowMutator(ctx BottomUpMutatorContext) { m, ok := ctx.Module().(Module) if !ok { @@ -254,6 +286,18 @@ func (m *startsWithMatcher) String() string { return ".starts-with(" + m.prefix + ")" } +type isSetMatcher struct{} + +func (m *isSetMatcher) test(value string) bool { + return value != "" +} + +func (m *isSetMatcher) String() string { + return ".is-set" +} + +var isSetMatcherInstance = &isSetMatcher{} + type ruleProperty struct { fields []string // e.x.: Vndk.Enabled matcher ValueMatcher diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 6f07a4a73..41e5c6fed 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -249,6 +249,50 @@ var neverallowTests = []struct { }`), }, }, + // CC sdk rule tests + { + name: `"sdk_variant_only" outside whitelist`, + fs: map[string][]byte{ + "Android.bp": []byte(` + cc_library { + name: "outside_whitelist", + sdk_version: "current", + sdk_variant_only: true, + }`), + }, + expectedErrors: []string{ + `module "outside_whitelist": violates neverallow`, + }, + }, + { + name: `"sdk_variant_only: false" outside whitelist`, + fs: map[string][]byte{ + "Android.bp": []byte(` + cc_library { + name: "outside_whitelist", + sdk_version: "current", + sdk_variant_only: false, + }`), + }, + expectedErrors: []string{ + `module "outside_whitelist": violates neverallow`, + }, + }, + { + name: `"platform" outside whitelist`, + fs: map[string][]byte{ + "Android.bp": []byte(` + cc_library { + name: "outside_whitelist", + platform: { + shared_libs: ["libfoo"], + }, + }`), + }, + expectedErrors: []string{ + `module "outside_whitelist": violates neverallow`, + }, + }, } func TestNeverallow(t *testing.T) { @@ -289,6 +333,8 @@ type mockCcLibraryProperties struct { Include_dirs []string Vendor_available *bool Static_libs []string + Sdk_version *string + Sdk_variant_only *bool Vndk struct { Enabled *bool @@ -305,6 +351,10 @@ type mockCcLibraryProperties struct { Cflags []string } } + + Platform struct { + Shared_libs []string + } } type mockCcLibraryModule struct { diff --git a/apex/apex_test.go b/apex/apex_test.go index 5468c77bf..dbccb9217 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3350,7 +3350,7 @@ func TestApexWithApps(t *testing.T) { } // JNI libraries including transitive deps are for _, jni := range []string{"libjni", "libfoo"} { - jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module).OutputFile() + jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_myapex").Module().(*cc.Module).OutputFile() // ... embedded inside APK (jnilibs.zip) ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String()) // ... and not directly inside the APEX diff --git a/apex/vndk_test.go b/apex/vndk_test.go index a9e26adc8..863d40dda 100644 --- a/apex/vndk_test.go +++ b/apex/vndk_test.go @@ -90,6 +90,7 @@ func TestVndkApexUsesVendorVariant(t *testing.T) { system_shared_libs: [], stl: "none", notice: "custom_notice", + sdk_version: "current", } cc_library { name: "libprofile-clang-extras_ndk", @@ -98,6 +99,7 @@ func TestVndkApexUsesVendorVariant(t *testing.T) { system_shared_libs: [], stl: "none", notice: "custom_notice", + sdk_version: "current", } `, func(fs map[string][]byte, config android.Config) { config.TestProductVariables.Native_coverage = proptools.BoolPtr(true) diff --git a/cc/androidmk.go b/cc/androidmk.go index ef695b003..19c71826f 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -29,6 +29,7 @@ var ( vendorSuffix = ".vendor" ramdiskSuffix = ".ramdisk" recoverySuffix = ".recovery" + sdkSuffix = ".sdk" ) type AndroidMkContext interface { @@ -103,6 +104,28 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { } } } + if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake { + // Make the SDK variant uninstallable so that there are not two rules to install + // to the same location. + entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) + // Add the unsuffixed name to SOONG_SDK_VARIANT_MODULES so that Make can rewrite + // dependencies to the .sdk suffix when building a module that uses the SDK. + entries.SetString("SOONG_SDK_VARIANT_MODULES", + "$(SOONG_SDK_VARIANT_MODULES) $(patsubst %.sdk,%,$(LOCAL_MODULE))") + } + }, + }, + ExtraFooters: []android.AndroidMkExtraFootersFunc{ + func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) { + if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake && + c.CcLibraryInterface() && c.Shared() { + // Using the SDK variant as a JNI library needs a copy of the .so that + // is not named .sdk.so so that it can be packaged into the APK with + // the right name. + fmt.Fprintln(w, "$(eval $(call copy-one-file,", + "$(LOCAL_BUILT_MODULE),", + "$(patsubst %.sdk.so,%.so,$(LOCAL_BUILT_MODULE))))") + } }, }, } @@ -393,6 +416,9 @@ func (library *toolchainLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, } func (installer *baseInstaller) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { + if installer.path == (android.InstallPath{}) { + return + } // Soong installation is only supported for host modules. Have Make // installation trigger Soong installation. if ctx.Target().Os.Class == android.Host { diff --git a/cc/cc.go b/cc/cc.go index 037b99cab..794adf134 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -42,6 +42,7 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_defaults", defaultsFactory) ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { + ctx.BottomUp("sdk", sdkMutator).Parallel() ctx.BottomUp("vndk", VndkMutator).Parallel() ctx.BottomUp("link", LinkageMutator).Parallel() ctx.BottomUp("ndk_api", NdkApiMutator).Parallel() @@ -208,9 +209,13 @@ type BaseProperties struct { // Deprecated. true is the default, false is invalid. Clang *bool `android:"arch_variant"` - // Minimum sdk version supported when compiling against the ndk + // Minimum sdk version supported when compiling against the ndk. Setting this property causes + // two variants to be built, one for the platform and one for apps. Sdk_version *string + // If true, always create an sdk variant and don't create a platform variant. + Sdk_variant_only *bool + AndroidMkSharedLibs []string `blueprint:"mutated"` AndroidMkStaticLibs []string `blueprint:"mutated"` AndroidMkRuntimeLibs []string `blueprint:"mutated"` @@ -252,6 +257,16 @@ type BaseProperties struct { SnapshotRuntimeLibs []string `blueprint:"mutated"` Installable *bool + + // Set by factories of module types that can only be referenced from variants compiled against + // the SDK. + AlwaysSdk bool `blueprint:"mutated"` + + // Variant is an SDK variant created by sdkMutator + IsSdkVariant bool `blueprint:"mutated"` + // Set when both SDK and platform variants are exported to Make to trigger renaming the SDK + // variant to have a ".sdk" suffix. + SdkAndPlatformVariantVisibleToMake bool `blueprint:"mutated"` } type VendorProperties struct { @@ -527,7 +542,10 @@ func (c *Module) Shared() bool { } func (c *Module) SelectedStl() string { - return c.stl.Properties.SelectedStl + if c.stl != nil { + return c.stl.Properties.SelectedStl + } + return "" } func (c *Module) ToolchainLibrary() bool { @@ -555,6 +573,10 @@ func (c *Module) SdkVersion() string { return String(c.Properties.Sdk_version) } +func (c *Module) AlwaysSdk() bool { + return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only) +} + func (c *Module) IncludeDirs() android.Paths { if c.linker != nil { if library, ok := c.linker.(exportedFlagsProducer); ok { @@ -803,6 +825,17 @@ func (c *Module) UseVndk() bool { return c.Properties.VndkVersion != "" } +func (c *Module) canUseSdk() bool { + return c.Os() == android.Android && !c.UseVndk() && !c.InRamdisk() && !c.InRecovery() +} + +func (c *Module) UseSdk() bool { + if c.canUseSdk() { + return String(c.Properties.Sdk_version) != "" + } + return false +} + func (c *Module) isCoverageVariant() bool { return c.coverage.Properties.IsCoverageVariant } @@ -1060,14 +1093,11 @@ func (ctx *moduleContextImpl) header() bool { } func (ctx *moduleContextImpl) canUseSdk() bool { - return ctx.ctx.Device() && !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inRecovery() && !ctx.ctx.Fuchsia() + return ctx.mod.canUseSdk() } func (ctx *moduleContextImpl) useSdk() bool { - if ctx.canUseSdk() { - return String(ctx.mod.Properties.Sdk_version) != "" - } - return false + return ctx.mod.UseSdk() } func (ctx *moduleContextImpl) sdkVersion() string { @@ -1386,6 +1416,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { c.Properties.SubName += ramdiskSuffix } else if c.InRecovery() && !c.OnlyInRecovery() { c.Properties.SubName += recoverySuffix + } else if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake { + c.Properties.SubName += sdkSuffix } ctx := &moduleContext{ diff --git a/cc/genrule.go b/cc/genrule.go index 155e410dc..9331448b8 100644 --- a/cc/genrule.go +++ b/cc/genrule.go @@ -27,6 +27,7 @@ type GenruleExtraProperties struct { Vendor_available *bool Ramdisk_available *bool Recovery_available *bool + Sdk_version *string } // cc_genrule is a genrule that can depend on other cc_* objects. diff --git a/cc/library.go b/cc/library.go index 346e7d84d..5ce854ed0 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1223,7 +1223,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { if Bool(library.Properties.Static_ndk_lib) && library.static() && !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inRecovery() && ctx.Device() && library.baseLinker.sanitize.isUnsanitizedVariant() && - !library.buildStubs() { + !library.buildStubs() && ctx.sdkVersion() == "" { installPath := getNdkSysrootBase(ctx).Join( ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base()) diff --git a/cc/linkable.go b/cc/linkable.go index 80cd6b8a2..fbe61a4f4 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -45,12 +45,14 @@ type LinkableInterface interface { InRecovery() bool OnlyInRecovery() bool + UseSdk() bool UseVndk() bool MustUseVendorVariant() bool IsVndk() bool HasVendorVariant() bool SdkVersion() string + AlwaysSdk() bool ToolchainLibrary() bool NdkPrebuiltStl() bool diff --git a/cc/linker.go b/cc/linker.go index ae5ee0ac3..385e04e16 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -158,6 +158,13 @@ type BaseLinkerProperties struct { // the ramdisk variant of the C/C++ module. Exclude_static_libs []string } + Platform struct { + // list of shared libs that should be use to build the platform variant + // of a module that sets sdk_version. This should rarely be necessary, + // in most cases the same libraries are available for the SDK and platform + // variants. + Shared_libs []string + } } // make android::build:GetBuildNumber() available containing the build ID. @@ -255,6 +262,10 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs) } + if !ctx.useSdk() { + deps.SharedLibs = append(deps.SharedLibs, linker.Properties.Target.Platform.Shared_libs...) + } + if ctx.toolchain().Bionic() { // libclang_rt.builtins and libatomic have to be last on the command line if !Bool(linker.Properties.No_libcrt) { diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 2a86d3362..68d4ac067 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -381,6 +381,9 @@ func newStubLibrary() *Module { module.linker = stub module.installer = stub + module.Properties.AlwaysSdk = true + module.Properties.Sdk_version = StringPtr("current") + module.AddProperties(&stub.properties, &library.MutatedProperties) return module diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go index e849aeea4..f909add43 100644 --- a/cc/ndk_prebuilt.go +++ b/cc/ndk_prebuilt.go @@ -76,6 +76,8 @@ func NdkPrebuiltObjectFactory() android.Module { baseLinker: NewBaseLinker(nil), }, } + module.Properties.AlwaysSdk = true + module.Properties.Sdk_version = StringPtr("current") module.Properties.HideFromMake = true return module.Init() } @@ -115,10 +117,9 @@ func NdkPrebuiltSharedStlFactory() android.Module { libraryDecorator: library, } module.installer = nil - minVersionString := "minimum" - noStlString := "none" - module.Properties.Sdk_version = &minVersionString - module.stl.Properties.Stl = &noStlString + module.Properties.Sdk_version = StringPtr("minimum") + module.Properties.AlwaysSdk = true + module.stl.Properties.Stl = StringPtr("none") return module.Init() } @@ -135,6 +136,9 @@ func NdkPrebuiltStaticStlFactory() android.Module { } module.installer = nil module.Properties.HideFromMake = true + module.Properties.AlwaysSdk = true + module.Properties.Sdk_version = StringPtr("current") + module.stl.Properties.Stl = StringPtr("none") module.ModuleBase.EnableNativeBridgeSupportByDefault() return module.Init() } diff --git a/cc/sdk.go b/cc/sdk.go new file mode 100644 index 000000000..d05a04a12 --- /dev/null +++ b/cc/sdk.go @@ -0,0 +1,65 @@ +// Copyright 2020 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 cc + +import ( + "android/soong/android" + "android/soong/genrule" +) + +// sdkMutator sets a creates a platform and an SDK variant for modules +// that set sdk_version, and ignores sdk_version for the platform +// variant. The SDK variant will be used for embedding in APKs +// that may be installed on older platforms. Apexes use their own +// variants that enforce backwards compatibility. +func sdkMutator(ctx android.BottomUpMutatorContext) { + if ctx.Os() != android.Android { + return + } + + switch m := ctx.Module().(type) { + case LinkableInterface: + if m.AlwaysSdk() { + if !m.UseSdk() { + ctx.ModuleErrorf("UseSdk() must return true when AlwaysSdk is set, did the factory forget to set Sdk_version?") + } + ctx.CreateVariations("sdk") + } else if m.UseSdk() { + modules := ctx.CreateVariations("", "sdk") + modules[0].(*Module).Properties.Sdk_version = nil + modules[1].(*Module).Properties.IsSdkVariant = true + + if ctx.Config().UnbundledBuild() { + modules[0].(*Module).Properties.HideFromMake = true + } else { + modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true + modules[1].(*Module).Properties.PreventInstall = true + } + ctx.AliasVariation("") + } else { + ctx.CreateVariations("") + ctx.AliasVariation("") + } + case *genrule.Module: + if p, ok := m.Extra.(*GenruleExtraProperties); ok { + if String(p.Sdk_version) != "" { + ctx.CreateVariations("", "sdk") + } else { + ctx.CreateVariations("") + } + ctx.AliasVariation("") + } + } +} diff --git a/cc/sdk_test.go b/cc/sdk_test.go new file mode 100644 index 000000000..5a3c181dc --- /dev/null +++ b/cc/sdk_test.go @@ -0,0 +1,102 @@ +// Copyright 2020 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 cc + +import ( + "testing" + + "android/soong/android" +) + +func TestSdkMutator(t *testing.T) { + bp := ` + cc_library { + name: "libsdk", + shared_libs: ["libsdkdep"], + sdk_version: "current", + stl: "c++_shared", + } + + cc_library { + name: "libsdkdep", + sdk_version: "current", + stl: "c++_shared", + } + + cc_library { + name: "libplatform", + shared_libs: ["libsdk"], + stl: "libc++", + } + + cc_binary { + name: "platformbinary", + shared_libs: ["libplatform"], + stl: "libc++", + } + + cc_binary { + name: "sdkbinary", + shared_libs: ["libsdk"], + sdk_version: "current", + stl: "libc++", + } + ` + + assertDep := func(t *testing.T, from, to android.TestingModule) { + t.Helper() + found := false + + var toFile android.Path + m := to.Module().(*Module) + if toc := m.Toc(); toc.Valid() { + toFile = toc.Path() + } else { + toFile = m.outputFile.Path() + } + + rule := from.Description("link") + for _, dep := range rule.Implicits { + if dep.String() == toFile.String() { + found = true + } + } + if !found { + t.Errorf("expected %q in %q", toFile.String(), rule.Implicits.Strings()) + } + } + + ctx := testCc(t, bp) + + libsdkNDK := ctx.ModuleForTests("libsdk", "android_arm64_armv8-a_sdk_shared") + libsdkPlatform := ctx.ModuleForTests("libsdk", "android_arm64_armv8-a_shared") + libsdkdepNDK := ctx.ModuleForTests("libsdkdep", "android_arm64_armv8-a_sdk_shared") + libsdkdepPlatform := ctx.ModuleForTests("libsdkdep", "android_arm64_armv8-a_shared") + libplatform := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared") + platformbinary := ctx.ModuleForTests("platformbinary", "android_arm64_armv8-a") + sdkbinary := ctx.ModuleForTests("sdkbinary", "android_arm64_armv8-a_sdk") + + libcxxNDK := ctx.ModuleForTests("ndk_libc++_shared", "android_arm64_armv8-a_sdk_shared") + libcxxPlatform := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared") + + assertDep(t, libsdkNDK, libsdkdepNDK) + assertDep(t, libsdkPlatform, libsdkdepPlatform) + assertDep(t, libplatform, libsdkPlatform) + assertDep(t, platformbinary, libplatform) + assertDep(t, sdkbinary, libsdkNDK) + + assertDep(t, libsdkNDK, libcxxNDK) + assertDep(t, libsdkPlatform, libcxxPlatform) +} diff --git a/cc/stl.go b/cc/stl.go index 8113f7258..4e74c7fb0 100644 --- a/cc/stl.go +++ b/cc/stl.go @@ -115,9 +115,13 @@ func (stl *stl) begin(ctx BaseModuleContext) { switch s { case "libc++", "libc++_static": return s + case "c++_shared": + return "libc++" + case "c++_static": + return "libc++_static" case "none": return "" - case "": + case "", "system": if ctx.static() { return "libc++_static" } else { diff --git a/cc/testing.go b/cc/testing.go index b8a7eab34..89a9c36dc 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -138,6 +138,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { name: "libgcc_stripped", vendor_available: true, recovery_available: true, + sdk_version: "current", src: "", } @@ -155,6 +156,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { llndk_library { name: "libc", symbol_file: "", + sdk_version: "current", } cc_library { name: "libm", @@ -174,6 +176,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { llndk_library { name: "libm", symbol_file: "", + sdk_version: "current", } cc_library { name: "libdl", @@ -193,6 +196,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { llndk_library { name: "libdl", symbol_file: "", + sdk_version: "current", } cc_library { name: "libft2", @@ -205,6 +209,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { name: "libft2", symbol_file: "", vendor_available: false, + sdk_version: "current", } cc_library { name: "libc++_static", @@ -336,6 +341,16 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { sdk_version: "27", } + ndk_prebuilt_object { + name: "ndk_crtbegin_dynamic.27", + sdk_version: "27", + } + + ndk_prebuilt_object { + name: "ndk_crtend_android.27", + sdk_version: "27", + } + ndk_prebuilt_shared_stl { name: "ndk_libc++_shared", } diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go index dfc6f7679..042e012d9 100644 --- a/cc/toolchain_library.go +++ b/cc/toolchain_library.go @@ -67,6 +67,7 @@ func ToolchainLibraryFactory() android.Module { module.stl = nil module.sanitize = nil module.installer = nil + module.Properties.Sdk_version = StringPtr("current") return module.Init() } diff --git a/java/app.go b/java/app.go index fc3ce97fb..346f1551d 100755 --- a/java/app.go +++ b/java/app.go @@ -204,6 +204,13 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { for _, jniTarget := range ctx.MultiTargets() { variation := append(jniTarget.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"}) + + // If the app builds against an Android SDK use the SDK variant of JNI dependencies + // unless jni_uses_platform_apis is set. + if a.sdkVersion().specified() && a.sdkVersion().kind != sdkCorePlatform && + !Bool(a.appProperties.Jni_uses_platform_apis) { + variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) + } ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...) } diff --git a/java/app_test.go b/java/app_test.go index 0c6da7a47..fa18e9dac 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -791,6 +791,7 @@ func TestJNIABI(t *testing.T) { cc_library { name: "libjni", system_shared_libs: [], + sdk_version: "current", stl: "none", } @@ -928,26 +929,26 @@ func TestJNIPackaging(t *testing.T) { android_test { name: "test", - sdk_version: "core_platform", + sdk_version: "current", jni_libs: ["libjni"], } android_test { name: "test_noembed", - sdk_version: "core_platform", + sdk_version: "current", jni_libs: ["libjni"], use_embedded_native_libs: false, } android_test_helper_app { name: "test_helper", - sdk_version: "core_platform", + sdk_version: "current", jni_libs: ["libjni"], } android_test_helper_app { name: "test_helper_noembed", - sdk_version: "core_platform", + sdk_version: "current", jni_libs: ["libjni"], use_embedded_native_libs: false, } @@ -979,6 +980,10 @@ func TestJNIPackaging(t *testing.T) { if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w { t.Errorf("expected jni compressed %v, got %v", w, g) } + + if !strings.Contains(jniLibZip.Implicits[0].String(), "_sdk_") { + t.Errorf("expected input %q to use sdk variant", jniLibZip.Implicits[0].String()) + } } }) } diff --git a/rust/rust.go b/rust/rust.go index f446ef039..6fe887129 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -164,6 +164,10 @@ func (mod *Module) OnlyInRecovery() bool { return false } +func (mod *Module) UseSdk() bool { + return false +} + func (mod *Module) UseVndk() bool { return false } @@ -184,6 +188,10 @@ func (mod *Module) SdkVersion() string { return "" } +func (mod *Module) AlwaysSdk() bool { + return false +} + func (mod *Module) ToolchainLibrary() bool { return false }