From f8aac21947f43a0e886a3cc3655514abb95bb260 Mon Sep 17 00:00:00 2001
From: Robert Maynard <robert.maynard@kitware.com>
Date: Fri, 26 Aug 2016 16:59:36 -0400
Subject: CUDA: Add basic CUDA language support for *NIX systems.

---
 Modules/CMakeCUDACompiler.cmake.in              |   7 ++
 Modules/CMakeCUDACompilerId.cu.in               |  40 +++++++++
 Modules/CMakeCUDAInformation.cmake              | 109 ++++++++++++++++++++++++
 Modules/CMakeDetermineCUDACompiler.cmake        |  49 +++++++++++
 Modules/CMakeTestCUDACompiler.cmake             |  58 +++++++++++++
 Modules/Compiler/NVIDIA-CUDA.cmake              |  16 ++++
 Modules/Compiler/NVIDIA-DetermineCompiler.cmake |   7 ++
 7 files changed, 286 insertions(+)
 create mode 100644 Modules/CMakeCUDACompiler.cmake.in
 create mode 100644 Modules/CMakeCUDACompilerId.cu.in
 create mode 100644 Modules/CMakeCUDAInformation.cmake
 create mode 100644 Modules/CMakeDetermineCUDACompiler.cmake
 create mode 100644 Modules/CMakeTestCUDACompiler.cmake
 create mode 100644 Modules/Compiler/NVIDIA-CUDA.cmake
 create mode 100644 Modules/Compiler/NVIDIA-DetermineCompiler.cmake

diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in
new file mode 100644
index 0000000..1e34825
--- /dev/null
+++ b/Modules/CMakeCUDACompiler.cmake.in
@@ -0,0 +1,7 @@
+set(CMAKE_CUDA_COMPILER "@CMAKE_CUDA_COMPILER@")
+set(CMAKE_CUDA_COMPILER_ID "@CMAKE_CUDA_COMPILER_ID@")
+
+set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
+
+set(CMAKE_CUDA_COMPILER_ID_RUN 1)
+set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu)
diff --git a/Modules/CMakeCUDACompilerId.cu.in b/Modules/CMakeCUDACompilerId.cu.in
new file mode 100644
index 0000000..ddbc8b4
--- /dev/null
+++ b/Modules/CMakeCUDACompilerId.cu.in
@@ -0,0 +1,40 @@
+
+#ifndef __cplusplus
+# error "A C compiler has been selected for CUDA/C++."
+#endif
+
+@CMAKE_CUDA_COMPILER_ID_CONTENT@
+
+/* Construct the string literal in pieces to prevent the source from
+   getting matched.  Store it in a pointer rather than an array
+   because some compilers will just produce instructions to fill the
+   array rather than assigning a pointer to a static array.  */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+
+@CMAKE_CUDA_COMPILER_ID_PLATFORM_CONTENT@
+@CMAKE_CUDA_COMPILER_ID_ERROR_FOR_TEST@
+
+const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+#if __cplusplus >= 201402L
+  "14"
+#elif __cplusplus >= 201103L
+  "11"
+#else
+  "98"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+  int require = 0;
+  require += info_compiler[argc];
+  require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+  require += info_version[argc];
+#endif
+  require += info_language_dialect_default[argc];
+  (void)argv;
+  return require;
+}
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
new file mode 100644
index 0000000..3436681
--- /dev/null
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -0,0 +1,109 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+set(CMAKE_CUDA_OUTPUT_EXTENSION .o)
+set(CMAKE_INCLUDE_FLAG_CUDA "-I")
+
+# Load compiler-specific information.
+if(CMAKE_CUDA_COMPILER_ID)
+  include(Compiler/${CMAKE_CUDA_COMPILER_ID}-CUDA OPTIONAL)
+else()
+  #couldn't id the cuda compile, fall back to the default setting
+  set(CMAKE_CUDA_COMPILER_ID "NVidia")
+  include(Compiler/NVidia-CUDA OPTIONAL)
+endif()
+
+# load the system- and compiler specific files
+if(CMAKE_CUDA_COMPILER_ID)
+  # load a hardware specific file, mostly useful for embedded compilers
+  if(CMAKE_SYSTEM_PROCESSOR)
+    include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CUDA_COMPILER_ID}-CUDA-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+  endif()
+  include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CUDA_COMPILER_ID}-CUDA OPTIONAL)
+endif()
+
+# for most systems a module is the same as a shared library
+# so unless the variable CMAKE_MODULE_EXISTS is set just
+# copy the values from the LIBRARY variables
+if(NOT CMAKE_MODULE_EXISTS)
+  set(CMAKE_SHARED_MODULE_CUDA_FLAGS ${CMAKE_SHARED_LIBRARY_CUDA_FLAGS})
+  set(CMAKE_SHARED_MODULE_CREATE_CUDA_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS})
+endif()
+
+# add the flags to the cache based
+# on the initial values computed in the platform/*.cmake files
+# use _INIT variables so that this only happens the first time
+# and you can set these flags in the cmake cache
+set(CMAKE_CUDA_FLAGS_INIT "$ENV{CUDAFLAGS} ${CMAKE_CUDA_FLAGS_INIT}")
+
+foreach(c "" _DEBUG _RELEASE _MINSIZEREL _RELWITHDEBINFO)
+  string(STRIP "${CMAKE_CUDA_FLAGS${c}_INIT}" CMAKE_CUDA_FLAGS${c}_INIT)
+endforeach()
+
+set (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS_INIT}" CACHE STRING
+     "Flags used by the compiler during all build types.")
+
+if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
+  set (CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG_INIT}" CACHE STRING
+     "Flags used by the compiler during debug builds.")
+  set (CMAKE_CUDA_FLAGS_MINSIZEREL "${CMAKE_CUDA_FLAGS_MINSIZEREL_INIT}" CACHE STRING
+     "Flags used by the compiler during release builds for minimum size.")
+  set (CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE_INIT}" CACHE STRING
+     "Flags used by the compiler during release builds.")
+  set (CMAKE_CUDA_FLAGS_RELWITHDEBINFO "${CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING
+     "Flags used by the compiler during release builds with debug info.")
+
+endif()
+
+include(CMakeCommonLanguageInclude)
+
+# now define the following rules:
+# CMAKE_CUDA_CREATE_SHARED_LIBRARY
+# CMAKE_CUDA_CREATE_SHARED_MODULE
+# CMAKE_CUDA_COMPILE_OBJECT
+# CMAKE_CUDA_LINK_EXECUTABLE
+
+# create a shared library
+if(NOT CMAKE_CUDA_CREATE_SHARED_LIBRARY)
+  set(CMAKE_CUDA_CREATE_SHARED_LIBRARY
+      "<CMAKE_CUDA_COMPILER> <CMAKE_SHARED_LIBRARY_CUDA_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+endif()
+
+# create a shared module copy the shared library rule by default
+if(NOT CMAKE_CUDA_CREATE_SHARED_MODULE)
+  set(CMAKE_CUDA_CREATE_SHARED_MODULE ${CMAKE_CUDA_CREATE_SHARED_LIBRARY})
+endif()
+
+# Create a static archive incrementally for large object file counts.
+if(NOT DEFINED CMAKE_CUDA_ARCHIVE_CREATE)
+  set(CMAKE_CUDA_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_CUDA_ARCHIVE_APPEND)
+  set(CMAKE_CUDA_ARCHIVE_APPEND "<CMAKE_AR> q  <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_CUDA_ARCHIVE_FINISH)
+  set(CMAKE_CUDA_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+endif()
+
+
+# compile a cu file into an object file
+if(NOT CMAKE_CUDA_COMPILE_OBJECT)
+  set(CMAKE_CUDA_COMPILE_OBJECT
+    "<CMAKE_CUDA_COMPILER>  <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
+endif()
+
+# compile a cu file into an executable
+if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
+  set(CMAKE_CUDA_LINK_EXECUTABLE
+    "<CMAKE_CUDA_COMPILER>  <FLAGS> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")
+endif()
+
+
+mark_as_advanced(
+CMAKE_CUDA_FLAGS
+CMAKE_CUDA_FLAGS_RELEASE
+CMAKE_CUDA_FLAGS_RELWITHDEBINFO
+CMAKE_CUDA_FLAGS_MINSIZEREL
+CMAKE_CUDA_FLAGS_DEBUG)
+
+set(CMAKE_CUDA_INFORMATION_LOADED 1)
diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake
new file mode 100644
index 0000000..fd87358
--- /dev/null
+++ b/Modules/CMakeDetermineCUDACompiler.cmake
@@ -0,0 +1,49 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
+
+if( NOT ( ("${CMAKE_GENERATOR}" MATCHES "Make") OR
+          ("${CMAKE_GENERATOR}" MATCHES "Ninja") ) )
+  message(FATAL_ERROR "CUDA language not currently supported by \"${CMAKE_GENERATOR}\" generator")
+endif()
+
+if(NOT CMAKE_CUDA_COMPILER)
+  set(CMAKE_CUDA_COMPILER_INIT NOTFOUND)
+
+  # finally list compilers to try
+  if(NOT CMAKE_CUDA_COMPILER_INIT)
+    set(CMAKE_CUDA_COMPILER_LIST nvcc)
+  endif()
+
+  _cmake_find_compiler(CUDA)
+else()
+  _cmake_find_compiler_path(CUDA)
+endif()
+
+mark_as_advanced(CMAKE_CUDA_COMPILER)
+
+# Build a small source file to identify the compiler.
+if(NOT CMAKE_CUDA_COMPILER_ID_RUN)
+  set(CMAKE_CUDA_COMPILER_ID_RUN 1)
+
+  list(APPEND CMAKE_CUDA_COMPILER_ID_MATCH_VENDORS NVidia)
+  set(CMAKE_CUDA_COMPILER_ID_MATCH_VENDOR_REGEX_NVidia "nvcc: NVIDIA \(R\) Cuda compiler driver")
+
+  set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdCXX/(\\./)?(CompilerIdCXX.xctest/)?CompilerIdCXX[ \t\n\\\"]")
+  set(CMAKE_CXX_COMPILER_ID_TOOL_MATCH_INDEX 2)
+
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
+  CMAKE_DETERMINE_COMPILER_ID(CUDA CUDAFLAGS CMakeCUDACompilerId.cu)
+
+endif()
+
+include(CMakeFindBinUtils)
+
+# configure all variables set in this file
+configure_file(${CMAKE_ROOT}/Modules/CMakeCUDACompiler.cmake.in
+  ${CMAKE_PLATFORM_INFO_DIR}/CMakeCUDACompiler.cmake
+  @ONLY
+  )
+
+set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake
new file mode 100644
index 0000000..e45d2ab
--- /dev/null
+++ b/Modules/CMakeTestCUDACompiler.cmake
@@ -0,0 +1,58 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+if(CMAKE_CUDA_COMPILER_FORCED)
+  # The compiler configuration was forced by the user.
+  # Assume the user has configured all compiler information.
+  set(CMAKE_CUDA_COMPILER_WORKS TRUE)
+  return()
+endif()
+
+include(CMakeTestCompilerCommon)
+
+# Remove any cached result from an older CMake version.
+# We now store this in CMakeCUDACompiler.cmake.
+unset(CMAKE_CUDA_COMPILER_WORKS CACHE)
+
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that that selected cuda compiler can actually compile
+# and link the most basic of programs.   If not, a fatal error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+if(NOT CMAKE_CUDA_COMPILER_WORKS)
+  PrintTestCompilerStatus("CUDA" "")
+  file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu
+    "#ifndef __CUDACC__\n"
+    "# error \"The CMAKE_CUDA_COMPILER is set to an invalid CUDA compiler\"\n"
+    "#endif\n"
+    "int main(){return 0;}\n")
+
+  try_compile(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_BINARY_DIR}
+    ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu
+    OUTPUT_VARIABLE __CMAKE_CUDA_COMPILER_OUTPUT)
+
+  # Move result from cache to normal variable.
+  set(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_CUDA_COMPILER_WORKS})
+  unset(CMAKE_CUDA_COMPILER_WORKS CACHE)
+  set(CUDA_TEST_WAS_RUN 1)
+endif()
+
+if(NOT CMAKE_CUDA_COMPILER_WORKS)
+  PrintTestCompilerStatus("CUDA" " -- broken")
+  file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+    "Determining if the CUDA compiler works failed with "
+    "the following output:\n${__CMAKE_CUDA_COMPILER_OUTPUT}\n\n")
+  message(FATAL_ERROR "The CUDA compiler \"${CMAKE_CUDA_COMPILER}\" "
+    "is not able to compile a simple test program.\nIt fails "
+    "with the following output:\n ${__CMAKE_CUDA_COMPILER_OUTPUT}\n\n"
+    "CMake will not be able to correctly generate this project.")
+else()
+  if(CUDA_TEST_WAS_RUN)
+    PrintTestCompilerStatus("CUDA" " -- works")
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+      "Determining if the CUDA compiler works passed with "
+      "the following output:\n${__CMAKE_CUDA_COMPILER_OUTPUT}\n\n")
+  endif()
+endif()
+
+unset(__CMAKE_CUDA_COMPILER_OUTPUT)
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
new file mode 100644
index 0000000..9fcd8d7
--- /dev/null
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -0,0 +1,16 @@
+set(CMAKE_CXX_VERBOSE_FLAG "-v")
+
+
+set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE)
+set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC)
+set(CMAKE_SHARED_LIBRARY_CUDA_FLAGS -Xcompiler=-fPIC)
+set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared)
+set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=)
+set(CMAKE_CUDA_COMPILE_OPTIONS_VISIBILITY -Xcompiler=-fvisibility=)
+
+if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 7.0)
+  set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+  set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=c++11")
+  set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "-std=c++11")
+  set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "-std=c++11")
+endif()
diff --git a/Modules/Compiler/NVIDIA-DetermineCompiler.cmake b/Modules/Compiler/NVIDIA-DetermineCompiler.cmake
new file mode 100644
index 0000000..32ccf8a
--- /dev/null
+++ b/Modules/Compiler/NVIDIA-DetermineCompiler.cmake
@@ -0,0 +1,7 @@
+
+set(_compiler_id_pp_test "defined(__NVCC__)")
+
+set(_compiler_id_version_compute "
+# define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__CUDACC_VER_MAJOR__)
+# define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__CUDACC_VER_MINOR__)
+# define @PREFIX@COMPILER_VERSION_PATCH @MACRO_DEC@(__CUDACC_VER_BUILD__)")
-- 
cgit v0.12