rust: Emit toc files for cdylibs
Write toc files that list the exported symbols so dependents are only rebuilt if the exported symbols change. This exports the CC function TransformSharedObjectToToc, and also removes an unused arg from its signature. Bug: 178185435 Test: New Soong test passes. Test: m <toc file path> Change-Id: I7ab69bf7e7f32f25eb4c7ca9d18d877dac1511db
This commit is contained in:
parent
a3bd963988
commit
7b0781d14c
10 changed files with 53 additions and 18 deletions
|
@ -949,8 +949,7 @@ func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceD
|
|||
}
|
||||
|
||||
// Generate a rule for extracting a table of contents from a shared library (.so)
|
||||
func transformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path,
|
||||
outputFile android.WritablePath, flags builderFlags) {
|
||||
func TransformSharedObjectToToc(ctx android.ModuleContext, inputFile android.Path, outputFile android.WritablePath) {
|
||||
|
||||
var format string
|
||||
if ctx.Darwin() {
|
||||
|
|
|
@ -1377,7 +1377,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
|
|||
// depending on a table of contents file instead of the library itself.
|
||||
tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
|
||||
library.tocFile = android.OptionalPathForPath(tocFile)
|
||||
transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
|
||||
TransformSharedObjectToToc(ctx, outputFile, tocFile)
|
||||
|
||||
stripFlags := flagsToStripFlags(flags)
|
||||
needsStrip := library.stripper.NeedsStrip(ctx)
|
||||
|
|
|
@ -114,8 +114,6 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
|
|||
// TODO(ccross): verify shared library dependencies
|
||||
srcs := p.prebuiltSrcs(ctx)
|
||||
if len(srcs) > 0 {
|
||||
builderFlags := flagsToBuilderFlags(flags)
|
||||
|
||||
if len(srcs) > 1 {
|
||||
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
|
||||
return nil
|
||||
|
@ -152,7 +150,7 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
|
|||
// depending on a table of contents file instead of the library itself.
|
||||
tocFile := android.PathForModuleOut(ctx, libName+".toc")
|
||||
p.tocFile = android.OptionalPathForPath(tocFile)
|
||||
transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags)
|
||||
TransformSharedObjectToToc(ctx, outputFile, tocFile)
|
||||
|
||||
if ctx.Windows() && p.properties.Windows_import_lib != nil {
|
||||
// Consumers of this library actually links to the import library in build
|
||||
|
|
|
@ -476,13 +476,12 @@ func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps Pat
|
|||
|
||||
if p.shared() {
|
||||
libName := in.Base()
|
||||
builderFlags := flagsToBuilderFlags(flags)
|
||||
|
||||
// Optimize out relinking against shared libraries whose interface hasn't changed by
|
||||
// depending on a table of contents file instead of the library itself.
|
||||
tocFile := android.PathForModuleOut(ctx, libName+".toc")
|
||||
p.tocFile = android.OptionalPathForPath(tocFile)
|
||||
transformSharedObjectToToc(ctx, in, tocFile, builderFlags)
|
||||
TransformSharedObjectToToc(ctx, in, tocFile)
|
||||
|
||||
ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
|
||||
SharedLibrary: in,
|
||||
|
|
|
@ -144,7 +144,6 @@ func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
|
|||
// current VNDK prebuilts are only shared libs.
|
||||
|
||||
in := p.singleSourcePath(ctx)
|
||||
builderFlags := flagsToBuilderFlags(flags)
|
||||
p.unstrippedOutputFile = in
|
||||
libName := in.Base()
|
||||
if p.stripper.NeedsStrip(ctx) {
|
||||
|
@ -158,7 +157,7 @@ func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
|
|||
// depending on a table of contents file instead of the library itself.
|
||||
tocFile := android.PathForModuleOut(ctx, libName+".toc")
|
||||
p.tocFile = android.OptionalPathForPath(tocFile)
|
||||
transformSharedObjectToToc(ctx, in, tocFile, builderFlags)
|
||||
TransformSharedObjectToToc(ctx, in, tocFile)
|
||||
|
||||
p.androidMkSuffix = p.NameSuffix()
|
||||
|
||||
|
|
|
@ -137,12 +137,16 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An
|
|||
} else if library.shared() {
|
||||
ret.Class = "SHARED_LIBRARIES"
|
||||
}
|
||||
|
||||
if library.distFile.Valid() {
|
||||
ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
|
||||
}
|
||||
ret.ExtraEntries = append(ret.ExtraEntries,
|
||||
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
||||
if library.tocFile.Valid() {
|
||||
entries.SetString("LOCAL_SOONG_TOC", library.tocFile.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
|
||||
ctx.SubAndroidMk(ret, procMacro.baseCompiler)
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ func rustEnvVars(ctx ModuleContext, deps PathDeps) []string {
|
|||
}
|
||||
|
||||
func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags,
|
||||
outputFile android.WritablePath, crate_type string) buildOutput {
|
||||
outputFile android.WritablePath, crateType string) buildOutput {
|
||||
|
||||
var inputs android.Paths
|
||||
var implicits android.Paths
|
||||
|
@ -204,7 +204,7 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
|
|||
// Collect rustc flags
|
||||
rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
|
||||
rustcFlags = append(rustcFlags, flags.RustFlags...)
|
||||
rustcFlags = append(rustcFlags, "--crate-type="+crate_type)
|
||||
rustcFlags = append(rustcFlags, "--crate-type="+crateType)
|
||||
if crateName != "" {
|
||||
rustcFlags = append(rustcFlags, "--crate-name="+crateName)
|
||||
}
|
||||
|
|
|
@ -102,6 +102,9 @@ type libraryDecorator struct {
|
|||
sourceProvider SourceProvider
|
||||
|
||||
collectedSnapshotHeaders android.Paths
|
||||
|
||||
// table-of-contents file for cdylib crates to optimize out relinking when possible
|
||||
tocFile android.OptionalPath
|
||||
}
|
||||
|
||||
type libraryInterface interface {
|
||||
|
@ -137,12 +140,18 @@ type libraryInterface interface {
|
|||
BuildOnlyDylib()
|
||||
BuildOnlyStatic()
|
||||
BuildOnlyShared()
|
||||
|
||||
toc() android.OptionalPath
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) nativeCoverage() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) toc() android.OptionalPath {
|
||||
return library.tocFile
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) rlib() bool {
|
||||
return library.MutatedProperties.VariantIsRlib
|
||||
}
|
||||
|
@ -519,9 +528,16 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
|||
}
|
||||
|
||||
if library.shared() {
|
||||
// Optimize out relinking against shared libraries whose interface hasn't changed by
|
||||
// depending on a table of contents file instead of the library itself.
|
||||
tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.SharedLibSuffix()[1:]+".toc")
|
||||
library.tocFile = android.OptionalPathForPath(tocFile)
|
||||
cc.TransformSharedObjectToToc(ctx, outputFile, tocFile)
|
||||
|
||||
ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
|
||||
SharedLibrary: outputFile,
|
||||
Target: ctx.Target(),
|
||||
TableOfContents: android.OptionalPathForPath(tocFile),
|
||||
SharedLibrary: outputFile,
|
||||
Target: ctx.Target(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -160,6 +160,26 @@ func TestSharedLibrary(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSharedLibraryToc(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_shared {
|
||||
name: "libfoo",
|
||||
srcs: ["foo.rs"],
|
||||
crate_name: "foo",
|
||||
}
|
||||
cc_binary {
|
||||
name: "fizzbuzz",
|
||||
shared_libs: ["libfoo"],
|
||||
}`)
|
||||
|
||||
fizzbuzz := ctx.ModuleForTests("fizzbuzz", "android_arm64_armv8-a").Rule("ld")
|
||||
|
||||
if !android.SuffixInList(fizzbuzz.Implicits.Strings(), "libfoo.so.toc") {
|
||||
t.Errorf("missing expected libfoo.so.toc implicit dependency, instead found: %#v",
|
||||
fizzbuzz.Implicits.Strings())
|
||||
}
|
||||
}
|
||||
|
||||
func TestStaticLibraryLinkage(t *testing.T) {
|
||||
ctx := testRust(t, `
|
||||
rust_ffi_static {
|
||||
|
|
|
@ -281,8 +281,8 @@ func (mod *Module) Object() bool {
|
|||
|
||||
func (mod *Module) Toc() android.OptionalPath {
|
||||
if mod.compiler != nil {
|
||||
if _, ok := mod.compiler.(libraryInterface); ok {
|
||||
return android.OptionalPath{}
|
||||
if lib, ok := mod.compiler.(libraryInterface); ok {
|
||||
return lib.toc()
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName()))
|
||||
|
|
Loading…
Reference in a new issue