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
This commit is contained in:
Brian Gaeke
2003-05-23 20:27:07 +00:00
parent 02ec5ede6c
commit 69a79600cb

View File

@@ -9,7 +9,7 @@
// //
// Note that if someone (or a script) deletes the executable program generated, // 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, // 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(); 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 // LoadLibraryExactName - This looks for a file with a known name and tries to
// particular directory. It returns true if no library is found, otherwise it // load it, similarly to LoadLibraryFromDirectory().
// puts the loaded modules into the Objects list, and sets isArchive to true if static inline bool LoadLibraryExactName (const std::string &FileName,
// a .a file was loaded. std::vector<Module*> &Objects, bool &isArchive) {
// if (Verbose) std::cerr << " Considering '" << FileName << "'\n";
static inline bool LoadLibraryFromDirectory(const std::string &LibName, if (FileExists(FileName)) {
const std::string &Directory, if (IsArchive (FileName)) {
std::vector<Module*> &Objects, std::string ErrorMessage;
bool &isArchive) { if (Verbose) std::cerr << " Loading '" << FileName << "'\n";
if (FileExists(Directory + "lib" + LibName + ".a")) { if (!ReadArchiveFile(FileName, Objects, &ErrorMessage)) {
std::string ErrorMessage; isArchive = true;
if (Verbose) std::cerr << " Loading '" << Directory << "lib" return false; // Success!
<< LibName << ".a'\n"; }
if (!ReadArchiveFile(Directory + "lib" + LibName + ".a", Objects, if (Verbose) {
&ErrorMessage)) { // Read the archive file std::cerr << " Error loading archive '" + FileName + "'";
isArchive = true; if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage;
return false; // Success! std::cerr << "\n";
} }
} else {
if (Verbose) { if (Module *M = LoadSingleLibraryObject(FileName)) {
std::cerr << " Error loading archive '" + Directory +"lib"+LibName+".a'"; isArchive = false;
if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage; Objects.push_back(M);
std::cerr << "\n"; 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; return true;
} }
// LoadLibrary - This searches for a .a, .so, or .bc file which provides the // LoadLibrary - Try to load a library named LIBNAME that contains
// LLVM bytecode for the library. It returns true if no library is found, // LLVM bytecode. If SEARCH is true, then search for a file named
// otherwise it puts the loaded modules into the Objects list, and sets // libLIBNAME.{a,so,bc} in the current library search path. Otherwise,
// isArchive to true if a .a file was loaded. // 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, static inline bool LoadLibrary(const std::string &LibName,
std::vector<Module*> &Objects, bool &isArchive, std::vector<Module*> &Objects, bool &isArchive,
std::string &ErrorMessage) { bool search, std::string &ErrorMessage) {
std::string Directory; if (search) {
unsigned NextLibPathIdx = 0; // First, try the current directory. Then, iterate over the
// directories in LibPaths, looking for a suitable match for LibName
while (1) { // in each one.
// Try loading from the current directory... for (unsigned NextLibPathIdx = 0; NextLibPathIdx != LibPaths.size();
if (Verbose) std::cerr << " Looking in directory '" << Directory << "'\n"; ++NextLibPathIdx) {
if (!LoadLibraryFromDirectory(LibName, Directory, Objects, isArchive)) 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; return false;
if (NextLibPathIdx == LibPaths.size()) break;
Directory = LibPaths[NextLibPathIdx++]+"/";
} }
ErrorMessage = "error linking library '-l" + LibName+ "': library not found!"; ErrorMessage = "error linking library '-l" + LibName+ "': library not found!";
return true; return true;
} }
@@ -231,7 +241,7 @@ static void GetAllUndefinedSymbols(Module *M,
static bool LinkLibrary(Module *M, const std::string &LibName, static bool LinkLibrary(Module *M, const std::string &LibName,
std::string &ErrorMessage) { bool search, std::string &ErrorMessage) {
std::set<std::string> UndefinedSymbols; std::set<std::string> UndefinedSymbols;
GetAllUndefinedSymbols(M, UndefinedSymbols); GetAllUndefinedSymbols(M, UndefinedSymbols);
if (UndefinedSymbols.empty()) { if (UndefinedSymbols.empty()) {
@@ -241,7 +251,8 @@ static bool LinkLibrary(Module *M, const std::string &LibName,
std::vector<Module*> Objects; std::vector<Module*> Objects;
bool isArchive; 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 // Figure out which symbols are defined by all of the modules in the .a file
std::vector<std::set<std::string> > DefinedSymbols; std::vector<std::set<std::string> > DefinedSymbols;
@@ -307,11 +318,25 @@ int main(int argc, char **argv) {
if (Composite.get() == 0) if (Composite.get() == 0)
return PrintAndReturn(argv[0], ErrorMessage); 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 the user specied an extra search path in their environment, respect it.
if (char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH")) if (char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH"))
LibPaths.push_back(SearchPath); LibPaths.push_back(SearchPath);
for (unsigned i = 1; i < InputFilenames.size(); ++i) { 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)); std::auto_ptr<Module> M(LoadObject(InputFilenames[i], ErrorMessage));
if (M.get() == 0) if (M.get() == 0)
return PrintAndReturn(argv[0], ErrorMessage); return PrintAndReturn(argv[0], ErrorMessage);
@@ -330,7 +355,7 @@ int main(int argc, char **argv) {
// Link in all of the libraries next... // Link in all of the libraries next...
for (unsigned i = 0; i != Libraries.size(); ++i) { for (unsigned i = 0; i != Libraries.size(); ++i) {
if (Verbose) std::cerr << "Linking in library: -l" << Libraries[i] << "\n"; 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); return PrintAndReturn(argv[0], ErrorMessage);
} }