[llvm-commits] CVS: llvm/tools/gccld/gccld.cpp

Brian Gaeke gaeke at cs.uiuc.edu
Fri May 23 15:28:01 PDT 2003


Changes in directory llvm/tools/gccld:

gccld.cpp updated: 1.30 -> 1.31

---
Log message:

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.)


---
Diffs of the changes:

Index: llvm/tools/gccld/gccld.cpp
diff -u llvm/tools/gccld/gccld.cpp:1.30 llvm/tools/gccld/gccld.cpp:1.31
--- llvm/tools/gccld/gccld.cpp:1.30	Tue May 13 17:14:13 2003
+++ llvm/tools/gccld/gccld.cpp	Fri May 23 15:27:07 2003
@@ -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 @@
   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 ("!<arch>\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<Module*> &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<Module*> &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<Module*> &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 bool LinkLibrary(Module *M, const std::string &LibName,
-                        std::string &ErrorMessage) {
+                        bool search, std::string &ErrorMessage) {
   std::set<std::string> UndefinedSymbols;
   GetAllUndefinedSymbols(M, UndefinedSymbols);
   if (UndefinedSymbols.empty()) {
@@ -241,7 +251,8 @@
 
   std::vector<Module*> 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<std::set<std::string> > DefinedSymbols;
@@ -307,11 +318,25 @@
   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<Module> M(LoadObject(InputFilenames[i], ErrorMessage));
     if (M.get() == 0)
       return PrintAndReturn(argv[0], ErrorMessage);
@@ -330,7 +355,7 @@
   // 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);
   }
 





More information about the llvm-commits mailing list