From 6939f8141ce40c5bf1ed5958abe29cc31919464c Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Sat, 11 Sep 2004 04:32:42 +0000 Subject: [PATCH] Implement dependent library processing and search paths for them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16287 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-link/llvm-link.cpp | 161 ++++++++++++++++++++++++++++++---- 1 file changed, 144 insertions(+), 17 deletions(-) diff --git a/tools/llvm-link/llvm-link.cpp b/tools/llvm-link/llvm-link.cpp index 664529850c5..a4a283ced0a 100644 --- a/tools/llvm-link/llvm-link.cpp +++ b/tools/llvm-link/llvm-link.cpp @@ -20,6 +20,8 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/System/Signals.h" +#include "llvm/System/Path.h" +#include "llvm/ADT/SetVector.h" #include #include #include @@ -46,30 +48,56 @@ static cl::list LibPaths("L", cl::desc("Specify a library search path"), cl::ZeroOrMore, cl::value_desc("directory"), cl::Prefix); +static cl::list +Libraries("l", cl::desc("Specify library names to link with"), cl::ZeroOrMore, + cl::Prefix, cl::value_desc("library name")); + +// GetModule - This function is just factored out of the functions below +static inline Module* GetModule(const sys::Path& Filename) { + if (Verbose) std::cerr << "Loading '" << Filename.c_str() << "'\n"; + std::string ErrorMessage; + if (Filename.exists()) { + Module* Result = ParseBytecodeFile(Filename.get(), &ErrorMessage); + if (Result) return Result; // Load successful! + + if (Verbose) { + std::cerr << "Error opening bytecode file: '" << Filename.c_str() << "'"; + if (ErrorMessage.size()) std::cerr << ": " << ErrorMessage; + std::cerr << "\n"; + } + } else { + std::cerr << "Bytecode file: '" << Filename.c_str() + << "' does not exist.\n"; + } + return 0; +} + // LoadFile - Read the specified bytecode file in and return it. This routine // searches the link path for the specified file to try to find it... // static inline std::auto_ptr LoadFile(const std::string &FN) { - std::string Filename = FN; - std::string ErrorMessage; + sys::Path Filename; + if (!Filename.set_file(FN)) { + std::cerr << "Invalid file name: '" << Filename.c_str() << "'\n"; + return std::auto_ptr(); + } + + if (Module* Result = GetModule(Filename)) + return std::auto_ptr(Result); - unsigned NextLibPathIdx = 0; bool FoundAFile = false; - while (1) { - if (Verbose) std::cerr << "Loading '" << Filename << "'\n"; - if (getFileSize(Filename) != -1) FoundAFile = true; - Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); - if (Result) return std::auto_ptr(Result); // Load successful! - - if (Verbose) { - std::cerr << "Error opening bytecode file: '" << Filename << "'"; - if (ErrorMessage.size()) std::cerr << ": " << ErrorMessage; - std::cerr << "\n"; + for (unsigned i = 0; i < LibPaths.size(); i++) { + if (!Filename.set_directory(LibPaths[i])) { + std::cerr << "Invalid library path: '" << LibPaths[i] << "'\n"; + } else if (!Filename.append_file(FN)) { + std::cerr << "Invalid library path: '" << LibPaths[i] + << "/" << FN.c_str() << "'\n"; + } else if (Filename.exists()) { + FoundAFile = true; + if (Module *Result = GetModule(Filename)) + return std::auto_ptr(Result); // Load successful! } - - if (NextLibPathIdx == LibPaths.size()) break; - Filename = LibPaths[NextLibPathIdx++] + "/" + FN; } if (FoundAFile) @@ -80,8 +108,79 @@ static inline std::auto_ptr LoadFile(const std::string &FN) { return std::auto_ptr(); } +sys::Path GetPathForLinkageItem(const std::string& link_item, + const std::string& dir) { + sys::Path fullpath; + fullpath.set_directory(dir); + // Try *.o + fullpath.append_file(link_item); + fullpath.append_suffix("o"); + if (fullpath.readable()) + return fullpath; + // Try *.bc + fullpath.elide_suffix(); + fullpath.append_suffix("bc"); + if (fullpath.readable()) + return fullpath; + + // Try *.so + fullpath.elide_suffix(); + fullpath.append_suffix(sys::Path::GetDLLSuffix()); + if (fullpath.readable()) + return fullpath; + + // Try lib*.a + fullpath.set_directory(dir); + fullpath.append_file(std::string("lib") + link_item); + fullpath.append_suffix("a"); + if (fullpath.readable()) + return fullpath; + + // Didn't find one. + fullpath.clear(); + return fullpath; +} + +static inline bool LoadLibrary(const std::string &FN, Module*& Result) { + Result = 0; + sys::Path Filename; + if (!Filename.set_file(FN)) { + return false; + } + + if (Filename.readable() && Filename.is_bytecode_file()) { + if (Result = GetModule(Filename)) + return true; + } + + bool foundAFile = false; + + for (unsigned I = 0; I < LibPaths.size(); I++) { + sys::Path path = GetPathForLinkageItem(FN,LibPaths[I]); + if (!path.is_empty()) { + if (path.is_bytecode_file()) { + if (Result = GetModule(path)) { + return true; + } else { + // We found file but its not a valid bytecode file so we + // return false and leave Result null. + return false; + } + } else { + // We found a file, but its not a bytecode file so we return + // false and leave Result null. + return false; + } + } + } + + // We didn't find a file so we leave Result null and return + // false to indicate that the library should be just left in the + // emitted module as resolvable at runtime. + return false; +} int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " llvm linker\n"); @@ -101,12 +200,40 @@ int main(int argc, char **argv) { if (Verbose) std::cerr << "Linking in '" << InputFilenames[i] << "'\n"; if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) { - std::cerr << argv[0] << ": error linking in '" << InputFilenames[i] + std::cerr << argv[0] << ": link error in '" << InputFilenames[i] << "': " << ErrorMessage << "\n"; return 1; } } + // Get the list of dependent libraries from the composite module + const Module::LibraryListType& libs = Composite.get()->getLibraries(); + + // Iterate over the list of dependent libraries, linking them in as we + // find them + Module::LibraryListType::const_iterator I = libs.begin(); + while (I != libs.end()) { + Module* Mod = 0; + if (LoadLibrary(*I,Mod)) { + if (Mod != 0) { + std::auto_ptr M(Mod); + if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) { + std::cerr << argv[0] << ": link error in '" << *I + << "': " << ErrorMessage << "\n"; + return 1; + } + } else { + std::cerr << argv[0] << ": confused loading library '" << *I + << "'. Aborting\n"; + return 2; + } + } + ++I; + } + + // TODO: Iterate over the -l list and link in any modules containing + // global symbols that have not been resolved so far. + if (DumpAsm) std::cerr << "Here's the assembly:\n" << Composite.get(); std::ostream *Out = &std::cout; // Default to printing to stdout...