int linkObjToBinaryMSVC(llvm::StringRef outputPath, bool useInternalLinker, llvm::cl::boolOrDefault fullyStaticFlag) { if (!opts::ccSwitches.empty()) { error(Loc(), "-Xcc is not supported for MSVC"); fatal(); } #ifdef _WIN32 windows::setupMsvcEnvironment(); #endif // build arguments std::vector<std::string> args; args.push_back("/NOLOGO"); // specify that the image will contain a table of safe exception handlers // and can handle addresses >2GB (32bit only) if (!global.params.is64bit) { args.push_back("/SAFESEH"); args.push_back("/LARGEADDRESSAWARE"); } // output debug information if (global.params.symdebug) { args.push_back("/DEBUG"); } // remove dead code and fold identical COMDATs if (opts::disableLinkerStripDead) { args.push_back("/OPT:NOREF"); } else { args.push_back("/OPT:REF"); args.push_back("/OPT:ICF"); } // add C runtime libs addMscrtLibs(args, fullyStaticFlag); // specify creation of DLL if (global.params.dll) { args.push_back("/DLL"); } args.push_back(("/OUT:" + outputPath).str()); // object files for (auto objfile : global.params.objfiles) { args.push_back(objfile); } // .res/.def files if (global.params.resfile) args.push_back(global.params.resfile); if (global.params.deffile) args.push_back(std::string("/DEF:") + global.params.deffile); if (opts::enableDynamicCompile) { args.push_back("ldc-jit-rt.lib"); args.push_back("ldc-jit.lib"); } // user libs for (auto libfile : global.params.libfiles) { args.push_back(libfile); } // LLVM compiler-rt libs addLibIfFound(args, "ldc_rt.builtins.lib"); addSanitizerLibs(args); if (opts::isInstrumentingForPGO()) { args.push_back("ldc_rt.profile.lib"); // it depends on ws2_32 for symbol `gethostname` args.push_back("ws2_32.lib"); } // additional linker switches auto addSwitch = [&](std::string str) { if (str.length() > 2) { // rewrite common -L and -l switches if (str[0] == '-' && str[1] == 'L') { str = "/LIBPATH:" + str.substr(2); } else if (str[0] == '-' && str[1] == 'l') { str = str.substr(2) + ".lib"; } } args.push_back(str); }; for (const auto &str : opts::linkerSwitches) { addSwitch(str); } for (auto ls : global.params.linkswitches) { addSwitch(ls); } // default libs // TODO check which libaries are necessary args.push_back("kernel32.lib"); args.push_back("user32.lib"); args.push_back("gdi32.lib"); args.push_back("winspool.lib"); args.push_back("shell32.lib"); // required for dmain2.d args.push_back("ole32.lib"); args.push_back("oleaut32.lib"); args.push_back("uuid.lib"); args.push_back("comdlg32.lib"); args.push_back("advapi32.lib"); Logger::println("Linking with: "); Stream logstr = Logger::cout(); for (const auto &arg : args) { if (!arg.empty()) { logstr << "'" << arg << "' "; } } logstr << "\n"; // FIXME where's flush ? #if LDC_WITH_LLD if (useInternalLinker) { const auto fullArgs = getFullArgs("lld-link.exe", args, global.params.verbose); const bool success = lld::coff::link(fullArgs); if (!success) error(Loc(), "linking with LLD failed"); return success ? 0 : 1; } #endif // try to call linker std::string linker = opts::linker; if (linker.empty()) linker = "link.exe"; return executeToolAndWait(linker, args, global.params.verbose); }
static int linkObjToBinaryMSVC(bool sharedLib) { Logger::println("*** Linking executable ***"); if (!opts::ccSwitches.empty()) { error(Loc(), "-Xcc is not supported for MSVC"); fatal(); } #ifdef _WIN32 windows::setupMsvcEnvironment(); #endif const std::string tool = "link.exe"; // build arguments std::vector<std::string> args; args.push_back("/NOLOGO"); // specify that the image will contain a table of safe exception handlers // and can handle addresses >2GB (32bit only) if (!global.params.is64bit) { args.push_back("/SAFESEH"); args.push_back("/LARGEADDRESSAWARE"); } // output debug information if (global.params.symdebug) { args.push_back("/DEBUG"); } // remove dead code and fold identical COMDATs if (opts::disableLinkerStripDead) { args.push_back("/OPT:NOREF"); } else { args.push_back("/OPT:REF"); args.push_back("/OPT:ICF"); } // add C runtime libs addMscrtLibs(args); // specify creation of DLL if (sharedLib) { args.push_back("/DLL"); } // output filename std::string output = getOutputName(sharedLib); args.push_back("/OUT:" + output); appendObjectFiles(args); // Link with profile-rt library when generating an instrumented binary // profile-rt depends on Phobos (MD5 hashing). if (global.params.genInstrProf) { args.push_back("ldc-profile-rt.lib"); // profile-rt depends on ws2_32 for symbol `gethostname` args.push_back("ws2_32.lib"); } // user libs for (unsigned i = 0; i < global.params.libfiles->dim; i++) args.push_back((*global.params.libfiles)[i]); // set the global gExePath gExePath = output; // assert(gExePath.isValid()); // create path to exe CreateDirectoryOnDisk(gExePath); // additional linker switches auto addSwitch = [&](std::string str) { if (str.length() > 2) { // rewrite common -L and -l switches if (str[0] == '-' && str[1] == 'L') { str = "/LIBPATH:" + str.substr(2); } else if (str[0] == '-' && str[1] == 'l') { str = str.substr(2) + ".lib"; } } args.push_back(str); }; for (const auto& str : opts::linkerSwitches) { addSwitch(str); } for (unsigned i = 0; i < global.params.linkswitches->dim; i++) { addSwitch(global.params.linkswitches->data[i]); } // default libs // TODO check which libaries are necessary args.push_back("kernel32.lib"); args.push_back("user32.lib"); args.push_back("gdi32.lib"); args.push_back("winspool.lib"); args.push_back("shell32.lib"); // required for dmain2.d args.push_back("ole32.lib"); args.push_back("oleaut32.lib"); args.push_back("uuid.lib"); args.push_back("comdlg32.lib"); args.push_back("advapi32.lib"); Logger::println("Linking with: "); Stream logstr = Logger::cout(); for (const auto &arg : args) { if (!arg.empty()) { logstr << "'" << arg << "'" << " "; } } logstr << "\n"; // FIXME where's flush ? // try to call linker return executeToolAndWait(tool, args, global.params.verbose); }