From 69a79600cb782c18715c4cf1cbb7ed5b0df799c1 Mon Sep 17 00:00:00 2001 From: Brian Gaeke Date: Fri, 23 May 2003 20:27:07 +0000 Subject: [PATCH] gccld.cpp: Fix typo in header. Add IsArchive static method. Roll LoadLibraryFromDirectory() into LoadLibrary(), and factor LoadLibraryExactName() out of the result. Instead of treating the current directory specially, just insert it into LibPaths in the beginning of main(). Make LoadLibrary() take a "search" flag that says whether to search for the correct library, or just trust that LibName is right. Make LinkLibrary() take a "search" flag, and pass it to LoadLibrary(). Change the for-loop over InputFilenames to detect ar archives and link them in as libraries without searching. Change the for-loop over Libraries to explicitly turn on the "search" flag to LinkLibrary() that makes LoadLibrary() search for the correct library (i.e., when processing -lNAME options.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6316 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/gccld/gccld.cpp | 139 +++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 57 deletions(-) diff --git a/tools/gccld/gccld.cpp b/tools/gccld/gccld.cpp index 6be78c29e31..9a4c00680e4 100644 --- a/tools/gccld/gccld.cpp +++ b/tools/gccld/gccld.cpp @@ -9,7 +9,7 @@ // // Note that if someone (or a script) deletes the executable program generated, // the .bc file will be left around. Considering that this is a temporary hack, -// I'm not to worried about this. +// I'm not too worried about this. // //===----------------------------------------------------------------------===// @@ -117,70 +117,80 @@ static Module *LoadSingleLibraryObject(const std::string &Filename) { return M.release(); } +// IsArchive - Returns true iff FILENAME appears to be the name of an ar +// archive file. It determines this by checking the magic string at the +// beginning of the file. +static bool IsArchive (const std::string &filename) { + static const std::string ArchiveMagic ("!\012"); + char buf[1 + ArchiveMagic.size ()]; + std::ifstream f (filename.c_str ()); + f.read (buf, ArchiveMagic.size ()); + buf[ArchiveMagic.size ()] = '\0'; + return (ArchiveMagic == buf); +} -// LoadLibraryFromDirectory - This looks for a .a, .so, or .bc file in a -// particular directory. It returns true if no library is found, otherwise it -// puts the loaded modules into the Objects list, and sets isArchive to true if -// a .a file was loaded. -// -static inline bool LoadLibraryFromDirectory(const std::string &LibName, - const std::string &Directory, - std::vector &Objects, - bool &isArchive) { - if (FileExists(Directory + "lib" + LibName + ".a")) { - std::string ErrorMessage; - if (Verbose) std::cerr << " Loading '" << Directory << "lib" - << LibName << ".a'\n"; - if (!ReadArchiveFile(Directory + "lib" + LibName + ".a", Objects, - &ErrorMessage)) { // Read the archive file - isArchive = true; - return false; // Success! - } - - if (Verbose) { - std::cerr << " Error loading archive '" + Directory +"lib"+LibName+".a'"; - if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage; - std::cerr << "\n"; +// LoadLibraryExactName - This looks for a file with a known name and tries to +// load it, similarly to LoadLibraryFromDirectory(). +static inline bool LoadLibraryExactName (const std::string &FileName, + std::vector &Objects, bool &isArchive) { + if (Verbose) std::cerr << " Considering '" << FileName << "'\n"; + if (FileExists(FileName)) { + if (IsArchive (FileName)) { + std::string ErrorMessage; + if (Verbose) std::cerr << " Loading '" << FileName << "'\n"; + if (!ReadArchiveFile(FileName, Objects, &ErrorMessage)) { + isArchive = true; + return false; // Success! + } + if (Verbose) { + std::cerr << " Error loading archive '" + FileName + "'"; + if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage; + std::cerr << "\n"; + } + } else { + if (Module *M = LoadSingleLibraryObject(FileName)) { + isArchive = false; + Objects.push_back(M); + return false; + } } } - - if (FileExists(Directory + "lib" + LibName + ".so")) - if (Module *M = LoadSingleLibraryObject(Directory + "lib" + LibName+".so")){ - isArchive = false; - Objects.push_back(M); - return false; - } - - if (FileExists(Directory + "lib" + LibName + ".bc")) - if (Module *M = LoadSingleLibraryObject(Directory + "lib" + LibName+".bc")){ - isArchive = false; - Objects.push_back(M); - return false; - } return true; } -// LoadLibrary - This searches for a .a, .so, or .bc file which provides the -// LLVM bytecode for the library. It returns true if no library is found, -// otherwise it puts the loaded modules into the Objects list, and sets -// isArchive to true if a .a file was loaded. +// LoadLibrary - Try to load a library named LIBNAME that contains +// LLVM bytecode. If SEARCH is true, then search for a file named +// libLIBNAME.{a,so,bc} in the current library search path. Otherwise, +// assume LIBNAME is the real name of the library file. This method puts +// the loaded modules into the Objects list, and sets isArchive to true if +// a .a file was loaded. It returns true if no library is found or if an +// error occurs; otherwise it returns false. // static inline bool LoadLibrary(const std::string &LibName, std::vector &Objects, bool &isArchive, - std::string &ErrorMessage) { - std::string Directory; - unsigned NextLibPathIdx = 0; - - while (1) { - // Try loading from the current directory... - if (Verbose) std::cerr << " Looking in directory '" << Directory << "'\n"; - if (!LoadLibraryFromDirectory(LibName, Directory, Objects, isArchive)) + bool search, std::string &ErrorMessage) { + if (search) { + // First, try the current directory. Then, iterate over the + // directories in LibPaths, looking for a suitable match for LibName + // in each one. + for (unsigned NextLibPathIdx = 0; NextLibPathIdx != LibPaths.size(); + ++NextLibPathIdx) { + std::string Directory = LibPaths[NextLibPathIdx] + "/"; + if (!LoadLibraryExactName(Directory + "lib" + LibName + ".a", + Objects, isArchive)) + return false; + if (!LoadLibraryExactName(Directory + "lib" + LibName + ".so", + Objects, isArchive)) + return false; + if (!LoadLibraryExactName(Directory + "lib" + LibName + ".bc", + Objects, isArchive)) + return false; + } + } else { + // If they said no searching, then assume LibName is the real name. + if (!LoadLibraryExactName(LibName, Objects, isArchive)) return false; - - if (NextLibPathIdx == LibPaths.size()) break; - Directory = LibPaths[NextLibPathIdx++]+"/"; } - ErrorMessage = "error linking library '-l" + LibName+ "': library not found!"; return true; } @@ -231,7 +241,7 @@ static void GetAllUndefinedSymbols(Module *M, static bool LinkLibrary(Module *M, const std::string &LibName, - std::string &ErrorMessage) { + bool search, std::string &ErrorMessage) { std::set UndefinedSymbols; GetAllUndefinedSymbols(M, UndefinedSymbols); if (UndefinedSymbols.empty()) { @@ -241,7 +251,8 @@ static bool LinkLibrary(Module *M, const std::string &LibName, std::vector Objects; bool isArchive; - if (LoadLibrary(LibName, Objects, isArchive, ErrorMessage)) return true; + if (LoadLibrary(LibName, Objects, isArchive, search, ErrorMessage)) + return true; // Figure out which symbols are defined by all of the modules in the .a file std::vector > DefinedSymbols; @@ -307,11 +318,25 @@ int main(int argc, char **argv) { if (Composite.get() == 0) return PrintAndReturn(argv[0], ErrorMessage); + // We always look first in the current directory when searching for libraries. + LibPaths.insert(LibPaths.begin(), "."); + // If the user specied an extra search path in their environment, respect it. if (char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH")) LibPaths.push_back(SearchPath); for (unsigned i = 1; i < InputFilenames.size(); ++i) { + // A user may specify an ar archive without -l, perhaps because it + // is not installed as a library. Detect that and link the library. + if (IsArchive (InputFilenames[i])) { + if (Verbose) std::cerr << "Linking archive '" << InputFilenames[i] + << "'\n"; + if (LinkLibrary (Composite.get(), InputFilenames[i], false, ErrorMessage)) + return PrintAndReturn(argv[0], ErrorMessage, + ": error linking in '" + InputFilenames[i] + "'"); + continue; + } + std::auto_ptr M(LoadObject(InputFilenames[i], ErrorMessage)); if (M.get() == 0) return PrintAndReturn(argv[0], ErrorMessage); @@ -330,7 +355,7 @@ int main(int argc, char **argv) { // Link in all of the libraries next... for (unsigned i = 0; i != Libraries.size(); ++i) { if (Verbose) std::cerr << "Linking in library: -l" << Libraries[i] << "\n"; - if (LinkLibrary(Composite.get(), Libraries[i], ErrorMessage)) + if (LinkLibrary(Composite.get(), Libraries[i], true, ErrorMessage)) return PrintAndReturn(argv[0], ErrorMessage); }