diff options
author | Jonas Hahnfeld <hahnjo@hahnjo.de> | 2018-01-31 08:26:51 +0000 |
---|---|---|
committer | Jonas Hahnfeld <hahnjo@hahnjo.de> | 2018-01-31 08:26:51 +0000 |
commit | 7f9c5184239eb61e900ca1b34286bf90acf1fe4d (patch) | |
tree | 0537b4ed2414c38cf0c0827cc1efbe103247c732 /clang/lib/Driver/ToolChains/Cuda.cpp | |
parent | 5106d4d21c61394fa2a46fe8edf91efcbb48781d (diff) | |
download | bcm5719-llvm-7f9c5184239eb61e900ca1b34286bf90acf1fe4d.tar.gz bcm5719-llvm-7f9c5184239eb61e900ca1b34286bf90acf1fe4d.zip |
[CUDA] Detect installation in PATH
If the CUDA toolkit is not installed to its default locations
in /usr/local/cuda, the user is forced to specify --cuda-path.
This is tedious and the driver can be smarter if well-known tools
(like ptxas) can already be found in the PATH environment variable.
Add option --cuda-path-ignore-env if the user wants to ignore
set environment variables. Also use it in the tests to make sure
the driver always finds the same CUDA installation, regardless
of the user's environment.
Differential Revision: https://reviews.llvm.org/D42642
llvm-svn: 323848
Diffstat (limited to 'clang/lib/Driver/ToolChains/Cuda.cpp')
-rw-r--r-- | clang/lib/Driver/ToolChains/Cuda.cpp | 65 |
1 files changed, 50 insertions, 15 deletions
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 1646d136afe..e513e818ebf 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -8,18 +8,20 @@ //===----------------------------------------------------------------------===// #include "Cuda.h" -#include "InputInfo.h" #include "CommonArgs.h" +#include "InputInfo.h" #include "clang/Basic/Cuda.h" -#include "clang/Config/config.h" #include "clang/Basic/VirtualFileSystem.h" -#include "clang/Driver/Distro.h" +#include "clang/Config/config.h" #include "clang/Driver/Compilation.h" +#include "clang/Driver/Distro.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" #include <system_error> using namespace clang::driver; @@ -61,42 +63,75 @@ CudaInstallationDetector::CudaInstallationDetector( const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args) : D(D) { - SmallVector<std::string, 4> CudaPathCandidates; + struct Candidate { + std::string Path; + bool StrictChecking; + + Candidate(std::string Path, bool StrictChecking = false) + : Path(Path), StrictChecking(StrictChecking) {} + }; + SmallVector<Candidate, 4> Candidates; // In decreasing order so we prefer newer versions to older versions. std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"}; if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) { - CudaPathCandidates.push_back( - Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ)); + Candidates.emplace_back( + Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ).str()); } else if (HostTriple.isOSWindows()) { for (const char *Ver : Versions) - CudaPathCandidates.push_back( + Candidates.emplace_back( D.SysRoot + "/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v" + Ver); } else { - CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda"); + if (!Args.hasArg(clang::driver::options::OPT_cuda_path_ignore_env)) { + // Try to find ptxas binary. If the executable is located in a directory + // called 'bin/', its parent directory might be a good guess for a valid + // CUDA installation. + // However, some distributions might installs 'ptxas' to /usr/bin. In that + // case the candidate would be '/usr' which passes the following checks + // because '/usr/include' exists as well. To avoid this case, we always + // check for the directory potentially containing files for libdevice, + // even if the user passes -nocudalib. + if (llvm::ErrorOr<std::string> ptxas = + llvm::sys::findProgramByName("ptxas")) { + SmallString<256> ptxasAbsolutePath; + llvm::sys::fs::real_path(*ptxas, ptxasAbsolutePath); + + StringRef ptxasDir = llvm::sys::path::parent_path(ptxasAbsolutePath); + if (llvm::sys::path::filename(ptxasDir) == "bin") + Candidates.emplace_back(llvm::sys::path::parent_path(ptxasDir), + /*StrictChecking=*/true); + } + } + + Candidates.emplace_back(D.SysRoot + "/usr/local/cuda"); for (const char *Ver : Versions) - CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-" + Ver); + Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver); if (Distro(D.getVFS()).IsDebian()) // Special case for Debian to have nvidia-cuda-toolkit work // out of the box. More info on http://bugs.debian.org/882505 - CudaPathCandidates.push_back(D.SysRoot + "/usr/lib/cuda"); + Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda"); } - for (const auto &CudaPath : CudaPathCandidates) { - if (CudaPath.empty() || !D.getVFS().exists(CudaPath)) + bool NoCudaLib = Args.hasArg(options::OPT_nocudalib); + + for (const auto &Candidate : Candidates) { + InstallPath = Candidate.Path; + if (InstallPath.empty() || !D.getVFS().exists(InstallPath)) continue; - InstallPath = CudaPath; - BinPath = CudaPath + "/bin"; + BinPath = InstallPath + "/bin"; IncludePath = InstallPath + "/include"; LibDevicePath = InstallPath + "/nvvm/libdevice"; auto &FS = D.getVFS(); if (!(FS.exists(IncludePath) && FS.exists(BinPath))) continue; + bool CheckLibDevice = (!NoCudaLib || Candidate.StrictChecking); + if (CheckLibDevice && !FS.exists(LibDevicePath)) + continue; // On Linux, we have both lib and lib64 directories, and we need to choose // based on our triple. On MacOS, we have only a lib directory. @@ -180,7 +215,7 @@ CudaInstallationDetector::CudaInstallationDetector( // Check that we have found at least one libdevice that we can link in if // -nocudalib hasn't been specified. - if (LibDeviceMap.empty() && !Args.hasArg(options::OPT_nocudalib)) + if (LibDeviceMap.empty() && !NoCudaLib) continue; IsValid = true; |