diff options
author | 2020-02-19 16:54:04 -0800 | |
---|---|---|
committer | 2020-04-01 16:09:05 -0700 | |
commit | 82e192c3aeae55337e335101ba83126decd4ddac (patch) | |
tree | 66e6710d15bd5f3d8178863fd5fca9518a5462fd | |
parent | b358ebb7598dc941213ad3a9445e035c5f768fcc (diff) |
Add sdk mutator for native modules
Compiling native modules against the NDK disables platform features
like ASAN. For anything shipped on the system image there is no
reason to compile against the NDK. Add a new mutator to Soong that
creates a platform and an SDK variant for modules that set
sdk_version, and ignore 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.
Test: sdk_test.go
Test: TestJNIPackaging
Bug: 149591340
Change-Id: I7d72934aaee2e1326cc0ba5f29f51f14feec4521
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | android/neverallow.go | 44 | ||||
-rw-r--r-- | android/neverallow_test.go | 50 | ||||
-rw-r--r-- | apex/apex_test.go | 2 | ||||
-rw-r--r-- | apex/vndk_test.go | 2 | ||||
-rw-r--r-- | cc/androidmk.go | 26 | ||||
-rw-r--r-- | cc/cc.go | 46 | ||||
-rw-r--r-- | cc/genrule.go | 1 | ||||
-rw-r--r-- | cc/library.go | 2 | ||||
-rw-r--r-- | cc/linkable.go | 2 | ||||
-rw-r--r-- | cc/linker.go | 11 | ||||
-rw-r--r-- | cc/ndk_library.go | 3 | ||||
-rw-r--r-- | cc/ndk_prebuilt.go | 12 | ||||
-rw-r--r-- | cc/sdk.go | 65 | ||||
-rw-r--r-- | cc/sdk_test.go | 102 | ||||
-rw-r--r-- | cc/stl.go | 6 | ||||
-rw-r--r-- | cc/testing.go | 15 | ||||
-rw-r--r-- | cc/toolchain_library.go | 1 | ||||
-rwxr-xr-x | java/app.go | 7 | ||||
-rw-r--r-- | java/app_test.go | 13 | ||||
-rw-r--r-- | rust/rust.go | 8 |
21 files changed, 401 insertions, 18 deletions
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 { @@ -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) +} @@ -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 } |