Home | History | Annotate | Download | only in Linker
      1 //===- lib/Linker/Linker.cpp - Basic Linker functionality  ----------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains basic Linker functionality that all usages will need.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/Linker.h"
     15 #include "llvm/Module.h"
     16 #include "llvm/Bitcode/ReaderWriter.h"
     17 #include "llvm/Support/Path.h"
     18 #include "llvm/Support/MemoryBuffer.h"
     19 #include "llvm/Support/raw_ostream.h"
     20 #include "llvm/Config/config.h"
     21 #include "llvm/Support/system_error.h"
     22 using namespace llvm;
     23 
     24 Linker::Linker(StringRef progname, StringRef modname,
     25                LLVMContext& C, unsigned flags):
     26   Context(C),
     27   Composite(new Module(modname, C)),
     28   LibPaths(),
     29   Flags(flags),
     30   Error(),
     31   ProgramName(progname) { }
     32 
     33 Linker::Linker(StringRef progname, Module* aModule, unsigned flags) :
     34   Context(aModule->getContext()),
     35   Composite(aModule),
     36   LibPaths(),
     37   Flags(flags),
     38   Error(),
     39   ProgramName(progname) { }
     40 
     41 Linker::~Linker() {
     42   delete Composite;
     43 }
     44 
     45 bool
     46 Linker::error(StringRef message) {
     47   Error = message;
     48   if (!(Flags&QuietErrors))
     49     errs() << ProgramName << ": error: " << message << "\n";
     50   return true;
     51 }
     52 
     53 bool
     54 Linker::warning(StringRef message) {
     55   Error = message;
     56   if (!(Flags&QuietWarnings))
     57     errs() << ProgramName << ": warning: " << message << "\n";
     58   return false;
     59 }
     60 
     61 void
     62 Linker::verbose(StringRef message) {
     63   if (Flags&Verbose)
     64     errs() << "  " << message << "\n";
     65 }
     66 
     67 void
     68 Linker::addPath(const sys::Path& path) {
     69   LibPaths.push_back(path);
     70 }
     71 
     72 void
     73 Linker::addPaths(const std::vector<std::string>& paths) {
     74   for (unsigned i = 0, e = paths.size(); i != e; ++i)
     75     LibPaths.push_back(sys::Path(paths[i]));
     76 }
     77 
     78 void
     79 Linker::addSystemPaths() {
     80   sys::Path::GetBitcodeLibraryPaths(LibPaths);
     81   LibPaths.insert(LibPaths.begin(),sys::Path("./"));
     82 }
     83 
     84 Module*
     85 Linker::releaseModule() {
     86   Module* result = Composite;
     87   LibPaths.clear();
     88   Error.clear();
     89   Composite = 0;
     90   Flags = 0;
     91   return result;
     92 }
     93 
     94 // LoadObject - Read in and parse the bitcode file named by FN and return the
     95 // module it contains (wrapped in an auto_ptr), or auto_ptr<Module>() and set
     96 // Error if an error occurs.
     97 std::auto_ptr<Module>
     98 Linker::LoadObject(const sys::Path &FN) {
     99   std::string ParseErrorMessage;
    100   Module *Result = 0;
    101 
    102   OwningPtr<MemoryBuffer> Buffer;
    103   if (error_code ec = MemoryBuffer::getFileOrSTDIN(FN.c_str(), Buffer))
    104     ParseErrorMessage = "Error reading file '" + FN.str() + "'" + ": "
    105                       + ec.message();
    106   else
    107     Result = ParseBitcodeFile(Buffer.get(), Context, &ParseErrorMessage);
    108 
    109   if (Result)
    110     return std::auto_ptr<Module>(Result);
    111   Error = "Bitcode file '" + FN.str() + "' could not be loaded";
    112   if (ParseErrorMessage.size())
    113     Error += ": " + ParseErrorMessage;
    114   return std::auto_ptr<Module>();
    115 }
    116 
    117 // IsLibrary - Determine if "Name" is a library in "Directory". Return
    118 // a non-empty sys::Path if its found, an empty one otherwise.
    119 static inline sys::Path IsLibrary(StringRef Name,
    120                                   const sys::Path &Directory) {
    121 
    122   sys::Path FullPath(Directory);
    123 
    124   // Try the libX.a form
    125   FullPath.appendComponent(("lib" + Name).str());
    126   FullPath.appendSuffix("a");
    127   if (FullPath.isArchive())
    128     return FullPath;
    129 
    130   // Try the libX.bca form
    131   FullPath.eraseSuffix();
    132   FullPath.appendSuffix("bca");
    133   if (FullPath.isArchive())
    134     return FullPath;
    135 
    136   // Try the libX.so (or .dylib) form
    137   FullPath.eraseSuffix();
    138   FullPath.appendSuffix(sys::Path::GetDLLSuffix());
    139   if (FullPath.isDynamicLibrary())  // Native shared library?
    140     return FullPath;
    141   if (FullPath.isBitcodeFile())    // .so file containing bitcode?
    142     return FullPath;
    143 
    144   // Try libX form, to make it possible to add dependency on the
    145   // specific version of .so, like liblzma.so.1.0.0
    146   FullPath.eraseSuffix();
    147   if (FullPath.isDynamicLibrary())  // Native shared library?
    148     return FullPath;
    149   if (FullPath.isBitcodeFile())    // .so file containing bitcode?
    150     return FullPath;
    151 
    152   // Not found .. fall through
    153 
    154   // Indicate that the library was not found in the directory.
    155   FullPath.clear();
    156   return FullPath;
    157 }
    158 
    159 /// FindLib - Try to convert Filename into the name of a file that we can open,
    160 /// if it does not already name a file we can open, by first trying to open
    161 /// Filename, then libFilename.[suffix] for each of a set of several common
    162 /// library suffixes, in each of the directories in LibPaths. Returns an empty
    163 /// Path if no matching file can be found.
    164 ///
    165 sys::Path
    166 Linker::FindLib(StringRef Filename) {
    167   // Determine if the pathname can be found as it stands.
    168   sys::Path FilePath(Filename);
    169   if (FilePath.canRead() &&
    170       (FilePath.isArchive() || FilePath.isDynamicLibrary()))
    171     return FilePath;
    172 
    173   // Iterate over the directories in Paths to see if we can find the library
    174   // there.
    175   for (unsigned Index = 0; Index != LibPaths.size(); ++Index) {
    176     sys::Path Directory(LibPaths[Index]);
    177     sys::Path FullPath = IsLibrary(Filename, Directory);
    178     if (!FullPath.isEmpty())
    179       return FullPath;
    180   }
    181   return sys::Path();
    182 }
    183