CheckIncludeFiles.cmake 6.43 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 12
#[=======================================================================[.rst:
CheckIncludeFiles
-----------------

Provides a macro to check if a list of one or more header files can
be included together.

.. command:: CHECK_INCLUDE_FILES

13
  .. code-block:: cmake
14 15 16 17 18 19 20 21

    CHECK_INCLUDE_FILES("<includes>" <variable> [LANGUAGE <language>])

  Check if the given ``<includes>`` list may be included together
  in a source file and store the result in an internal cache
  entry named ``<variable>``.  Specify the ``<includes>`` argument
  as a :ref:`;-list <CMake Language Lists>` of header file names.

22 23 24 25
  If ``LANGUAGE`` is set, the specified compiler will be used to perform the
  check. Acceptable values are ``C`` and ``CXX``. If not set, the C compiler
  will be used if enabled. If the C compiler is not enabled, the C++
  compiler will be used if enabled.
26 27 28 29 30

The following variables may be set before calling this macro to modify
the way the check is run:

``CMAKE_REQUIRED_FLAGS``
31
  string of compile command line flags.
32
``CMAKE_REQUIRED_DEFINITIONS``
33
  a :ref:`;-list <CMake Language Lists>` of macros to define (-DFOO=bar).
34
``CMAKE_REQUIRED_INCLUDES``
35 36 37 38
  a :ref:`;-list <CMake Language Lists>` of header search paths to pass to
  the compiler.
``CMAKE_REQUIRED_LINK_OPTIONS``
  a :ref:`;-list <CMake Language Lists>` of options to add to the link command.
39
``CMAKE_REQUIRED_LIBRARIES``
40 41
  a :ref:`;-list <CMake Language Lists>` of libraries to add to the link
  command. See policy :policy:`CMP0075`.
42
``CMAKE_REQUIRED_QUIET``
43
  execute quietly without messages.
44 45 46 47

See modules :module:`CheckIncludeFile` and :module:`CheckIncludeFileCXX`
to check for a single header file in ``C`` or ``CXX`` languages.
#]=======================================================================]
48

49 50
include_guard(GLOBAL)

51
macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
52
  if(NOT DEFINED "${VARIABLE}")
53
    set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
54 55 56 57 58 59 60

    if("x${ARGN}" STREQUAL "x")
       if(CMAKE_C_COMPILER_LOADED)
         set(_lang C)
       elseif(CMAKE_CXX_COMPILER_LOADED)
         set(_lang CXX)
       else()
61
         message(FATAL_ERROR "CHECK_INCLUDE_FILES needs either C or CXX language enabled.\n")
62 63
       endif()
    elseif("x${ARGN}" MATCHES "^xLANGUAGE;([a-zA-Z]+)$")
64 65 66
      set(_lang "${CMAKE_MATCH_1}")
    elseif("x${ARGN}" MATCHES "^xLANGUAGE$")
      message(FATAL_ERROR "No languages listed for LANGUAGE option.\nSupported languages: C, CXX.\n")
67
    else()
68
      message(FATAL_ERROR "Unknown arguments:\n  ${ARGN}\n")
69 70 71
    endif()

    if(_lang STREQUAL "C")
72
      set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.c)
73
    elseif(_lang STREQUAL "CXX")
74
      set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.cpp)
75 76 77 78
    else()
      message(FATAL_ERROR "Unknown language:\n  ${_lang}\nSupported languages: C, CXX.\n")
    endif()

79 80
    if(CMAKE_REQUIRED_INCLUDES)
      set(CHECK_INCLUDE_FILES_INCLUDE_DIRS "-DINCLUDE_DIRECTORIES=${CMAKE_REQUIRED_INCLUDES}")
81
    else()
82
      set(CHECK_INCLUDE_FILES_INCLUDE_DIRS)
83
    endif()
84 85 86
    set(CHECK_INCLUDE_FILES_CONTENT "/* */\n")
    set(MACRO_CHECK_INCLUDE_FILES_FLAGS ${CMAKE_REQUIRED_FLAGS})
    foreach(FILE ${INCLUDE})
