CheckCSourceCompiles.cmake 5.63 KB
Newer Older
1 2 3
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

4 5 6 7 8 9 10 11
#[=======================================================================[.rst:
CheckCSourceCompiles
--------------------

Check if given C source compiles and links into an executable.

.. command:: check_c_source_compiles

12
  .. code-block:: cmake
13

14 15
    check_c_source_compiles(<code> <resultVar>
                            [FAIL_REGEX <regex1> [<regex2>...]])
16

17
  Check that the source supplied in ``<code>`` can be compiled as a C source
18 19
  file and linked as an executable (so it must contain at least a ``main()``
  function). The result will be stored in the internal cache variable specified
20 21
  by ``<resultVar>``, with a boolean true value for success and boolean false
  for failure. If ``FAIL_REGEX`` is provided, then failure is determined by
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
  checking if anything in the output matches any of the specified regular
  expressions.

  The underlying check is performed by the :command:`try_compile` command. The
  compile and link commands can be influenced by setting any of the following
  variables prior to calling ``check_c_source_compiles()``:

  ``CMAKE_REQUIRED_FLAGS``
    Additional flags to pass to the compiler. Note that the contents of
    :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
    configuration-specific variable are automatically added to the compiler
    command before the contents of ``CMAKE_REQUIRED_FLAGS``.

  ``CMAKE_REQUIRED_DEFINITIONS``
    A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
    ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
38
    ``<resultVar>`` will also be added automatically.
39 40 41 42 43 44 45

  ``CMAKE_REQUIRED_INCLUDES``
    A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
    the compiler. These will be the only header search paths used by
    ``try_compile()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
    directory property will be ignored.

46 47 48 49
  ``CMAKE_REQUIRED_LINK_OPTIONS``
    A :ref:`;-list <CMake Language Lists>` of options to add to the link
    command (see :command:`try_compile` for further details).

50 51 52 53 54 55 56 57 58 59 60
  ``CMAKE_REQUIRED_LIBRARIES``
    A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
    command. These can be the name of system libraries or they can be
    :ref:`Imported Targets <Imported Targets>` (see :command:`try_compile` for
    further details).

  ``CMAKE_REQUIRED_QUIET``
    If this variable evaluates to a boolean true value, all status messages
    associated with the check will be suppressed.

  The check is only performed once, with the result cached in the variable
61 62
  named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
  value rather than performing the check again, even if the ``<code>`` changes.
63
  In order to force the check to be re-evaluated, the variable named by
64
  ``<resultVar>`` must be manually removed from the cache.
65 66 67

#]=======================================================================]

68
include_guard(GLOBAL)
69

70
macro(CHECK_C_SOURCE_COMPILES SOURCE VAR)
71
  if(NOT DEFINED "${VAR}")
72 73 74 75 76 77 78 79 80 81 82 83
    set(_FAIL_REGEX)
    set(_key)
    foreach(arg ${ARGN})
      if("${arg}" MATCHES "^(FAIL_REGEX)$")
        set(_key "${arg}")
      elseif(_key)
        list(APPEND _${_key} "${arg}")
      else()
        message(FATAL_ERROR "Unknown argument:\n  ${arg}\n")
      endif()
    endforeach()
    set(MACRO_CHECK_FUNCTION_DEFINITIONS
84
      "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
85 86 87 88 89 90
    if(CMAKE_REQUIRED_LINK_OPTIONS)
      set(CHECK_C_SOURCE_COMPILES_ADD_LINK_OPTIONS
        LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
    else()
      set(CHECK_C_SOURCE_COMPILES_ADD_LINK_OPTIONS)
    endif()
91 92
    if(CMAKE_REQUIRED_LIBRARIES)
      set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
93
        LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
94
    else()
95
      set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
96
    endif()
97 98
    if(CMAKE_REQUIRED_INCLUDES)
      set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
99
        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
100
    else()
101
      set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
102
    endif()
103
    file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
104
      "${SOURCE}\n")
105

106 107 108
    if(NOT CMAKE_REQUIRED_QUIET)
      message(STATUS "Performing Test ${VAR}")
    endif()
109
    try_compile(${VAR}
110
      ${CMAKE_BINARY_DIR}
111
      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
112
      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
113
      ${CHECK_C_SOURCE_COMPILES_ADD_LINK_OPTIONS}
114
      ${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}
115
      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
116 117
      "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
      OUTPUT_VARIABLE OUTPUT)
118

119 120 121 122 123
    foreach(_regex ${_FAIL_REGEX})
      if("${OUTPUT}" MATCHES "${_regex}")
        set(${VAR} 0)
      endif()
    endforeach()
124

125 126
    if(${VAR})
      set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
127 128 129
      if(NOT CMAKE_REQUIRED_QUIET)
        message(STATUS "Performing Test ${VAR} - Success")
      endif()
130
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
131
        "Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n"
132
        "${OUTPUT}\n"
133
        "Source file was:\n${SOURCE}\n")
134
    else()
135 136 137
      if(NOT CMAKE_REQUIRED_QUIET)
        message(STATUS "Performing Test ${VAR} - Failed")
      endif()
138 139
      set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
140 141
        "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
        "${OUTPUT}\n"
142
        "Source file was:\n${SOURCE}\n")
143 144 145
    endif()
  endif()
endmacro()