-
- if (Verbose) std::cerr << "Linking in '" << Filename << "'\n";
-
- return (LinkModules (HeadModule, M.get(), &ErrorMessage));
-}
-
-//
-// Function: LinkFiles ()
-//
-// Description:
-// This function takes a module and a list of files and links them all
-// together. It locates the file either in the current directory, as it's
-// absolute or relative pathname, or as a file somewhere in
-// LLVM_LIB_SEARCH_PATH.
-//
-// Inputs:
-// progname - The name of the program (infamous argv[0]).
-// HeadModule - The module under which all files will be linked.
-// Files - A vector of C++ strings indicating the LLVM bytecode filenames
-// to be linked. The names can refer to a mixture of pure LLVM
-// bytecode files and archive (ar) formatted files.
-// Verbose - Flags whether verbose output should be printed while linking.
-//
-// Outputs:
-// HeadModule - The module will have the specified LLVM bytecode files linked
-// in.
-//
-// Return value:
-// FALSE - No errors.
-// TRUE - Some error occurred.
-//
-bool
-LinkFiles (const char * progname,
- Module * HeadModule,
- const std::vector<std::string> & Files,
- bool Verbose)
-{
- // String in which to receive error messages.
- std::string ErrorMessage;
-
- // Full pathname of the file
- std::string Pathname;
-
- // Get the library search path from the environment
- char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");
-
- for (unsigned i = 1; i < Files.size(); ++i)
- {
- //
- // Determine where this file lives.
- //
- if (FileExists (Files[i]))
- {
- Pathname = Files[i];
- }
- else
- {
- if (SearchPath == NULL)
- {
- std::cerr << "Cannot find " << Files[i];
- return true;
- }
-
- Pathname = std::string(SearchPath)+"/"+Files[i];
- if (!FileExists (Pathname))
- {
- std::cerr << "Cannot find " << Files[i];
- return true;
- }
- }
-
- //
- // 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(Pathname))
- {
- if (Verbose)
- {
- std::cerr << "Linking archive '" << Files[i] << "'\n";
- }
-
- if (LinkInArchive (HeadModule, Pathname, ErrorMessage, Verbose))
- {
- PrintAndReturn(progname, ErrorMessage,
- ": Error linking in '" + Files[i] + "'");
- return true;
- }
- }
- else
- {
- if (Verbose)
- {
- std::cerr << "Linking file '" << Files[i] << "'\n";
- }
-
- if (LinkInFile (HeadModule, Pathname, ErrorMessage, Verbose))
- {
- PrintAndReturn(progname, ErrorMessage,
- ": error linking in '" + Files[i] + "'");
- return true;
- }
- }
- }
-
- return false;
-}
-
-//
-// Function: LinkLibraries ()
-//
-// Description:
-// This function takes the specified library files and links them into the
-// main bytecode object file.
-//
-// Inputs:
-// progname - The name of the program (infamous argv[0]).
-// HeadModule - The module into which all necessary libraries will be linked.
-// Libraries - The list of libraries to link into the module.
-// LibPaths - The list of library paths in which to find libraries.
-// Verbose - Flags whether verbose messages should be printed.
-// Native - Flags whether native code is being generated.
-//
-// Outputs:
-// HeadModule - The module will have all necessary libraries linked in.
-//
-// Return value:
-// FALSE - No error.
-// TRUE - Error.
-//
-bool
-LinkLibraries (const char * progname,
- Module * HeadModule,
- const std::vector<std::string> & Libraries,
- const std::vector<std::string> & LibPaths,
- bool Verbose,
- bool Native)
-{
- // String in which to receive error messages.
- std::string ErrorMessage;
-
- for (unsigned i = 1; i < Libraries.size(); ++i)
- {
- //
- // Determine where this library lives.
- //
- std::string Pathname = FindLib (Libraries[i], LibPaths);
- if (Pathname.empty())
- {
- //
- // If the pathname does not exist, then continue to the next one if
- // we're doing a native link and give an error if we're doing a bytecode
- // link.
- //
- if (Native)
- {
- continue;
- }
- else
- {
- PrintAndReturn (progname, "Cannot find " + Libraries[i]);
- return true;
- }
- }
-
- //
- // 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(Pathname))
- {
- if (Verbose)
- {
- std::cerr << "Linking archive '" << Libraries[i] << "'\n";
- }
-
- if (LinkInArchive (HeadModule, Pathname, ErrorMessage, Verbose))
- {
- PrintAndReturn(progname, ErrorMessage,
- ": Error linking in '" + Libraries[i] + "'");
- return true;
- }
- }
- else
- {
- if (Verbose)
- {
- std::cerr << "Linking file '" << Libraries[i] << "'\n";
- }
-
- if (LinkInFile (HeadModule, Pathname, ErrorMessage, Verbose))
- {
- PrintAndReturn(progname, ErrorMessage,
- ": error linking in '" + Libraries[i] + "'");
- return true;
- }
+ is_native = false;
+
+ // Save a set of symbols that are not defined by the archive. Since we're
+ // entering a loop, there's no point searching for these multiple times. This
+ // variable is used to "set_subtract" from the set of undefined symbols.
+ std::set<std::string> NotDefinedByArchive;
+
+ // Save the current set of undefined symbols, because we may have to make
+ // multiple passes over the archive:
+ std::set<std::string> CurrentlyUndefinedSymbols;
+
+ do {
+ CurrentlyUndefinedSymbols = UndefinedSymbols;
+
+ // Find the modules we need to link into the target module
+ std::set<ModuleProvider*> Modules;
+ if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg))
+ return error("Cannot find symbols in '" + Filename.toString() +
+ "': " + ErrMsg);
+
+ // If we didn't find any more modules to link this time, we are done
+ // searching this archive.
+ if (Modules.empty())
+ break;
+
+ // Any symbols remaining in UndefinedSymbols after
+ // findModulesDefiningSymbols are ones that the archive does not define. So
+ // we add them to the NotDefinedByArchive variable now.
+ NotDefinedByArchive.insert(UndefinedSymbols.begin(),
+ UndefinedSymbols.end());
+
+ // Loop over all the ModuleProviders that we got back from the archive
+ for (std::set<ModuleProvider*>::iterator I=Modules.begin(), E=Modules.end();
+ I != E; ++I) {
+
+ // Get the module we must link in.
+ std::string moduleErrorMsg;
+ std::auto_ptr<Module> AutoModule((*I)->releaseModule( &moduleErrorMsg ));
+ if (!moduleErrorMsg.empty())
+ return error("Could not load a module: " + moduleErrorMsg);
+
+ Module* aModule = AutoModule.get();
+
+ if (aModule != NULL) {
+ verbose(" Linking in module: " + aModule->getModuleIdentifier());
+
+ // Link it in
+ if (LinkInModule(aModule, &moduleErrorMsg)) {
+ return error("Cannot link in module '" +
+ aModule->getModuleIdentifier() + "': " + moduleErrorMsg);
+ }
+ }