87 88
      string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
        "#include <${FILE}>\n")
89
    endforeach()
90 91
    string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
      "\n\nint main(void){return 0;}\n")
92
    configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
93
      "${src}" @ONLY)
94

95 96 97 98 99 100 101 102 103
    set(_INCLUDE ${INCLUDE}) # remove empty elements
    if("${_INCLUDE}" MATCHES "^([^;]+);.+;([^;]+)$")
      list(LENGTH _INCLUDE _INCLUDE_LEN)
      set(_description "${_INCLUDE_LEN} include files ${CMAKE_MATCH_1}, ..., ${CMAKE_MATCH_2}")
    elseif("${_INCLUDE}" MATCHES "^([^;]+);([^;]+)$")
      set(_description "include files ${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}")
    else()
      set(_description "include file ${_INCLUDE}")
    endif()
104

105 106 107 108 109
    set(_CIF_LINK_OPTIONS)
    if(CMAKE_REQUIRED_LINK_OPTIONS)
      set(_CIF_LINK_OPTIONS LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
    endif()

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    set(_CIF_LINK_LIBRARIES "")
    if(CMAKE_REQUIRED_LIBRARIES)
      cmake_policy(GET CMP0075 _CIF_CMP0075
        PARENT_SCOPE # undocumented, do not use outside of CMake
        )
      if("x${_CIF_CMP0075}x" STREQUAL "xNEWx")
        set(_CIF_LINK_LIBRARIES LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
      elseif("x${_CIF_CMP0075}x" STREQUAL "xOLDx")
      elseif(NOT _CIF_CMP0075_WARNED)
        set(_CIF_CMP0075_WARNED 1)
        message(AUTHOR_WARNING
          "Policy CMP0075 is not set: Include file check macros honor CMAKE_REQUIRED_LIBRARIES.  "
          "Run \"cmake --help-policy CMP0075\" for policy details.  "
          "Use the cmake_policy command to set the policy and suppress this warning."
          "\n"
          "CMAKE_REQUIRED_LIBRARIES is set to:\n"
          "  ${CMAKE_REQUIRED_LIBRARIES}\n"
          "For compatibility with CMake 3.11 and below this check is ignoring it."
          )
      endif()
      unset(_CIF_CMP0075)
    endif()

133 134 135
    if(NOT CMAKE_REQUIRED_QUIET)
      message(STATUS "Looking for ${_description}")
    endif()
136
    try_compile(${VARIABLE}
137
      ${CMAKE_BINARY_DIR}
138
      ${src}
139
      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
140
      ${_CIF_LINK_OPTIONS}
141
      ${_CIF_LINK_LIBRARIES}
142
      CMAKE_FLAGS
143
      -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILES_FLAGS}
144
      "${CHECK_INCLUDE_FILES_INCLUDE_DIRS}"
145
      OUTPUT_VARIABLE OUTPUT)
146
    unset(_CIF_LINK_OPTIONS)
147
    unset(_CIF_LINK_LIBRARIES)
148
    if(${VARIABLE})
149 150 151
      if(NOT CMAKE_REQUIRED_QUIET)
        message(STATUS "Looking for ${_description} - found")
      endif()
152 153
      set(${VARIABLE} 1 CACHE INTERNAL "Have include ${INCLUDE}")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
154 155 156
        "Determining if files ${INCLUDE} "
        "exist passed with the following output:\n"
        "${OUTPUT}\n\n")
157
    else()
158 159 160
      if(NOT CMAKE_REQUIRED_QUIET)
        message(STATUS "Looking for ${_description} - not found")
      endif()
161 162
      set(${VARIABLE} "" CACHE INTERNAL "Have includes ${INCLUDE}")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
163 164
        "Determining if files ${INCLUDE} "
        "exist failed with the following output:\n"
165
        "${OUTPUT}\nSource:\n${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
166 167 168
    endif()
  endif()
endmacro()