Merge changes from topic "cc_prebuilt_stubs" into main
* changes: Skip `-Wl,--version-script` on libclang_rt.* stubs (temp hack) Special case the stubgen args for bionic libs Add stub generation support to cc_prebuilt_library
This commit is contained in:
@@ -906,7 +906,7 @@ func TestApexWithStubs(t *testing.T) {
|
||||
cc_library {
|
||||
name: "mylib",
|
||||
srcs: ["mylib.cpp"],
|
||||
shared_libs: ["mylib2", "mylib3"],
|
||||
shared_libs: ["mylib2", "mylib3", "my_prebuilt_platform_lib", "my_prebuilt_platform_stub_only_lib"],
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
apex_available: [ "myapex" ],
|
||||
@@ -919,6 +919,7 @@ func TestApexWithStubs(t *testing.T) {
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
stubs: {
|
||||
symbol_file: "mylib2.map.txt",
|
||||
versions: ["1", "2", "3"],
|
||||
},
|
||||
}
|
||||
@@ -930,6 +931,7 @@ func TestApexWithStubs(t *testing.T) {
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
stubs: {
|
||||
symbol_file: "mylib3.map.txt",
|
||||
versions: ["10", "11", "12"],
|
||||
},
|
||||
apex_available: [ "myapex" ],
|
||||
@@ -943,6 +945,24 @@ func TestApexWithStubs(t *testing.T) {
|
||||
apex_available: [ "myapex" ],
|
||||
}
|
||||
|
||||
cc_prebuilt_library_shared {
|
||||
name: "my_prebuilt_platform_lib",
|
||||
stubs: {
|
||||
symbol_file: "my_prebuilt_platform_lib.map.txt",
|
||||
versions: ["1", "2", "3"],
|
||||
},
|
||||
srcs: ["foo.so"],
|
||||
}
|
||||
|
||||
// Similar to my_prebuilt_platform_lib, but this library only provides stubs, i.e. srcs is empty
|
||||
cc_prebuilt_library_shared {
|
||||
name: "my_prebuilt_platform_stub_only_lib",
|
||||
stubs: {
|
||||
symbol_file: "my_prebuilt_platform_stub_only_lib.map.txt",
|
||||
versions: ["1", "2", "3"],
|
||||
}
|
||||
}
|
||||
|
||||
rust_binary {
|
||||
name: "foo.rust",
|
||||
srcs: ["foo.rs"],
|
||||
@@ -1022,6 +1042,20 @@ func TestApexWithStubs(t *testing.T) {
|
||||
|
||||
apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
|
||||
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
|
||||
|
||||
// Ensure that mylib is linking with the latest version of stubs for my_prebuilt_platform_lib
|
||||
ensureContains(t, mylibLdFlags, "my_prebuilt_platform_lib/android_arm64_armv8-a_shared_current/my_prebuilt_platform_lib.so")
|
||||
// ... and not linking to the non-stub (impl) variant of my_prebuilt_platform_lib
|
||||
ensureNotContains(t, mylibLdFlags, "my_prebuilt_platform_lib/android_arm64_armv8-a_shared/my_prebuilt_platform_lib.so")
|
||||
// Ensure that genstub for platform-provided lib is invoked with --systemapi
|
||||
ensureContains(t, ctx.ModuleForTests("my_prebuilt_platform_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
|
||||
|
||||
// Ensure that mylib is linking with the latest version of stubs for my_prebuilt_platform_lib
|
||||
ensureContains(t, mylibLdFlags, "my_prebuilt_platform_stub_only_lib/android_arm64_armv8-a_shared_current/my_prebuilt_platform_stub_only_lib.so")
|
||||
// ... and not linking to the non-stub (impl) variant of my_prebuilt_platform_lib
|
||||
ensureNotContains(t, mylibLdFlags, "my_prebuilt_platform_stub_only_lib/android_arm64_armv8-a_shared/my_prebuilt_platform_stub_only_lib.so")
|
||||
// Ensure that genstub for platform-provided lib is invoked with --systemapi
|
||||
ensureContains(t, ctx.ModuleForTests("my_prebuilt_platform_stub_only_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
|
||||
}
|
||||
|
||||
func TestApexShouldNotEmbedStubVariant(t *testing.T) {
|
||||
@@ -1156,6 +1190,7 @@ func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
stubs: {
|
||||
symbol_file: "mylib2.map.txt",
|
||||
versions: ["28", "29", "30", "current"],
|
||||
},
|
||||
min_sdk_version: "28",
|
||||
@@ -1168,6 +1203,7 @@ func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
stubs: {
|
||||
symbol_file: "mylib3.map.txt",
|
||||
versions: ["28", "29", "30", "current"],
|
||||
},
|
||||
apex_available: [ "myapex" ],
|
||||
@@ -11940,7 +11976,7 @@ func TestPrebuiltStubNoinstall(t *testing.T) {
|
||||
).RunTest(t)
|
||||
|
||||
ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
|
||||
android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
|
||||
android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared_current/libfoo.so")
|
||||
|
||||
installRules := result.InstallMakeRulesForTesting(t)
|
||||
|
||||
|
@@ -927,7 +927,7 @@ func TestLlndkLibrary(t *testing.T) {
|
||||
|
||||
cc_prebuilt_library_shared {
|
||||
name: "libllndkprebuilt",
|
||||
stubs: { versions: ["1", "2"] },
|
||||
stubs: { versions: ["1", "2"] , symbol_file: "libllndkprebuilt.map.txt" },
|
||||
llndk: {
|
||||
symbol_file: "libllndkprebuilt.map.txt",
|
||||
},
|
||||
|
107
cc/library.go
107
cc/library.go
@@ -594,43 +594,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
||||
return objs
|
||||
}
|
||||
if library.buildStubs() {
|
||||
symbolFile := String(library.Properties.Stubs.Symbol_file)
|
||||
if symbolFile != "" && !strings.HasSuffix(symbolFile, ".map.txt") {
|
||||
ctx.PropertyErrorf("symbol_file", "%q doesn't have .map.txt suffix", symbolFile)
|
||||
return Objects{}
|
||||
}
|
||||
library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile)
|
||||
// b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
|
||||
// systemapi, respectively. The former is for symbols defined in platform libraries
|
||||
// and the latter is for symbols defined in APEXes.
|
||||
// A single library can contain either # apex or # systemapi, but not both.
|
||||
// The stub generator (ndkstubgen) is additive, so passing _both_ of these to it should be a no-op.
|
||||
// However, having this distinction helps guard accidental
|
||||
// promotion or demotion of API and also helps the API review process b/191371676
|
||||
var flag string
|
||||
if ctx.Module().(android.ApexModule).NotInPlatform() {
|
||||
flag = "--apex"
|
||||
} else {
|
||||
flag = "--systemapi"
|
||||
}
|
||||
// b/184712170, unless the lib is an NDK library, exclude all public symbols from
|
||||
// the stub so that it is mandated that all symbols are explicitly marked with
|
||||
// either apex or systemapi.
|
||||
if !ctx.Module().(*Module).IsNdk(ctx.Config()) {
|
||||
flag = flag + " --no-ndk"
|
||||
}
|
||||
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
|
||||
android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
|
||||
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
|
||||
library.versionScriptPath = android.OptionalPathForPath(
|
||||
nativeAbiResult.versionScript)
|
||||
|
||||
// Parse symbol file to get API list for coverage
|
||||
if library.stubsVersion() == "current" && ctx.PrimaryArch() && !ctx.inRecovery() && !ctx.inProduct() && !ctx.inVendor() {
|
||||
library.apiListCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
|
||||
}
|
||||
|
||||
return objs
|
||||
return library.compileModuleLibApiStubs(ctx, flags, deps)
|
||||
}
|
||||
|
||||
srcs := library.baseCompiler.Properties.Srcs.GetOrDefault(ctx, nil)
|
||||
@@ -681,6 +645,61 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
||||
return objs
|
||||
}
|
||||
|
||||
// Compile stubs for the API surface between platform and apex
|
||||
// This method will be used by source and prebuilt cc module types.
|
||||
func (library *libraryDecorator) compileModuleLibApiStubs(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
|
||||
// TODO (b/275273834): Make this a hard error when the symbol files have been added to module sdk.
|
||||
if library.Properties.Stubs.Symbol_file == nil {
|
||||
return Objects{}
|
||||
}
|
||||
symbolFile := String(library.Properties.Stubs.Symbol_file)
|
||||
library.stubsSymbolFilePath = android.PathForModuleSrc(ctx, symbolFile)
|
||||
// b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
|
||||
// systemapi, respectively. The former is for symbols defined in platform libraries
|
||||
// and the latter is for symbols defined in APEXes.
|
||||
// A single library can contain either # apex or # systemapi, but not both.
|
||||
// The stub generator (ndkstubgen) is additive, so passing _both_ of these to it should be a no-op.
|
||||
// However, having this distinction helps guard accidental
|
||||
// promotion or demotion of API and also helps the API review process b/191371676
|
||||
var flag string
|
||||
if ctx.Module().(android.ApexModule).NotInPlatform() {
|
||||
flag = "--apex"
|
||||
} else {
|
||||
flag = "--systemapi"
|
||||
}
|
||||
// b/184712170, unless the lib is an NDK library, exclude all public symbols from
|
||||
// the stub so that it is mandated that all symbols are explicitly marked with
|
||||
// either apex or systemapi.
|
||||
if !ctx.Module().(*Module).IsNdk(ctx.Config()) &&
|
||||
// the symbol files of libclang libs are autogenerated and do not contain systemapi tags
|
||||
// TODO (spandandas): Update mapfile.py to include #systemapi tag on all symbols
|
||||
!strings.Contains(ctx.ModuleName(), "libclang_rt") {
|
||||
flag = flag + " --no-ndk"
|
||||
}
|
||||
// TODO(b/361303067): Remove this special case if bionic/ projects are added to ART development branches.
|
||||
if isBionic(ctx.baseModuleName()) {
|
||||
// set the flags explicitly for bionic libs.
|
||||
// this is necessary for development in minimal branches which does not contain bionic/*.
|
||||
// In such minimal branches, e.g. on the prebuilt libc stubs
|
||||
// 1. IsNdk will return false (since the ndk_library definition for libc does not exist)
|
||||
// 2. NotInPlatform will return true (since the source com.android.runtime does not exist)
|
||||
flag = "--apex"
|
||||
}
|
||||
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
|
||||
android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
|
||||
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
|
||||
|
||||
library.versionScriptPath = android.OptionalPathForPath(
|
||||
nativeAbiResult.versionScript)
|
||||
|
||||
// Parse symbol file to get API list for coverage
|
||||
if library.stubsVersion() == "current" && ctx.PrimaryArch() && !ctx.inRecovery() && !ctx.inProduct() && !ctx.inVendor() {
|
||||
library.apiListCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
|
||||
}
|
||||
|
||||
return objs
|
||||
}
|
||||
|
||||
type libraryInterface interface {
|
||||
versionedInterface
|
||||
|
||||
@@ -1182,12 +1201,17 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
|
||||
return unstrippedOutputFile
|
||||
}
|
||||
|
||||
func addStubDependencyProviders(ctx ModuleContext) {
|
||||
// Visits the stub variants of the library and returns a struct containing the stub .so paths
|
||||
func addStubDependencyProviders(ctx ModuleContext) []SharedStubLibrary {
|
||||
stubsInfo := []SharedStubLibrary{}
|
||||
stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
|
||||
if len(stubs) > 0 {
|
||||
var stubsInfo []SharedStubLibrary
|
||||
for _, stub := range stubs {
|
||||
stubInfo, _ := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
|
||||
stubInfo, ok := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
|
||||
// TODO (b/275273834): Make this a hard error when the symbol files have been added to module sdk.
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
|
||||
stubsInfo = append(stubsInfo, SharedStubLibrary{
|
||||
Version: moduleLibraryInterface(stub).stubsVersion(),
|
||||
@@ -1195,12 +1219,15 @@ func addStubDependencyProviders(ctx ModuleContext) {
|
||||
FlagExporterInfo: flagInfo,
|
||||
})
|
||||
}
|
||||
if len(stubsInfo) > 0 {
|
||||
android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
|
||||
SharedStubLibraries: stubsInfo,
|
||||
IsLLNDK: ctx.IsLlndk(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return stubsInfo
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
|
||||
return library.unstrippedOutputFile
|
||||
|
@@ -16,6 +16,7 @@ package cc
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
@@ -95,10 +96,6 @@ func (p *prebuiltLibraryLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
||||
return p.libraryDecorator.linkerDeps(ctx, deps)
|
||||
}
|
||||
|
||||
func (p *prebuiltLibraryLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
|
||||
return flags
|
||||
}
|
||||
|
||||
func (p *prebuiltLibraryLinker) linkerProps() []interface{} {
|
||||
return p.libraryDecorator.linkerProps()
|
||||
}
|
||||
@@ -117,6 +114,30 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
|
||||
|
||||
// TODO(ccross): verify shared library dependencies
|
||||
srcs := p.prebuiltSrcs(ctx)
|
||||
stubInfo := addStubDependencyProviders(ctx)
|
||||
|
||||
// Stub variants will create a stub .so file from stub .c files
|
||||
if p.buildStubs() && objs.objFiles != nil {
|
||||
// TODO (b/275273834): Make objs.objFiles == nil a hard error when the symbol files have been added to module sdk.
|
||||
|
||||
// The map.txt files of libclang_rt.* contain version information, but the checked in .so files do not.
|
||||
// e.g. libclang_rt.* libs impl
|
||||
// $ nm -D prebuilts/../libclang_rt.hwasan-aarch64-android.so
|
||||
// __hwasan_init
|
||||
|
||||
// stubs generated from .map.txt
|
||||
// $ nm -D out/soong/.intermediates/../<stubs>/libclang_rt.hwasan-aarch64-android.so
|
||||
// __hwasan_init@@LIBCLANG_RT_ASAN
|
||||
|
||||
// Special-case libclang_rt.* libs to account for this discrepancy.
|
||||
// TODO (spandandas): Remove this special case https://r.android.com/3236596 has been submitted, and a new set of map.txt
|
||||
// files of libclang_rt.* libs have been generated.
|
||||
if strings.Contains(ctx.ModuleName(), "libclang_rt.") {
|
||||
p.versionScriptPath = android.OptionalPathForPath(nil)
|
||||
}
|
||||
return p.linkShared(ctx, flags, deps, objs)
|
||||
}
|
||||
|
||||
if len(srcs) > 0 {
|
||||
if len(srcs) > 1 {
|
||||
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
|
||||
@@ -203,6 +224,16 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
|
||||
|
||||
return outputFile
|
||||
}
|
||||
} else if p.shared() && len(stubInfo) > 0 {
|
||||
// This is a prebuilt which does not have any implementation (nil `srcs`), but provides APIs.
|
||||
// Provide the latest (i.e. `current`) stubs to reverse dependencies.
|
||||
latestStub := stubInfo[len(stubInfo)-1].SharedLibraryInfo.SharedLibrary
|
||||
android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
|
||||
SharedLibrary: latestStub,
|
||||
Target: ctx.Target(),
|
||||
})
|
||||
|
||||
return latestStub
|
||||
}
|
||||
|
||||
if p.header() {
|
||||
@@ -257,11 +288,11 @@ func (p *prebuiltLibraryLinker) implementationModuleName(name string) string {
|
||||
|
||||
func NewPrebuiltLibrary(hod android.HostOrDeviceSupported, srcsProperty string) (*Module, *libraryDecorator) {
|
||||
module, library := NewLibrary(hod)
|
||||
module.compiler = nil
|
||||
|
||||
prebuilt := &prebuiltLibraryLinker{
|
||||
libraryDecorator: library,
|
||||
}
|
||||
module.compiler = prebuilt
|
||||
module.linker = prebuilt
|
||||
module.library = prebuilt
|
||||
|
||||
@@ -280,6 +311,13 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported, srcsProperty string)
|
||||
return module, library
|
||||
}
|
||||
|
||||
func (p *prebuiltLibraryLinker) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
|
||||
if p.buildStubs() && p.stubsVersion() != "" {
|
||||
return p.compileModuleLibApiStubs(ctx, flags, deps)
|
||||
}
|
||||
return Objects{}
|
||||
}
|
||||
|
||||
// cc_prebuilt_library installs a precompiled shared library that are
|
||||
// listed in the srcs property in the device's directory.
|
||||
func PrebuiltLibraryFactory() android.Module {
|
||||
|
Reference in New Issue
Block a user