ToolChain::InvocationInfo ToolChain::constructInvocation(const REPLJobAction &job, const JobContext &context) const { assert(context.Inputs.empty()); assert(context.InputActions.empty()); bool useLLDB; switch (job.getRequestedMode()) { case REPLJobAction::Mode::Integrated: useLLDB = false; break; case REPLJobAction::Mode::RequireLLDB: useLLDB = true; break; case REPLJobAction::Mode::PreferLLDB: useLLDB = !findProgramRelativeToSwift("lldb").empty(); break; } ArgStringList FrontendArgs; addCommonFrontendArgs(*this, context.OI, context.Output, context.Args, FrontendArgs); context.Args.AddAllArgs(FrontendArgs, options::OPT_l, options::OPT_framework, options::OPT_L); if (!useLLDB) { FrontendArgs.insert(FrontendArgs.begin(), {"-frontend", "-repl"}); FrontendArgs.push_back("-module-name"); FrontendArgs.push_back(context.Args.MakeArgString(context.OI.ModuleName)); return {SWIFT_EXECUTABLE_NAME, FrontendArgs}; } // Squash important frontend options into a single argument for LLDB. std::string SingleArg = "--repl="; { llvm::raw_string_ostream os(SingleArg); Job::printArguments(os, FrontendArgs); } ArgStringList Arguments; Arguments.push_back(context.Args.MakeArgString(std::move(SingleArg))); return {"lldb", Arguments}; }
ToolChain::InvocationInfo toolchains::Darwin::constructInvocation(const LinkJobAction &job, const JobContext &context) const { assert(context.Output.getPrimaryOutputType() == types::TY_Image && "Invalid linker output type."); const Driver &D = getDriver(); const llvm::Triple &Triple = getTriple(); ArgStringList Arguments; addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object); addInputsOfType(Arguments, context.InputActions, types::TY_Object); if (context.OI.DebugInfoKind == IRGenDebugInfoKind::Normal) { size_t argCount = Arguments.size(); if (context.OI.CompilerMode == OutputInfo::Mode::SingleCompile) addInputsOfType(Arguments, context.Inputs, types::TY_SwiftModuleFile); else addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_SwiftModuleFile); if (Arguments.size() > argCount) { assert(argCount + 1 == Arguments.size() && "multiple swiftmodules found for -g"); Arguments.insert(Arguments.end() - 1, "-add_ast_path"); } } switch (job.getKind()) { case LinkKind::None: llvm_unreachable("invalid link kind"); case LinkKind::Executable: // The default for ld; no extra flags necessary. break; case LinkKind::DynamicLibrary: Arguments.push_back("-dylib"); break; } assert(Triple.isOSDarwin()); // FIXME: If we used Clang as a linker instead of going straight to ld, // we wouldn't have to replicate Clang's logic here. bool wantsObjCRuntime = false; if (Triple.isiOS()) wantsObjCRuntime = Triple.isOSVersionLT(8); else if (Triple.isWatchOS()) wantsObjCRuntime = Triple.isOSVersionLT(2); else if (Triple.isMacOSX()) wantsObjCRuntime = Triple.isMacOSXVersionLT(10, 10); if (context.Args.hasFlag(options::OPT_link_objc_runtime, options::OPT_no_link_objc_runtime, /*default=*/wantsObjCRuntime)) { llvm::SmallString<128> ARCLiteLib(D.getSwiftProgramPath()); llvm::sys::path::remove_filename(ARCLiteLib); // 'swift' llvm::sys::path::remove_filename(ARCLiteLib); // 'bin' llvm::sys::path::append(ARCLiteLib, "lib", "arc"); if (!llvm::sys::fs::is_directory(ARCLiteLib)) { // If we don't have a 'lib/arc/' directory, find the "arclite" library // relative to the Clang in the active Xcode. ARCLiteLib.clear(); if (findXcodeClangPath(ARCLiteLib)) { llvm::sys::path::remove_filename(ARCLiteLib); // 'clang' llvm::sys::path::remove_filename(ARCLiteLib); // 'bin' llvm::sys::path::append(ARCLiteLib, "lib", "arc"); } } if (!ARCLiteLib.empty()) { llvm::sys::path::append(ARCLiteLib, "libarclite_"); ARCLiteLib += getPlatformNameForTriple(Triple); ARCLiteLib += ".a"; Arguments.push_back("-force_load"); Arguments.push_back(context.Args.MakeArgString(ARCLiteLib)); // Arclite depends on CoreFoundation. Arguments.push_back("-framework"); Arguments.push_back("CoreFoundation"); } else { // FIXME: We should probably diagnose this, but this is not a place where // we can emit diagnostics. Silently ignore it for now. } } context.Args.AddAllArgValues(Arguments, options::OPT_Xlinker); context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); context.Args.AddAllArgs(Arguments, options::OPT_F); if (context.Args.hasArg(options::OPT_enable_app_extension)) { // Keep this string fixed in case the option used by the // compiler itself changes. Arguments.push_back("-application_extension"); } if (context.Args.hasArg(options::OPT_embed_bitcode, options::OPT_embed_bitcode_marker)) { Arguments.push_back("-bitcode_bundle"); } if (!context.OI.SDKPath.empty()) { Arguments.push_back("-syslibroot"); Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath)); } Arguments.push_back("-lobjc"); Arguments.push_back("-lSystem"); Arguments.push_back("-arch"); Arguments.push_back(context.Args.MakeArgString(getTriple().getArchName())); // Add the runtime library link path, which is platform-specific and found // relative to the compiler. SmallString<128> RuntimeLibPath; getRuntimeLibraryPath(RuntimeLibPath, context.Args, *this); Arguments.push_back("-L"); Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); if (context.Args.hasArg(options::OPT_profile_generate)) { SmallString<128> LibProfile(RuntimeLibPath); llvm::sys::path::remove_filename(LibProfile); // remove platform name llvm::sys::path::append(LibProfile, "clang", CLANG_VERSION_STRING); StringRef RT; if (Triple.isiOS()) { if (Triple.isTvOS()) RT = "tvos"; else RT = "ios"; } else if (Triple.isWatchOS()) RT = "watchos"; else RT = "osx"; llvm::sys::path::append(LibProfile, "lib", "darwin", "libclang_rt.profile_" + RT + ".a"); Arguments.push_back(context.Args.MakeArgString(LibProfile)); } // FIXME: We probably shouldn't be adding an rpath here unless we know ahead // of time the standard library won't be copied. Arguments.push_back("-rpath"); Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); // FIXME: Properly handle deployment targets. assert(Triple.isiOS() || Triple.isWatchOS() || Triple.isMacOSX()); if (Triple.isiOS()) { bool isiOSSimulator = tripleIsiOSSimulator(Triple); if (Triple.isTvOS()) { if (isiOSSimulator) Arguments.push_back("-tvos_simulator_version_min"); else Arguments.push_back("-tvos_version_min"); } else { if (isiOSSimulator) Arguments.push_back("-ios_simulator_version_min"); else Arguments.push_back("-iphoneos_version_min"); } unsigned major, minor, micro; Triple.getiOSVersion(major, minor, micro); addVersionString(context.Args, Arguments, major, minor, micro); } else if (Triple.isWatchOS()) { if (tripleIsWatchSimulator(Triple)) Arguments.push_back("-watchos_simulator_version_min"); else Arguments.push_back("-watchos_version_min"); unsigned major, minor, micro; Triple.getOSVersion(major, minor, micro); addVersionString(context.Args, Arguments, major, minor, micro); } else { Arguments.push_back("-macosx_version_min"); unsigned major, minor, micro; Triple.getMacOSXVersion(major, minor, micro); addVersionString(context.Args, Arguments, major, minor, micro); } Arguments.push_back("-no_objc_category_merging"); // This should be the last option, for convenience in checking output. Arguments.push_back("-o"); Arguments.push_back(context.Output.getPrimaryOutputFilename().c_str()); return {"ld", Arguments}; }