Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -556,6 +556,8 @@ def no_cuda_noopt_device_debug : Flag<["--"], "no-cuda-noopt-device-debug">; def cuda_path_EQ : Joined<["--"], "cuda-path=">, Group, HelpText<"CUDA installation path">; +def cuda_path_ignore_env : Joined<["--"], "cuda-path-ignore-env">, Group, + HelpText<"Ignore environment variables to detect CUDA installation">; def ptxas_path_EQ : Joined<["--"], "ptxas-path=">, Group, HelpText<"Path to ptxas (used for compiling CUDA code)">; def fcuda_flush_denormals_to_zero : Flag<["-"], "fcuda-flush-denormals-to-zero">, Index: lib/Driver/ToolChains/Cuda.cpp =================================================================== --- lib/Driver/ToolChains/Cuda.cpp +++ lib/Driver/ToolChains/Cuda.cpp @@ -8,18 +8,19 @@ //===----------------------------------------------------------------------===// #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/Path.h" +#include "llvm/Support/Program.h" #include using namespace clang::driver; @@ -73,6 +74,19 @@ D.SysRoot + "/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v" + Ver); } else { + 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. + if (llvm::ErrorOr ptxas = + llvm::sys::findProgramByName("ptxas")) { + StringRef ptxasDir = llvm::sys::path::parent_path(*ptxas); + if (llvm::sys::path::filename(ptxasDir) == "bin") { + CudaPathCandidates.push_back(llvm::sys::path::parent_path(ptxasDir)); + } + } + } + CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda"); for (const char *Ver : Versions) CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-" + Ver); Index: test/Driver/cuda-detect-path.cu =================================================================== --- /dev/null +++ test/Driver/cuda-detect-path.cu @@ -0,0 +1,32 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: nvptx-registered-target +// This tests uses the PATH environment variable. +// REQUIRES: !system-windows + +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=i386-unknown-linux 2>&1 | FileCheck %s +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=i386-apple-macosx 2>&1 | FileCheck %s +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=x86_64-unknown-linux 2>&1 | FileCheck %s +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=x86_64-apple-macosx 2>&1 | FileCheck %s + +// Check that the CUDA installation in PATH is not taken when passing +// the option --cuda-path-ignore-env +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=i386-unknown-linux --cuda-path-ignore-env \ +// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=i386-apple-macosx --cuda-path-ignore-env \ +// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=x86_64-unknown-linux --cuda-path-ignore-env \ +// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA +// RUN: env PATH=%S/Inputs/CUDA/usr/local/cuda/bin \ +// RUN: %clang -v --target=x86_64-apple-macosx --cuda-path-ignore-env \ +// RUN: 2>&1 | FileCheck %s --check-prefix NOCUDA + +// CHECK: Found CUDA installation: {{.*}}/Inputs/CUDA/usr/local/cuda +// NOCUDA-NOT: Found CUDA installation: Index: test/Driver/cuda-detect.cu =================================================================== --- test/Driver/cuda-detect.cu +++ test/Driver/cuda-detect.cu @@ -4,9 +4,14 @@ // // Check that we properly detect CUDA installation. // RUN: %clang -v --target=i386-unknown-linux \ -// RUN: --sysroot=%S/no-cuda-there 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA // RUN: %clang -v --target=i386-apple-macosx \ -// RUN: --sysroot=%S/no-cuda-there 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: %clang -v --target=x86_64-unknown-linux \ +// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: %clang -v --target=x86_64-apple-macosx \ +// RUN: --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA + // RUN: %clang -v --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/CUDA 2>&1 | FileCheck %s @@ -20,15 +25,23 @@ // Check that we don't find a CUDA installation without libdevice ... // RUN: %clang -v --target=i386-unknown-linux \ -// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA // RUN: %clang -v --target=i386-apple-macosx \ -// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: %clang -v --target=x86_64-unknown-linux \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA +// RUN: %clang -v --target=x84_64-apple-macosx \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA // ... unless the user doesn't need libdevice // RUN: %clang -v --target=i386-unknown-linux -nocudalib \ -// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE // RUN: %clang -v --target=i386-apple-macosx -nocudalib \ -// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE +// RUN: %clang -v --target=x86_64-unknown-linux -nocudalib \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE +// RUN: %clang -v --target=x86_64-apple-macosx -nocudalib \ +// RUN: --sysroot=%S/Inputs/CUDA-nolibdevice --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NO-LIBDEVICE // Make sure we map libdevice bitcode files to proper GPUs. These Index: test/Driver/cuda-not-found.cu =================================================================== --- test/Driver/cuda-not-found.cu +++ test/Driver/cuda-not-found.cu @@ -3,10 +3,10 @@ // Check that we raise an error if we're trying to compile CUDA code but can't // find a CUDA install, unless -nocudainc was passed. -// RUN: %clang -### --sysroot=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix ERR +// RUN: %clang -### --sysroot=%s/no-cuda-there --cuda-path-ignore-env %s 2>&1 | FileCheck %s --check-prefix ERR // RUN: %clang -### --cuda-path=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix ERR // ERR: cannot find CUDA installation -// RUN: %clang -### -nocudainc --sysroot=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix OK +// RUN: %clang -### -nocudainc --sysroot=%s/no-cuda-there --cuda-path-ignore-env %s 2>&1 | FileCheck %s --check-prefix OK // RUN: %clang -### -nocudainc --cuda-path=%s/no-cuda-there %s 2>&1 | FileCheck %s --check-prefix OK // OK-NOT: cannot find CUDA installation Index: test/Driver/cuda-version-check.cu =================================================================== --- test/Driver/cuda-version-check.cu +++ test/Driver/cuda-version-check.cu @@ -2,40 +2,40 @@ // REQUIRES: x86-registered-target // REQUIRES: nvptx-registered-target -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --sysroot=%S/Inputs/CUDA 2>&1 %s | \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=OK -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --sysroot=%S/Inputs/CUDA_80 2>&1 %s | \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_20 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=OK -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA_80 2>&1 %s | \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=OK // The installation at Inputs/CUDA is CUDA 7.0, which doesn't support sm_60. -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA 2>&1 %s | \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=ERR_SM60 // This should only complain about sm_60, not sm_35. // RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_35 \ -// RUN: --sysroot=%S/Inputs/CUDA 2>&1 %s | \ +// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=ERR_SM60 --check-prefix=OK_SM35 // We should get two errors here, one for sm_60 and one for sm_61. // RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_61 \ -// RUN: --sysroot=%S/Inputs/CUDA 2>&1 %s | \ +// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=ERR_SM60 --check-prefix=ERR_SM61 // We should still get an error if we pass -nocudainc, because this compilation // would invoke ptxas, and we do a version check on that, too. -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 -nocudainc --sysroot=%S/Inputs/CUDA 2>&1 %s | \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 -nocudainc --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=ERR_SM60 // If with -nocudainc and -E, we don't touch the CUDA install, so we // shouldn't get an error. // RUN: %clang --target=x86_64-linux -v -### -E --cuda-device-only --cuda-gpu-arch=sm_60 -nocudainc \ -// RUN: --sysroot=%S/Inputs/CUDA 2>&1 %s | \ +// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=OK // --no-cuda-version-check should suppress all of these errors. -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --sysroot=%S/Inputs/CUDA 2>&1 \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 \ // RUN: --no-cuda-version-check %s | \ // RUN: FileCheck %s --check-prefix=OK @@ -43,9 +43,9 @@ // therefore we should not get an error in host-only mode. We use the -S here // to avoid the error being produced in case by the assembler tool, which does // the same check. -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-host-only --sysroot=%S/Inputs/CUDA -S 2>&1 %s | \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-host-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda -S 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=OK -// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-device-only --sysroot=%S/Inputs/CUDA -S 2>&1 %s | \ +// RUN: %clang --target=x86_64-linux -v -### --cuda-gpu-arch=sm_60 --cuda-device-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda -S 2>&1 %s | \ // RUN: FileCheck %s --check-prefix=ERR_SM60 // OK-NOT: error: GPU arch