From 54b71daec4294d1746473127d71241885f8dede6 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sun, 31 May 2015 19:17:12 +0000 Subject: [PATCH] COFF: Refactor functions to find files from search paths. llvm-svn: 238678 --- lld/COFF/Driver.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++-- lld/COFF/Driver.h | 15 +++++++++---- lld/COFF/DriverUtils.cpp | 48 ----------------------------------------- lld/COFF/Memory.h | 1 + 4 files changed, 66 insertions(+), 54 deletions(-) diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index d178bac..8ea41e9 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" #include @@ -30,6 +31,7 @@ using namespace llvm; using llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; using llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI; using llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI; +using llvm::sys::Process; namespace lld { namespace coff { @@ -94,7 +96,7 @@ LinkerDriver::parseDirectives(StringRef S, std::unique_ptr Args = std::move(ArgsOrErr.get()); for (auto *Arg : Args->filtered(OPT_defaultlib)) { - std::string Path = findLib(Arg->getValue()); + StringRef Path = findLib(Arg->getValue()); if (!insertFile(Path)) continue; Res->push_back(llvm::make_unique(Path)); @@ -102,6 +104,56 @@ LinkerDriver::parseDirectives(StringRef S, return std::error_code(); } +// Find file from search paths. You can omit ".obj", this function takes +// care of that. Note that the returned path is not guaranteed to exist. +StringRef LinkerDriver::findFile(StringRef Filename) { + bool hasPathSep = (Filename.find_first_of("/\\") != StringRef::npos); + if (hasPathSep) + return Filename; + bool hasExt = (Filename.find('.') != StringRef::npos); + for (StringRef Dir : SearchPaths) { + SmallString<128> Path = Dir; + llvm::sys::path::append(Path, Filename); + if (llvm::sys::fs::exists(Path.str())) + return Alloc.save(Path.str()); + if (!hasExt) { + Path.append(".obj"); + if (llvm::sys::fs::exists(Path.str())) + return Alloc.save(Path.str()); + } + } + return Filename; +} + +StringRef LinkerDriver::findLib(StringRef Filename) { + StringRef S = addExtOpt(Filename, ".lib"); + return findFile(S); +} + +// Add Ext to Filename if Filename has no file extension. +StringRef LinkerDriver::addExtOpt(StringRef Filename, StringRef Ext) { + bool hasExt = (Filename.find('.') != StringRef::npos); + if (hasExt) + return Filename; + return Alloc.save(Filename + Ext); +} + +// Parses LIB environment which contains a list of search paths. +std::vector LinkerDriver::getSearchPaths() { + std::vector Ret; + Ret.push_back("."); + Optional EnvOpt = Process::GetEnv("LIB"); + if (!EnvOpt.hasValue()) + return Ret; + StringRef Env = Alloc.save(*EnvOpt); + while (!Env.empty()) { + StringRef Path; + std::tie(Path, Env) = Env.split(';'); + Ret.push_back(Path); + } + return Ret; +} + bool LinkerDriver::link(int Argc, const char *Argv[]) { // Parse command line options. auto ArgsOrErr = parseArgs(Argc, Argv); @@ -187,7 +239,7 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) { // The symbol table will take care of name resolution. SymbolTable Symtab; for (auto *Arg : Args->filtered(OPT_INPUT)) { - std::string Path = findFile(Arg->getValue()); + StringRef Path = findFile(Arg->getValue()); if (!insertFile(Path)) continue; if (auto EC = Symtab.addFile(createFile(Path))) { diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 7bdf3ae..7123c43 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -35,6 +35,7 @@ bool link(int Argc, const char *Argv[]); class LinkerDriver { public: + LinkerDriver() : SearchPaths(getSearchPaths()) {} bool link(int Argc, const char *Argv[]); // Used by the resolver to parse .drectve section contents. @@ -45,6 +46,16 @@ private: // Returns false if a given file has already been read. bool insertFile(StringRef Path); + // Searches a file from search paths. + StringRef findFile(StringRef Filename); + StringRef findLib(StringRef Filename); + StringRef addExtOpt(StringRef Filename, StringRef Ext); + + // Parses LIB environment which contains a list of search paths. + // The returned list always contains "." as the first element. + std::vector getSearchPaths(); + + std::vector SearchPaths; std::set VisitedFiles; StringAllocator Alloc; }; @@ -56,10 +67,6 @@ parseArgs(int Argc, const char *Argv[]); void printHelp(const char *Argv0); -// "ENV" environment variable-aware file finders. -std::string findLib(StringRef Filename); -std::string findFile(StringRef Filename); - // For /machine option. ErrorOr getMachineType(llvm::opt::InputArgList *Args); diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index b6d12b1..6e80468 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -39,54 +39,6 @@ using llvm::sys::fs::identify_magic; namespace lld { namespace coff { -// Split the given string with the path separator. -static std::vector splitPathList(StringRef str) { - std::vector ret; - while (!str.empty()) { - StringRef path; - std::tie(path, str) = str.split(';'); - ret.push_back(path); - } - return ret; -} - -std::string findLib(StringRef Filename) { - if (llvm::sys::fs::exists(Filename)) - return Filename; - std::string Name; - if (Filename.endswith_lower(".lib")) { - Name = Filename; - } else { - Name = (Filename + ".lib").str(); - } - - Optional Env = Process::GetEnv("LIB"); - if (!Env.hasValue()) - return Filename; - for (StringRef Dir : splitPathList(*Env)) { - SmallString<128> Path = Dir; - llvm::sys::path::append(Path, Name); - if (llvm::sys::fs::exists(Path.str())) - return Path.str(); - } - return Filename; -} - -std::string findFile(StringRef Filename) { - if (llvm::sys::fs::exists(Filename)) - return Filename; - Optional Env = Process::GetEnv("LIB"); - if (!Env.hasValue()) - return Filename; - for (StringRef Dir : splitPathList(*Env)) { - SmallString<128> Path = Dir; - llvm::sys::path::append(Path, Filename); - if (llvm::sys::fs::exists(Path.str())) - return Path.str(); - } - return Filename; -} - // Returns /machine's value. ErrorOr getMachineType(llvm::opt::InputArgList *Args) { if (auto *Arg = Args->getLastArg(OPT_machine)) { diff --git a/lld/COFF/Memory.h b/lld/COFF/Memory.h index d8afcaa..8ff4a42 100644 --- a/lld/COFF/Memory.h +++ b/lld/COFF/Memory.h @@ -31,6 +31,7 @@ public: StringRef save(Twine S) { return save(StringRef(S.str())); } StringRef save(const char *S) { return save(StringRef(S)); } + StringRef save(std::string &S) { return save(StringRef(S)); } private: llvm::BumpPtrAllocator Alloc; -- 2.7.4