// BuildLinkItems -- This function generates a LinkItemList for the LinkItems // linker function by combining the Files and Libraries in the order they were // declared on the command line. static void BuildLinkItems( Linker::ItemList& Items, const cl::list<std::string>& Files, const cl::list<std::string>& Libraries) { // Build the list of linkage items for LinkItems. cl::list<std::string>::const_iterator fileIt = Files.begin(); cl::list<std::string>::const_iterator libIt = Libraries.begin(); int libPos = -1, filePos = -1; while ( libIt != Libraries.end() || fileIt != Files.end() ) { if (libIt != Libraries.end()) libPos = Libraries.getPosition(libIt - Libraries.begin()); else libPos = -1; if (fileIt != Files.end()) filePos = Files.getPosition(fileIt - Files.begin()); else filePos = -1; if (filePos != -1 && (libPos == -1 || filePos < libPos)) { // Add a source file Items.push_back(std::make_pair(*fileIt++, false)); } else if (libPos != -1 && (filePos == -1 || libPos < filePos)) { // Add a library Items.push_back(std::make_pair(*libIt++, true)); } } }
/// GenerateNative - generates a native object file from the /// specified bytecode file. /// /// Inputs: /// InputFilename - The name of the input bytecode file. /// OutputFilename - The name of the file to generate. /// NativeLinkItems - The native libraries, files, code with which to link /// LibPaths - The list of directories in which to find libraries. /// gcc - The pathname to use for GGC. /// envp - A copy of the process's current environment. /// /// Outputs: /// None. /// /// Returns non-zero value on error. /// static int GenerateNative(const std::string &OutputFilename, const std::string &InputFilename, const Linker::ItemList &LinkItems, const sys::Path &gcc, char ** const envp, std::string& ErrMsg) { // Remove these environment variables from the environment of the // programs that we will execute. It appears that GCC sets these // environment variables so that the programs it uses can configure // themselves identically. // // However, when we invoke GCC below, we want it to use its normal // configuration. Hence, we must sanitize its environment. char ** clean_env = CopyEnv(envp); if (clean_env == NULL) return 1; RemoveEnv("LIBRARY_PATH", clean_env); RemoveEnv("COLLECT_GCC_OPTIONS", clean_env); RemoveEnv("GCC_EXEC_PREFIX", clean_env); RemoveEnv("COMPILER_PATH", clean_env); RemoveEnv("COLLECT_GCC", clean_env); // Run GCC to assemble and link the program into native code. // // Note: // We can't just assemble and link the file with the system assembler // and linker because we don't know where to put the _start symbol. // GCC mysteriously knows how to do it. std::vector<const char*> args; args.push_back(gcc.c_str()); args.push_back("-fno-strict-aliasing"); args.push_back("-O3"); args.push_back("-o"); args.push_back(OutputFilename.c_str()); args.push_back(InputFilename.c_str()); // Add in the library paths for (unsigned index = 0; index < LibPaths.size(); index++) { args.push_back("-L"); args.push_back(LibPaths[index].c_str()); } // Add the requested options for (unsigned index = 0; index < XLinker.size(); index++) { args.push_back(XLinker[index].c_str()); args.push_back(Libraries[index].c_str()); } // Add in the libraries to link. for (unsigned index = 0; index < LinkItems.size(); index++) if (LinkItems[index].first != "crtend") { if (LinkItems[index].second) { std::string lib_name = "-l" + LinkItems[index].first; args.push_back(lib_name.c_str()); } else args.push_back(LinkItems[index].first.c_str()); } args.push_back(0); if (Verbose) { cout << "Generating Native Executable With:\n"; PrintCommand(args); } // Run the compiler to assembly and link together the program. int R = sys::Program::ExecuteAndWait( gcc, &args[0], (const char**)clean_env, 0, 0, 0, &ErrMsg); delete [] clean_env; return R; }
/// GenerateNative - generates a native object file from the /// specified bitcode file. /// /// Inputs: /// InputFilename - The name of the input bitcode file. /// OutputFilename - The name of the file to generate. /// NativeLinkItems - The native libraries, files, code with which to link /// LibPaths - The list of directories in which to find libraries. /// FrameworksPaths - The list of directories in which to find frameworks. /// Frameworks - The list of frameworks (dynamic libraries) /// gcc - The pathname to use for GGC. /// envp - A copy of the process's current environment. /// /// Outputs: /// None. /// /// Returns non-zero value on error. /// static int GenerateNative(const std::string &OutputFilename, const std::string &InputFilename, const Linker::ItemList &LinkItems, const sys::Path &gcc, char ** const envp, std::string& ErrMsg) { // Remove these environment variables from the environment of the // programs that we will execute. It appears that GCC sets these // environment variables so that the programs it uses can configure // themselves identically. // // However, when we invoke GCC below, we want it to use its normal // configuration. Hence, we must sanitize its environment. char ** clean_env = CopyEnv(envp); if (clean_env == NULL) return 1; RemoveEnv("LIBRARY_PATH", clean_env); RemoveEnv("COLLECT_GCC_OPTIONS", clean_env); RemoveEnv("GCC_EXEC_PREFIX", clean_env); RemoveEnv("COMPILER_PATH", clean_env); RemoveEnv("COLLECT_GCC", clean_env); // Run GCC to assemble and link the program into native code. // // Note: // We can't just assemble and link the file with the system assembler // and linker because we don't know where to put the _start symbol. // GCC mysteriously knows how to do it. std::vector<std::string> args; args.push_back(gcc.c_str()); args.push_back("-fno-strict-aliasing"); args.push_back("-O3"); args.push_back("-o"); args.push_back(OutputFilename); args.push_back(InputFilename); // Add in the library and framework paths for (unsigned index = 0; index < LibPaths.size(); index++) { args.push_back("-L" + LibPaths[index]); } for (unsigned index = 0; index < FrameworkPaths.size(); index++) { args.push_back("-F" + FrameworkPaths[index]); } // Add the requested options for (unsigned index = 0; index < XLinker.size(); index++) args.push_back(XLinker[index]); // Add in the libraries to link. for (unsigned index = 0; index < LinkItems.size(); index++) if (LinkItems[index].first != "crtend") { if (LinkItems[index].second) args.push_back("-l" + LinkItems[index].first); else args.push_back(LinkItems[index].first); } // Add in frameworks to link. for (unsigned index = 0; index < Frameworks.size(); index++) { args.push_back("-framework"); args.push_back(Frameworks[index]); } // Now that "args" owns all the std::strings for the arguments, call the c_str // method to get the underlying string array. We do this game so that the // std::string array is guaranteed to outlive the const char* array. std::vector<const char *> Args; for (unsigned i = 0, e = args.size(); i != e; ++i) Args.push_back(args[i].c_str()); Args.push_back(0); if (Verbose) { errs() << "Generating Native Executable With:\n"; PrintCommand(Args); } // Run the compiler to assembly and link together the program. int R = sys::Program::ExecuteAndWait( gcc, &Args[0], const_cast<const char **>(clean_env), 0, 0, 0, &ErrMsg); delete [] clean_env; return R; }