diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 0e507a48f783..d4000b546756 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -22,6 +22,7 @@ struct Configuration { llvm::StringRef DynamicLinker; std::string RPath; std::vector InputSearchPaths; + llvm::StringRef Sysroot; bool Shared = false; bool DiscardAll = false; bool DiscardLocals = false; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 6bc3d754bbc7..948d4ecd8e73 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -60,6 +60,21 @@ static std::unique_ptr createFile(MemoryBufferRef MB) { return createELFFile(MB); } +// Makes a path by concatenating Dir and File. +// If Dir starts with "=" the result will be preceded by SysRoot, +// which can be set with --sysroot command line switch. +static std::string buildSysrootedPath(StringRef Dir, StringRef File) { + SmallString<128> Path; + if (Dir.startswith("=")) { + Path.assign(Config->Sysroot); + sys::path::append(Path, Dir.substr(1), File); + } else { + Path.assign(Dir); + sys::path::append(Path, File); + } + return Path.str().str(); +} + // Searches a given library from input search paths, which are filled // from -L command line switches. Returns a path to an existent library file. static std::string searchLibrary(StringRef Path) { @@ -70,13 +85,11 @@ static std::string searchLibrary(StringRef Path) { Names.push_back((Twine("lib") + Path + ".so").str()); Names.push_back((Twine("lib") + Path + ".a").str()); } - SmallString<128> FullPath; for (StringRef Dir : Config->InputSearchPaths) { for (const std::string &Name : Names) { - FullPath = Dir; - sys::path::append(FullPath, Name); - if (sys::fs::exists(FullPath.str())) - return FullPath.str().str(); + std::string FullPath = buildSysrootedPath(Dir, Name); + if (sys::fs::exists(FullPath)) + return FullPath; } } error(Twine("Unable to find library -l") + Path); @@ -96,6 +109,9 @@ void LinkerDriver::link(ArrayRef ArgsArr) { if (auto *Arg = Args.getLastArg(OPT_dynamic_linker)) Config->DynamicLinker = Arg->getValue(); + if (auto *Arg = Args.getLastArg(OPT_sysroot)) + Config->Sysroot = Arg->getValue(); + std::vector RPaths; for (auto *Arg : Args.filtered(OPT_rpath)) RPaths.push_back(Arg->getValue()); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 9eb363a88729..1a237cb6b1cd 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -49,3 +49,6 @@ def l : Joined<["-"], "l">, MetaVarName<"">, def alias_l : Joined<["--"], "library=">, Alias; + +def sysroot : Joined<["--"], "sysroot=">, + HelpText<"Set the system root">; diff --git a/lld/test/elf2/sysroot.s b/lld/test/elf2/sysroot.s new file mode 100644 index 000000000000..845fdfe3500c --- /dev/null +++ b/lld/test/elf2/sysroot.s @@ -0,0 +1,36 @@ +// RUN: mkdir -p %t/lib +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t/m.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +// RUN: %p/Inputs/libsearch-st.s -o %t/st.o +// RUN: rm -f %t/lib/libls.a +// RUN: llvm-ar rcs %t/lib/libls.a %t/st.o +// REQUIRES: x86 + +// Should not link because of undefined symbol _bar +// RUN: not lld -flavor gnu2 -o %t/r %t/m.o 2>&1 \ +// RUN: | FileCheck --check-prefix=UNDEFINED %s +// UNDEFINED: undefined symbol: _bar + +// We need to be sure that there is no suitable library in the /lib directory +// RUN: not lld -flavor gnu2 -o %t/r %t/m.o -L/lib -l:libls.a 2>&1 \ +// RUN: | FileCheck --check-prefix=NOLIB %s +// NOLIB: Unable to find library -l:libls.a + +// Should just remove the '=' symbol if --sysroot is not specified. +// Case 1: relative path +// RUN: cd %t && lld -flavor gnu2 -o %t/r %t/m.o -L=lib -l:libls.a +// Case 2: absolute path +// RUN: cd %p && lld -flavor gnu2 -o %t/r %t/m.o -L=%t/lib -l:libls.a + +// RUN: cd %p + +// Should substitute SysRoot if specified +// RUN: lld -flavor gnu2 -o %t/r %t/m.o --sysroot=%t -L=lib -l:libls.a +// RUN: lld -flavor gnu2 -o %t/r %t/m.o --sysroot=%t -L=/lib -l:libls.a + +// Should not substitute SysRoot if the directory name does not start with '=' +// RUN: not lld -flavor gnu2 -o %t/r %r/m.o --sysroot=%t -Llib -l:libls.a +// RUN: not lld -flavor gnu2 -o %t/r %r/m.o --sysroot=%t -L/lib -l:libls.a + +.globl _start,_bar; +_start: