diff --git a/cc/Android.bp b/cc/Android.bp index e68e4a398..3bbcaa92e 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -73,6 +73,7 @@ bootstrap_go_package { "ndk_abi.go", "ndk_headers.go", "ndk_library.go", + "ndk_prebuilt.go", "ndk_sysroot.go", "llndk_library.go", diff --git a/cc/androidmk.go b/cc/androidmk.go index cecaae23a..41346538f 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -451,6 +451,10 @@ func (c *vndkPrebuiltLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, en }) } +func (c *ndkPrebuiltStlLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { + entries.Class = "SHARED_LIBRARIES" +} + func (p *prebuiltLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { if p.properties.Check_elf_files != nil { diff --git a/cc/cc.go b/cc/cc.go index 23a3a835b..740be3afe 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -1028,6 +1028,13 @@ func (c *Module) SelectedStl() string { return "" } +func (c *Module) NdkPrebuiltStl() bool { + if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok { + return true + } + return false +} + func (c *Module) StubDecorator() bool { if _, ok := c.linker.(*stubDecorator); ok { return true @@ -1081,6 +1088,16 @@ func (c *Module) CcLibraryInterface() bool { return false } +func (c *Module) IsNdkPrebuiltStl() bool { + if c.linker == nil { + return false + } + if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok { + return true + } + return false +} + func (c *Module) RlibStd() bool { panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName())) } @@ -2735,6 +2752,10 @@ func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to Lin return } if c, ok := to.(*Module); ok { + if c.NdkPrebuiltStl() { + // These are allowed, but they don't set sdk_version + return + } if c.StubDecorator() { // These aren't real libraries, but are the stub shared libraries that are included in // the NDK. @@ -3904,6 +3925,7 @@ const ( headerLibrary testBin // testBinary already declared ndkLibrary + ndkPrebuiltStl ) func (c *Module) typ() moduleType { @@ -3942,6 +3964,8 @@ func (c *Module) typ() moduleType { return sharedLibrary } else if c.isNDKStubLibrary() { return ndkLibrary + } else if c.IsNdkPrebuiltStl() { + return ndkPrebuiltStl } return unknownType } diff --git a/cc/cc_test.go b/cc/cc_test.go index b1c094547..ccdaae58f 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -2760,7 +2760,7 @@ func TestIncludeDirectoryOrdering(t *testing.T) { "external/foo/libarm", "external/foo/lib32", "external/foo/libandroid_arm", - "defaults/cc/common/ndk_libc++_shared_include_dirs", + "defaults/cc/common/ndk_libc++_shared", } conly := []string{"-fPIC", "${config.CommonGlobalConlyflags}"} diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go new file mode 100644 index 000000000..f503982cd --- /dev/null +++ b/cc/ndk_prebuilt.go @@ -0,0 +1,133 @@ +// Copyright 2016 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 ( + "strings" + + "android/soong/android" +) + +func init() { + android.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory) + android.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory) +} + +// NDK prebuilt libraries. +// +// These differ from regular prebuilts in that they aren't stripped and usually aren't installed +// either (with the exception of the shared STLs, which are installed to the app's directory rather +// than to the system image). + +type ndkPrebuiltStlLinker struct { + *libraryDecorator +} + +func (ndk *ndkPrebuiltStlLinker) linkerProps() []interface{} { + return append(ndk.libraryDecorator.linkerProps(), &ndk.Properties, &ndk.flagExporter.Properties) +} + +func (*ndkPrebuiltStlLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { + // NDK libraries can't have any dependencies + return deps +} + +func (*ndkPrebuiltStlLinker) availableFor(what string) bool { + // ndk prebuilt objects are available to everywhere + return true +} + +// ndk_prebuilt_shared_stl exports a precompiled ndk shared standard template +// library (stl) library for linking operation. The soong's module name format +// is ndk_.so where the library is located under +// ./prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/$(HOST_ARCH)/.so. +func NdkPrebuiltSharedStlFactory() android.Module { + module, library := NewLibrary(android.DeviceSupported) + library.BuildOnlyShared() + module.compiler = nil + module.linker = &ndkPrebuiltStlLinker{ + libraryDecorator: library, + } + module.installer = nil + module.Properties.Sdk_version = StringPtr("minimum") + module.Properties.AlwaysSdk = true + module.stl.Properties.Stl = StringPtr("none") + return module.Init() +} + +// ndk_prebuilt_static_stl exports a precompiled ndk static standard template +// library (stl) library for linking operation. The soong's module name format +// is ndk_.a where the library is located under +// ./prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/$(HOST_ARCH)/.a. +func NdkPrebuiltStaticStlFactory() android.Module { + module, library := NewLibrary(android.DeviceSupported) + library.BuildOnlyStatic() + module.compiler = nil + module.linker = &ndkPrebuiltStlLinker{ + libraryDecorator: library, + } + module.installer = nil + module.Properties.Sdk_version = StringPtr("minimum") + module.Properties.HideFromMake = true + module.Properties.AlwaysSdk = true + module.Properties.Sdk_version = StringPtr("current") + module.stl.Properties.Stl = StringPtr("none") + return module.Init() +} + +const ( + libDir = "current/sources/cxx-stl/llvm-libc++/libs" +) + +func getNdkStlLibDir(ctx android.ModuleContext) android.SourcePath { + return android.PathForSource(ctx, ctx.ModuleDir(), libDir).Join(ctx, ctx.Arch().Abi[0]) +} + +func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags, + deps PathDeps, objs Objects) android.Path { + // A null build step, but it sets up the output path. + if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") { + ctx.ModuleErrorf("NDK prebuilt libraries must have an ndk_lib prefixed name") + } + + ndk.libraryDecorator.flagExporter.exportIncludesAsSystem(ctx) + + libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_") + libExt := flags.Toolchain.ShlibSuffix() + if ndk.static() { + libExt = staticLibraryExtension + } + + libDir := getNdkStlLibDir(ctx) + lib := libDir.Join(ctx, libName+libExt) + + ndk.libraryDecorator.flagExporter.setProvider(ctx) + + if ndk.static() { + depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(lib).Build() + android.SetProvider(ctx, StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: lib, + + TransitiveStaticLibrariesForOrdering: depSet, + }) + } else { + android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{ + SharedLibrary: lib, + Target: ctx.Target(), + }) + } + + return lib +} diff --git a/cc/stl.go b/cc/stl.go index 8c4ef0b4a..de2066f30 100644 --- a/cc/stl.go +++ b/cc/stl.go @@ -177,7 +177,7 @@ func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps { } else { deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi") } - deps.StaticLibs = append(deps.StaticLibs, "libunwind") + deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind") default: panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) } diff --git a/cc/testing.go b/cc/testing.go index ed567af69..02f992426 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -38,6 +38,8 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory) ctx.RegisterModuleType("cc_object", ObjectFactory) ctx.RegisterModuleType("cc_genrule", GenRuleFactory) + ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory) + ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory) ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory) } @@ -309,25 +311,6 @@ func commonDefaultModules() string { "//apex_available:anyapex", ], } - cc_library { - name: "ndk_libc++_shared", - export_include_dirs: ["ndk_libc++_shared_include_dirs"], - no_libcrt: true, - nocrt: true, - system_shared_libs: [], - stl: "none", - vendor_available: true, - vendor_ramdisk_available: true, - product_available: true, - recovery_available: true, - host_supported: false, - sdk_version: "minimum", - double_loadable: true, - apex_available: [ - "//apex_available:platform", - "//apex_available:anyapex", - ], - } cc_library { name: "libc++demangle", no_libcrt: true, @@ -414,6 +397,13 @@ func commonDefaultModules() string { name: "libprotobuf-cpp-lite", } + cc_library { + name: "ndk_libunwind", + sdk_version: "minimum", + stl: "none", + system_shared_libs: [], + } + ndk_library { name: "libc", first_version: "minimum", @@ -432,6 +422,11 @@ func commonDefaultModules() string { symbol_file: "libdl.map.txt", } + ndk_prebuilt_shared_stl { + name: "ndk_libc++_shared", + export_include_dirs: ["ndk_libc++_shared"], + } + cc_library_static { name: "libgoogle-benchmark", sdk_version: "current", @@ -562,6 +557,13 @@ var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( RegisterLlndkLibraryTxtType(ctx) }), + + // Additional files needed in tests that disallow non-existent source files. + // This includes files that are needed by all, or at least most, instances of a cc module type. + android.MockFS{ + // Needed for ndk_prebuilt_(shared|static)_stl. + "defaults/cc/common/current/sources/cxx-stl/llvm-libc++/libs": nil, + }.AddToFixture(), ) // Preparer that will define default cc modules, e.g. standard prebuilt modules. @@ -570,17 +572,17 @@ var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers( // Additional files needed in tests that disallow non-existent source. android.MockFS{ - "defaults/cc/common/libc.map.txt": nil, - "defaults/cc/common/libdl.map.txt": nil, - "defaults/cc/common/libft2.map.txt": nil, - "defaults/cc/common/libm.map.txt": nil, - "defaults/cc/common/ndk_libc++_shared_include_dirs": nil, - "defaults/cc/common/crtbegin_so.c": nil, - "defaults/cc/common/crtbegin.c": nil, - "defaults/cc/common/crtend_so.c": nil, - "defaults/cc/common/crtend.c": nil, - "defaults/cc/common/crtbrand.c": nil, - "external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil, + "defaults/cc/common/libc.map.txt": nil, + "defaults/cc/common/libdl.map.txt": nil, + "defaults/cc/common/libft2.map.txt": nil, + "defaults/cc/common/libm.map.txt": nil, + "defaults/cc/common/ndk_libc++_shared": nil, + "defaults/cc/common/crtbegin_so.c": nil, + "defaults/cc/common/crtbegin.c": nil, + "defaults/cc/common/crtend_so.c": nil, + "defaults/cc/common/crtend.c": nil, + "defaults/cc/common/crtbrand.c": nil, + "external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil, "defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil, "defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a": nil,