diff --git a/cc/linker.go b/cc/linker.go index 625d89cd0..371d78daf 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -15,10 +15,10 @@ package cc import ( - "fmt" - "android/soong/android" "android/soong/cc/config" + "fmt" + "path/filepath" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -270,8 +270,7 @@ func NewBaseLinker(sanitize *sanitize) *baseLinker { type baseLinker struct { Properties BaseLinkerProperties dynamicProperties struct { - RunPaths []string `blueprint:"mutated"` - BuildStubs bool `blueprint:"mutated"` + BuildStubs bool `blueprint:"mutated"` } sanitize *sanitize @@ -281,13 +280,8 @@ func (linker *baseLinker) appendLdflags(flags []string) { linker.Properties.Ldflags = append(linker.Properties.Ldflags, flags...) } -// linkerInit initializes dynamic properties of the linker (such as runpath). +// linkerInit initializes dynamic properties of the linker. func (linker *baseLinker) linkerInit(ctx BaseModuleContext) { - if ctx.toolchain().Is64Bit() { - linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib64", "lib64") - } else { - linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "../lib", "lib") - } } func (linker *baseLinker) linkerProps() []interface{} { @@ -529,17 +523,8 @@ func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags { flags.Local.LdFlags = append(flags.Local.LdFlags, proptools.NinjaAndShellEscapeList(linker.Properties.Ldflags)...) - if ctx.Host() && !ctx.Windows() { - rpathPrefix := `\$$ORIGIN/` - if ctx.Darwin() { - rpathPrefix = "@loader_path/" - } - - if !ctx.static() { - for _, rpath := range linker.dynamicProperties.RunPaths { - flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,-rpath,"+rpathPrefix+rpath) - } - } + if ctx.Host() && !ctx.Windows() && !ctx.static() { + flags.Global.LdFlags = append(flags.Global.LdFlags, RpathFlags(ctx)...) } if ctx.useSdk() { @@ -610,6 +595,45 @@ func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags { return flags } +// RpathFlags returns the rpath linker flags for current target to search the following directories relative +// to the binary: +// +// - "." to find libraries alongside tests +// - "lib[64]" to find libraries in a subdirectory of the binaries' directory +// - "../lib[64]" to find libraries when the binaries are in a bin directory +// - "../../lib[64]" to find libraries in out/host/linux-x86/lib64 when the test or binary is in +// out/host/linux-x86/nativetest// +// - "../../../lib[[64] to find libraries in out/host/linux-x86/lib64 when the test or binary is in +// out/host/linux-x86/testcases/// +func RpathFlags(ctx android.ModuleContext) []string { + key := struct { + os android.OsType + arch android.ArchType + }{ctx.Target().Os, ctx.Target().Arch.ArchType} + + return ctx.Config().OnceStringSlice(android.NewCustomOnceKey(key), func() []string { + rpathPrefix := `\$$ORIGIN/` + if key.os == android.Darwin { + rpathPrefix = "@loader_path/" + } + + var libDir string + if key.arch.Multilib == "lib64" { + libDir = "lib64" + } else { + libDir = "lib" + } + + return []string{ + "-Wl,-rpath," + rpathPrefix, + "-Wl,-rpath," + rpathPrefix + libDir, + "-Wl,-rpath," + rpathPrefix + filepath.Join("..", libDir), + "-Wl,-rpath," + rpathPrefix + filepath.Join("../..", libDir), + "-Wl,-rpath," + rpathPrefix + filepath.Join("../../..", libDir), + } + }) +} + func (linker *baseLinker) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { panic(fmt.Errorf("baseLinker doesn't know how to link")) diff --git a/cc/test.go b/cc/test.go index 16ef0eff5..4b968dcf6 100644 --- a/cc/test.go +++ b/cc/test.go @@ -311,23 +311,6 @@ func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps { return deps } -func (test *testDecorator) linkerInit(ctx BaseModuleContext, linker *baseLinker) { - // 1. Add ../../lib[64] to rpath so that out/host/linux-x86/nativetest// can - // find out/host/linux-x86/lib[64]/library.so - // 2. Add ../../../lib[64] to rpath so that out/host/linux-x86/testcases/// can - // also find out/host/linux-x86/lib[64]/library.so - runpaths := []string{"../../lib", "../../../lib"} - for _, runpath := range runpaths { - if ctx.toolchain().Is64Bit() { - runpath += "64" - } - linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, runpath) - } - - // add "" to rpath so that test binaries can find libraries in their own test directory - linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "") -} - func (test *testDecorator) linkerProps() []interface{} { return []interface{}{&test.LinkerProperties} } @@ -356,11 +339,6 @@ func (test *testBinary) linkerProps() []interface{} { return props } -func (test *testBinary) linkerInit(ctx BaseModuleContext) { - test.testDecorator.linkerInit(ctx, test.binaryDecorator.baseLinker) - test.binaryDecorator.linkerInit(ctx) -} - func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { deps = test.testDecorator.linkerDeps(ctx, deps) deps = test.binaryDecorator.linkerDeps(ctx, deps) @@ -535,11 +513,6 @@ func (test *testLibrary) linkerProps() []interface{} { return append(props, test.libraryDecorator.linkerProps()...) } -func (test *testLibrary) linkerInit(ctx BaseModuleContext) { - test.testDecorator.linkerInit(ctx, test.libraryDecorator.baseLinker) - test.libraryDecorator.linkerInit(ctx) -} - func (test *testLibrary) linkerDeps(ctx DepsContext, deps Deps) Deps { deps = test.testDecorator.linkerDeps(ctx, deps) deps = test.libraryDecorator.linkerDeps(ctx, deps) @@ -610,15 +583,6 @@ func (benchmark *benchmarkDecorator) benchmarkBinary() bool { return true } -func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) { - runpath := "../../lib" - if ctx.toolchain().Is64Bit() { - runpath += "64" - } - benchmark.baseLinker.dynamicProperties.RunPaths = append(benchmark.baseLinker.dynamicProperties.RunPaths, runpath) - benchmark.binaryDecorator.linkerInit(ctx) -} - func (benchmark *benchmarkDecorator) linkerProps() []interface{} { props := benchmark.binaryDecorator.linkerProps() props = append(props, &benchmark.Properties) diff --git a/rust/compiler.go b/rust/compiler.go index 6055158ec..8ec42f079 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -15,6 +15,7 @@ package rust import ( + "android/soong/cc" "fmt" "path/filepath" "strings" @@ -307,19 +308,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flag flags.EmitXrefs = ctx.Config().EmitXrefRules() if ctx.Host() && !ctx.Windows() { - rpathPrefix := `\$$ORIGIN/` - if ctx.Darwin() { - rpathPrefix = "@loader_path/" - } - - var rpath string - if ctx.toolchain().Is64Bit() { - rpath = "lib64" - } else { - rpath = "lib" - } - flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+rpath) - flags.LinkFlags = append(flags.LinkFlags, "-Wl,-rpath,"+rpathPrefix+"../"+rpath) + flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...) } return flags diff --git a/rust/test.go b/rust/test.go index 4f922b494..4b5296e54 100644 --- a/rust/test.go +++ b/rust/test.go @@ -200,6 +200,7 @@ func (test *testDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags { if ctx.Device() { flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests") } + return flags }