Index: include/clang/Driver/ToolChain.h =================================================================== --- include/clang/Driver/ToolChain.h +++ include/clang/Driver/ToolChain.h @@ -402,6 +402,10 @@ virtual void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; + /// \brief Add LD arguments pointing to CUDA libraries. + virtual void AddCudaLinkerArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &LDArgs) const; + /// \brief Return sanitizers which are available in this toolchain. virtual SanitizerMask getSupportedSanitizers() const; }; Index: lib/Driver/ToolChain.cpp =================================================================== --- lib/Driver/ToolChain.cpp +++ lib/Driver/ToolChain.cpp @@ -665,4 +665,11 @@ } void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const {} + ArgStringList &CC1Args) const { + // Only supported on Linux at the moment. +} + +void ToolChain::AddCudaLinkerArgs(const ArgList &DriverArgs, + ArgStringList &LDArgs) const { + // Only supported on Linux at the moment. +} Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -790,6 +790,8 @@ llvm::opt::ArgStringList &CC1Args) const override; void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + void AddCudaLinkerArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; bool isPIEDefault() const override; SanitizerMask getSupportedSanitizers() const override; void addProfileRTLibs(const llvm::opt::ArgList &Args, Index: lib/Driver/ToolChains.cpp =================================================================== --- lib/Driver/ToolChains.cpp +++ lib/Driver/ToolChains.cpp @@ -4120,6 +4120,15 @@ } } +void Linux::AddCudaLinkerArgs(const ArgList &DriverArgs, + ArgStringList &LDArgs) const { + if (DriverArgs.hasArg(options::OPT_nocudalib) || !CudaInstallation.isValid()) + return; + + LDArgs.push_back("-L"); + LDArgs.push_back(DriverArgs.MakeArgString(CudaInstallation.getLibPath())); +} + bool Linux::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); } SanitizerMask Linux::getSupportedSanitizers() const { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -206,8 +206,16 @@ } } -static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, - const ArgList &Args, ArgStringList &CmdArgs) { +// Is the given action, or any of its inputs, a CUDA action? +static bool isCudaAction(const Action* A) { + return CudaDeviceAction::classof(A) || CudaHostAction::classof(A) || + std::any_of(A->getInputs().begin(), A->getInputs().end(), + isCudaAction); +} + +static void AddLinkerInputs(const Compilation &C, const ToolChain &TC, + const InputInfoList &Inputs, const ArgList &Args, + ArgStringList &CmdArgs) { const Driver &D = TC.getDriver(); // Add extra linker input arguments which are not treated as inputs @@ -246,6 +254,11 @@ // and only supported on native toolchains. if (!TC.isCrossCompiling()) addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); + + // Add -L/path/to/cuda/lib if any of our inputs are .cu files. + if (std::any_of(C.getActions().begin(), C.getActions().end(), isCudaAction)) { + TC.AddCudaLinkerArgs(Args, CmdArgs); + } } /// \brief Determine whether Objective-C automated reference counting is @@ -6368,7 +6381,7 @@ {options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_u_Group}); - AddLinkerInputs(HTC, Inputs, Args, CmdArgs); + AddLinkerInputs(C, HTC, Inputs, Args, CmdArgs); //---------------------------------------------------------------------------- // Libraries @@ -6431,7 +6444,7 @@ CmdArgs.push_back("old-gnu"); CmdArgs.push_back("-target"); CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString())); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique(JA, *this, Args.MakeArgString(Linker), @@ -6461,7 +6474,7 @@ CmdArgs.push_back("ld"); CmdArgs.push_back("-target"); CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString())); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique(JA, *this, Linker, CmdArgs, Inputs)); @@ -6764,7 +6777,7 @@ if (D.isUsingLTO()) AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin); - AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) @@ -7134,7 +7147,7 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); // Build the input file for -filelist (list of linker input files) in case we // need it later for (const auto &II : Inputs) { @@ -7352,7 +7365,7 @@ Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e, options::OPT_r}); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (getToolChain().getDriver().CCCIsCXX()) @@ -7525,7 +7538,7 @@ options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { @@ -7644,7 +7657,7 @@ Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e}); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { @@ -7893,7 +7906,7 @@ AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); - AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { addOpenMPRuntime(CmdArgs, ToolChain, Args); @@ -8189,7 +8202,7 @@ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); unsigned Major, Minor, Micro; getToolChain().getTriple().getOSVersion(Major, Minor, Micro); @@ -8776,7 +8789,7 @@ CmdArgs.push_back("--no-demangle"); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); - AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs); // The profile runtime also needs access to system libraries. getToolChain().addProfileRTLibs(Args, CmdArgs); @@ -8970,7 +8983,7 @@ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); - AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs); if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { @@ -9082,7 +9095,7 @@ Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e}); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); getToolChain().addProfileRTLibs(Args, CmdArgs); @@ -9203,7 +9216,7 @@ Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e}); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of @@ -9724,7 +9737,7 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); TC.AddFilePathLibArgs(Args, CmdArgs); - AddLinkerInputs(TC, Inputs, Args, CmdArgs); + AddLinkerInputs(C, TC, Inputs, Args, CmdArgs); // TODO: Add ASan stuff here @@ -9848,7 +9861,7 @@ false)) CmdArgs.push_back("-fexceptions"); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); @@ -10002,7 +10015,7 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); TC.AddFilePathLibArgs(Args, CmdArgs); - AddLinkerInputs(TC, Inputs, Args, CmdArgs); + AddLinkerInputs(C, TC, Inputs, Args, CmdArgs); if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { @@ -10180,7 +10193,7 @@ TC.AddFilePathLibArgs(Args, CmdArgs); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + AddLinkerInputs(C, getToolChain(), Inputs, Args, CmdArgs); if (UseDefaultLibs) { if (C.getDriver().CCCIsCXX()) @@ -10289,7 +10302,7 @@ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); - AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs); if (Args.hasArg(options::OPT_pthread)) { CmdArgs.push_back("-lpthread"); @@ -10385,7 +10398,7 @@ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); - AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + AddLinkerInputs(C, ToolChain, Inputs, Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { // For PS4, we always want to pass libm, libstdc++ and libkernel