From 2093af23c06429f5dd22dbae5d47ef800a9fb379 Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Tue, 25 Aug 2020 12:48:19 -0400 Subject: [PATCH] [rust] Pass cc dependencies as linker flags. In order to support cc dependencies which do not start with the 'lib' prefix, we can't pass them through the -l flag. Instead, we can pass them directly to linker flags. Bug: 166151658 Test: cd external/rust/; mma Test: cd external/crosvm/; mma Test: Test linking to a cc dep that does not begin with 'lib' Change-Id: I5acbf3d3405e66446f3eae600b35683c4eb3d8a5 --- rust/binary.go | 1 + rust/binary_test.go | 18 +++++++++++++ rust/library.go | 2 ++ rust/rust.go | 64 +++++++++++++++++++++++---------------------- rust/rust_test.go | 19 -------------- 5 files changed, 54 insertions(+), 50 deletions(-) diff --git a/rust/binary.go b/rust/binary.go index 1a82c9208..8490e93a7 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -112,6 +112,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path binary.unstrippedOutputFile = outputFile flags.RustFlags = append(flags.RustFlags, deps.depFlags...) + flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...) outputs := TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs) binary.coverageFile = outputs.coverageFile diff --git a/rust/binary_test.go b/rust/binary_test.go index b9c8698b9..eeee8417c 100644 --- a/rust/binary_test.go +++ b/rust/binary_test.go @@ -58,3 +58,21 @@ func TestPreferDynamicBinary(t *testing.T) { t.Errorf("unexpected prefer-dynamic flag, rustcFlags: %#v", flags) } } + +func TestLinkObjects(t *testing.T) { + ctx := testRust(t, ` + rust_binary { + name: "fizz-buzz", + srcs: ["foo.rs"], + shared_libs: ["libfoo"], + } + cc_library { + name: "libfoo", + }`) + + fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Output("fizz-buzz") + linkFlags := fizzBuzz.Args["linkFlags"] + if !strings.Contains(linkFlags, "/libfoo.so") { + t.Errorf("missing shared dependency 'libfoo.so' in linkFlags: %#v", linkFlags) + } +} diff --git a/rust/library.go b/rust/library.go index 6766d618b..1339670f3 100644 --- a/rust/library.go +++ b/rust/library.go @@ -381,6 +381,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa } flags.RustFlags = append(flags.RustFlags, deps.depFlags...) + flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...) if library.dylib() { // We need prefer-dynamic for now to avoid linking in the static stdlib. See: @@ -427,6 +428,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa if library.rlib() || library.dylib() { library.exportLinkDirs(deps.linkDirs...) library.exportDepFlags(deps.depFlags...) + library.exportLinkObjects(deps.linkObjects...) } library.unstrippedOutputFile = outputFile diff --git a/rust/rust.go b/rust/rust.go index b69786976..8dffb43b7 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -244,13 +244,14 @@ type Deps struct { } type PathDeps struct { - DyLibs RustLibraries - RLibs RustLibraries - SharedLibs android.Paths - StaticLibs android.Paths - ProcMacros RustLibraries - linkDirs []string - depFlags []string + DyLibs RustLibraries + RLibs RustLibraries + SharedLibs android.Paths + StaticLibs android.Paths + ProcMacros RustLibraries + linkDirs []string + depFlags []string + linkObjects []string //ReexportedDeps android.Paths // Used by bindgen modules which call clang @@ -294,13 +295,16 @@ type compiler interface { type exportedFlagsProducer interface { exportedLinkDirs() []string exportedDepFlags() []string + exportedLinkObjects() []string exportLinkDirs(...string) exportDepFlags(...string) + exportLinkObjects(...string) } type flagExporter struct { - depFlags []string - linkDirs []string + depFlags []string + linkDirs []string + linkObjects []string } func (flagExporter *flagExporter) exportedLinkDirs() []string { @@ -311,6 +315,10 @@ func (flagExporter *flagExporter) exportedDepFlags() []string { return flagExporter.depFlags } +func (flagExporter *flagExporter) exportedLinkObjects() []string { + return flagExporter.linkObjects +} + func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) } @@ -319,12 +327,17 @@ func (flagExporter *flagExporter) exportDepFlags(flags ...string) { flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...)) } +func (flagExporter *flagExporter) exportLinkObjects(flags ...string) { + flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...)) +} + var _ exportedFlagsProducer = (*flagExporter)(nil) func NewFlagExporter() *flagExporter { return &flagExporter{ - depFlags: []string{}, - linkDirs: []string{}, + depFlags: []string{}, + linkDirs: []string{}, + linkObjects: []string{}, } } @@ -811,6 +824,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok && depTag != procMacroDepTag { depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedLinkDirs()...) depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...) + depPaths.linkObjects = append(depPaths.linkObjects, lib.exportedLinkObjects()...) } if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { @@ -838,21 +852,18 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } } - linkFile := ccDep.OutputFile() - linkPath := linkPathFromFilePath(linkFile.Path()) - libName := libNameFromFilePath(linkFile.Path()) - depFlag := "-l" + libName + linkObject := ccDep.OutputFile() + linkPath := linkPathFromFilePath(linkObject.Path()) - if !linkFile.Valid() { + if !linkObject.Valid() { ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName()) } exportDep := false switch { case cc.IsStaticDepTag(depTag): - depFlag = "-lstatic=" + libName depPaths.linkDirs = append(depPaths.linkDirs, linkPath) - depPaths.depFlags = append(depPaths.depFlags, depFlag) + depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...) if mod, ok := ccDep.(*cc.Module); ok { depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...) @@ -862,9 +873,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directStaticLibDeps = append(directStaticLibDeps, ccDep) mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName) case cc.IsSharedDepTag(depTag): - depFlag = "-ldylib=" + libName depPaths.linkDirs = append(depPaths.linkDirs, linkPath) - depPaths.depFlags = append(depPaths.depFlags, depFlag) + depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...) if mod, ok := ccDep.(*cc.Module); ok { depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...) @@ -874,15 +884,15 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName) exportDep = true case depTag == cc.CrtBeginDepTag: - depPaths.CrtBegin = linkFile + depPaths.CrtBegin = linkObject case depTag == cc.CrtEndDepTag: - depPaths.CrtEnd = linkFile + depPaths.CrtEnd = linkObject } // Make sure these dependencies are propagated if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep { lib.exportLinkDirs(linkPath) - lib.exportDepFlags(depFlag) + lib.exportLinkObjects(linkObject.String()) } } @@ -956,14 +966,6 @@ func linkPathFromFilePath(filepath android.Path) string { return strings.Split(filepath.String(), filepath.Base())[0] } -func libNameFromFilePath(filepath android.Path) string { - libName := strings.TrimSuffix(filepath.Base(), filepath.Ext()) - if strings.HasPrefix(libName, "lib") { - libName = libName[3:] - } - return libName -} - func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { ctx := &depsContext{ BottomUpMutatorContext: actx, diff --git a/rust/rust_test.go b/rust/rust_test.go index 04de48b19..f1a08a805 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -132,25 +132,6 @@ func testRustError(t *testing.T, pattern string, bp string) { t.Fatalf("missing expected error %q (0 errors are returned)", pattern) } -// Test that we can extract the lib name from a lib path. -func TestLibNameFromFilePath(t *testing.T) { - libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so.so") - libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so") - - libBarName := libNameFromFilePath(libBarPath) - libLibName := libNameFromFilePath(libLibPath) - - expectedResult := "bar.so" - if libBarName != expectedResult { - t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName) - } - - expectedResult = "lib.dylib" - if libLibName != expectedResult { - t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libLibPath) - } -} - // Test that we can extract the link path from a lib path. func TestLinkPathFromFilePath(t *testing.T) { barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")