1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5CheckLanguage
6-------------
7
8Check if a language can be enabled
9
10Usage:
11
12::
13
14  check_language(<lang>)
15
16where ``<lang>`` is a language that may be passed to :command:`enable_language`
17such as ``Fortran``.  If :variable:`CMAKE_<LANG>_COMPILER` is already defined
18the check does nothing.  Otherwise it tries enabling the language in a
19test project.  The result is cached in :variable:`CMAKE_<LANG>_COMPILER`
20as the compiler that was found, or ``NOTFOUND`` if the language cannot be
21enabled. For CUDA which can have an explicit host compiler, the cache
22:variable:`CMAKE_CUDA_HOST_COMPILER` variable will be set if it was required
23for compilation (and cleared if it was not).
24
25Example:
26
27::
28
29  check_language(Fortran)
30  if(CMAKE_Fortran_COMPILER)
31    enable_language(Fortran)
32  else()
33    message(STATUS "No Fortran support")
34  endif()
35#]=======================================================================]
36
37include_guard(GLOBAL)
38
39cmake_policy(PUSH)
40cmake_policy(SET CMP0126 NEW)
41
42macro(check_language lang)
43  if(NOT DEFINED CMAKE_${lang}_COMPILER)
44    set(_desc "Looking for a ${lang} compiler")
45    message(CHECK_START "${_desc}")
46    file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang})
47
48    set(extra_compiler_variables)
49    if(${lang} STREQUAL CUDA AND NOT CMAKE_GENERATOR MATCHES "Visual Studio")
50      set(extra_compiler_variables "set(CMAKE_CUDA_HOST_COMPILER \\\"\${CMAKE_CUDA_HOST_COMPILER}\\\")")
51    endif()
52
53    set(_cl_content
54      "cmake_minimum_required(VERSION ${CMAKE_VERSION})
55project(Check${lang} ${lang})
56file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
57  \"set(CMAKE_${lang}_COMPILER \\\"\${CMAKE_${lang}_COMPILER}\\\")\\n\"
58  \"${extra_compiler_variables}\\n\"
59  )"
60    )
61
62    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/CMakeLists.txt"
63      "${_cl_content}")
64    if(CMAKE_GENERATOR_INSTANCE)
65      set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
66    else()
67      set(_D_CMAKE_GENERATOR_INSTANCE "")
68    endif()
69    if(CMAKE_GENERATOR MATCHES "^(Xcode$|Green Hills MULTI$|Visual Studio)")
70      set(_D_CMAKE_MAKE_PROGRAM "")
71    else()
72      set(_D_CMAKE_MAKE_PROGRAM "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
73    endif()
74    if(CMAKE_TOOLCHAIN_FILE)
75      set(_D_CMAKE_TOOLCHAIN_FILE "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE}")
76    else()
77      set(_D_CMAKE_TOOLCHAIN_FILE "")
78    endif()
79    execute_process(
80      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
81      COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
82                                 -A "${CMAKE_GENERATOR_PLATFORM}"
83                                 -T "${CMAKE_GENERATOR_TOOLSET}"
84                                 ${_D_CMAKE_GENERATOR_INSTANCE}
85                                 ${_D_CMAKE_MAKE_PROGRAM}
86                                 ${_D_CMAKE_TOOLCHAIN_FILE}
87      OUTPUT_VARIABLE _cl_output
88      ERROR_VARIABLE _cl_output
89      RESULT_VARIABLE _cl_result
90      )
91    include(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/result.cmake OPTIONAL)
92    if(CMAKE_${lang}_COMPILER AND "${_cl_result}" STREQUAL "0")
93      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
94        "${_desc} passed with the following output:\n"
95        "${_cl_output}\n")
96      set(_CHECK_COMPILER_STATUS CHECK_PASS)
97    else()
98      set(CMAKE_${lang}_COMPILER NOTFOUND)
99      set(_CHECK_COMPILER_STATUS CHECK_FAIL)
100      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
101        "${_desc} failed with the following output:\n"
102        "${_cl_output}\n")
103    endif()
104    message(${_CHECK_COMPILER_STATUS} "${CMAKE_${lang}_COMPILER}")
105    set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER}" CACHE FILEPATH "${lang} compiler")
106    mark_as_advanced(CMAKE_${lang}_COMPILER)
107
108    if(CMAKE_${lang}_HOST_COMPILER)
109      message(STATUS "Looking for a ${lang} host compiler - ${CMAKE_${lang}_HOST_COMPILER}")
110      set(CMAKE_${lang}_HOST_COMPILER "${CMAKE_${lang}_HOST_COMPILER}" CACHE FILEPATH "${lang} host compiler")
111      mark_as_advanced(CMAKE_${lang}_HOST_COMPILER)
112    endif()
113
114  endif()
115endmacro()
116
117cmake_policy(POP)
118