Revert^2 "Add sdk mutator for native modules"
f8e80229fedb47302e9cfd32990859a6308020cf
Change-Id: Ic30ab6b844684bfc3e8ece5a1913980d5fbf8de2
diff --git a/cc/androidmk.go b/cc/androidmk.go
index ef695b0..19c7182 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -29,6 +29,7 @@
vendorSuffix = ".vendor"
ramdiskSuffix = ".ramdisk"
recoverySuffix = ".recovery"
+ sdkSuffix = ".sdk"
)
type AndroidMkContext interface {
@@ -103,6 +104,28 @@
}
}
}
+ 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 (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 037b99c..794adf1 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -42,6 +42,7 @@
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 @@
// 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 @@
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) 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 @@
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 @@
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) 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 @@
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 155e410..9331448 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -27,6 +27,7 @@
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 346e7d8..5ce854e 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1223,7 +1223,7 @@
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 80cd6b8..fbe61a4 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -45,12 +45,14 @@
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 ae5ee0a..385e04e 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -158,6 +158,13 @@
// 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 @@
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 2a86d33..68d4ac0 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -381,6 +381,9 @@
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 e849aee..f909add 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -76,6 +76,8 @@
baseLinker: NewBaseLinker(nil),
},
}
+ module.Properties.AlwaysSdk = true
+ module.Properties.Sdk_version = StringPtr("current")
module.Properties.HideFromMake = true
return module.Init()
}
@@ -115,10 +117,9 @@
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 @@
}
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 0000000..d05a04a
--- /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 0000000..5a3c181
--- /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 8113f72..4e74c7f 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -115,9 +115,13 @@
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 b8a7eab..89a9c36 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -138,6 +138,7 @@
name: "libgcc_stripped",
vendor_available: true,
recovery_available: true,
+ sdk_version: "current",
src: "",
}
@@ -155,6 +156,7 @@
llndk_library {
name: "libc",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libm",
@@ -174,6 +176,7 @@
llndk_library {
name: "libm",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libdl",
@@ -193,6 +196,7 @@
llndk_library {
name: "libdl",
symbol_file: "",
+ sdk_version: "current",
}
cc_library {
name: "libft2",
@@ -205,6 +209,7 @@
name: "libft2",
symbol_file: "",
vendor_available: false,
+ sdk_version: "current",
}
cc_library {
name: "libc++_static",
@@ -336,6 +341,16 @@
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 dfc6f76..042e012 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -67,6 +67,7 @@
module.stl = nil
module.sanitize = nil
module.installer = nil
+ module.Properties.Sdk_version = StringPtr("current")
return module.Init()
}