rust: Pass cc static libs to rustc.
Pass static libraries to rustc via the "-lstatic" flag so that rustc can reason how to handle these libraries. This means that these static libraries get bundled into rlibs, reducing the need to redeclare these dependencies in dependent modules. Additionally, exported depFlags were never used anywhere, so remove this from flagExporter. Bug: 175886967 Bug: 179122837 Test: m Test: Checked that static symbols aren't duplicated in a resulting binary when it appears in a dependency graph more than once. Change-Id: Ifeb3c384e4fad8704206997242a0156ddcb87d2c
This commit is contained in:
parent
632f080f88
commit
3dfa12db6c
|
@ -119,6 +119,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path
|
||||||
outputFile := android.PathForModuleOut(ctx, fileName)
|
outputFile := android.PathForModuleOut(ctx, fileName)
|
||||||
|
|
||||||
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
|
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
|
||||||
|
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
|
||||||
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
|
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
|
||||||
|
|
||||||
TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
|
TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
|
||||||
|
|
|
@ -96,7 +96,11 @@ type BaseCompilerProperties struct {
|
||||||
// list of C shared library dependencies
|
// list of C shared library dependencies
|
||||||
Shared_libs []string `android:"arch_variant"`
|
Shared_libs []string `android:"arch_variant"`
|
||||||
|
|
||||||
// list of C static library dependencies
|
// list of C static library dependencies. Note, static libraries prefixed by "lib" will be passed to rustc
|
||||||
|
// along with "-lstatic=<name>". This will bundle the static library into rlib/static libraries so dependents do
|
||||||
|
// not need to also declare the static library as a dependency. Static libraries which are not prefixed by "lib"
|
||||||
|
// cannot be passed to rustc with this flag and will not be bundled into rlib/static libraries, and thus must
|
||||||
|
// be redeclared in dependents.
|
||||||
Static_libs []string `android:"arch_variant"`
|
Static_libs []string `android:"arch_variant"`
|
||||||
|
|
||||||
// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
|
// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
|
||||||
|
|
|
@ -439,6 +439,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
||||||
}
|
}
|
||||||
|
|
||||||
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
|
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
|
||||||
|
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
|
||||||
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
|
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
|
||||||
|
|
||||||
if library.dylib() {
|
if library.dylib() {
|
||||||
|
@ -478,7 +479,6 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa
|
||||||
|
|
||||||
if library.rlib() || library.dylib() {
|
if library.rlib() || library.dylib() {
|
||||||
library.flagExporter.exportLinkDirs(deps.linkDirs...)
|
library.flagExporter.exportLinkDirs(deps.linkDirs...)
|
||||||
library.flagExporter.exportDepFlags(deps.depFlags...)
|
|
||||||
library.flagExporter.exportLinkObjects(deps.linkObjects...)
|
library.flagExporter.exportLinkObjects(deps.linkObjects...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
45
rust/rust.go
45
rust/rust.go
|
@ -280,10 +280,15 @@ type PathDeps struct {
|
||||||
SharedLibDeps android.Paths
|
SharedLibDeps android.Paths
|
||||||
StaticLibs android.Paths
|
StaticLibs android.Paths
|
||||||
ProcMacros RustLibraries
|
ProcMacros RustLibraries
|
||||||
linkDirs []string
|
|
||||||
depFlags []string
|
// depFlags and depLinkFlags are rustc and linker (clang) flags.
|
||||||
linkObjects []string
|
depFlags []string
|
||||||
//ReexportedDeps android.Paths
|
depLinkFlags []string
|
||||||
|
|
||||||
|
// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker.
|
||||||
|
// Both of these are exported and propagate to dependencies.
|
||||||
|
linkDirs []string
|
||||||
|
linkObjects []string
|
||||||
|
|
||||||
// Used by bindgen modules which call clang
|
// Used by bindgen modules which call clang
|
||||||
depClangFlags []string
|
depClangFlags []string
|
||||||
|
@ -328,12 +333,10 @@ type compiler interface {
|
||||||
|
|
||||||
type exportedFlagsProducer interface {
|
type exportedFlagsProducer interface {
|
||||||
exportLinkDirs(...string)
|
exportLinkDirs(...string)
|
||||||
exportDepFlags(...string)
|
|
||||||
exportLinkObjects(...string)
|
exportLinkObjects(...string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type flagExporter struct {
|
type flagExporter struct {
|
||||||
depFlags []string
|
|
||||||
linkDirs []string
|
linkDirs []string
|
||||||
linkObjects []string
|
linkObjects []string
|
||||||
}
|
}
|
||||||
|
@ -342,17 +345,12 @@ func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
|
||||||
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
|
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flagExporter *flagExporter) exportDepFlags(flags ...string) {
|
|
||||||
flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
|
func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
|
||||||
flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
|
flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
|
func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
|
||||||
ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
|
ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
|
||||||
Flags: flagExporter.depFlags,
|
|
||||||
LinkDirs: flagExporter.linkDirs,
|
LinkDirs: flagExporter.linkDirs,
|
||||||
LinkObjects: flagExporter.linkObjects,
|
LinkObjects: flagExporter.linkObjects,
|
||||||
})
|
})
|
||||||
|
@ -898,8 +896,21 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||||
exportDep := false
|
exportDep := false
|
||||||
switch {
|
switch {
|
||||||
case cc.IsStaticDepTag(depTag):
|
case cc.IsStaticDepTag(depTag):
|
||||||
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
|
// Link cc static libraries using "-lstatic" so rustc can reason about how to handle these
|
||||||
|
// (for example, bundling them into rlibs).
|
||||||
|
//
|
||||||
|
// rustc does not support linking libraries with the "-l" flag unless they are prefixed by "lib".
|
||||||
|
// If we need to link a library that isn't prefixed by "lib", we'll just link to it directly through
|
||||||
|
// linkObjects; such a library may need to be redeclared by static dependents.
|
||||||
|
if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
|
||||||
|
depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this to linkObjects to pass the library directly to the linker as well. This propagates
|
||||||
|
// to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
|
||||||
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
|
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
|
||||||
|
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
|
||||||
|
|
||||||
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
|
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
|
||||||
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
||||||
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
|
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
|
||||||
|
@ -1213,6 +1224,16 @@ func (mod *Module) IsInstallableToApex() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a library file has a "lib" prefix, extract the library name without the prefix.
|
||||||
|
func libNameFromFilePath(filepath android.Path) (string, bool) {
|
||||||
|
libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
|
||||||
|
if strings.HasPrefix(libName, "lib") {
|
||||||
|
libName = libName[3:]
|
||||||
|
return libName, true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
var Bool = proptools.Bool
|
var Bool = proptools.Bool
|
||||||
var BoolDefault = proptools.BoolDefault
|
var BoolDefault = proptools.BoolDefault
|
||||||
var String = proptools.String
|
var String = proptools.String
|
||||||
|
|
|
@ -230,6 +230,7 @@ func TestDepsTracking(t *testing.T) {
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
|
module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
|
||||||
|
rustc := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustc")
|
||||||
|
|
||||||
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
|
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
|
||||||
if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
|
if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
|
||||||
|
@ -251,6 +252,11 @@ func TestDepsTracking(t *testing.T) {
|
||||||
if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
|
if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) {
|
||||||
t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
|
t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=static") {
|
||||||
|
t.Errorf("-lstatic flag not being passed to rustc for static library")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSourceProviderDeps(t *testing.T) {
|
func TestSourceProviderDeps(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue