CMakeCheckCompilerFlag.cmake 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. NOTE: This function is used internally by CMake. Projects should not include
  5. this file directly.
  6. The cmake_check_compiler_flag() function can be used to compile and link a
  7. source file to check whether a specific compiler or linker flag is supported.
  8. The function does not use the try_compile() command so as to avoid infinite
  9. recursion. It may not work for all platforms or toolchains, the caller is
  10. responsible for ensuring it is only called in valid situations.
  11. cmake_check_compiler_flag(<lang> <flag> <result>
  12. [SRC_EXT <ext>] [COMMAND_PATTERN <pattern>]
  13. [FAIL_REGEX <regex> ...]
  14. [OUTPUT_VARIABLE <output>])
  15. Parameters:
  16. <lang> - Language to check.
  17. <flag> - The flag to add to the compile/link command line.
  18. <result> - Boolean output variable. It will be stored in the cache as an
  19. internal variable and if true, will cause future tests that assign
  20. to that variable to be bypassed.
  21. Optional parameters:
  22. SRC_EXT - Overrides the extension of the source file used for the
  23. check. Defaults are 'c' (C), 'cxx' (CXX), 'F' (Fortran).
  24. COMMAND_PATTERN - Pattern to be used for the command line. The default is
  25. '<FLAG> -o <OUTPUT> <SOURCE>'
  26. FAIL_REGEX - List of additional regular expressions that, if matched by
  27. the output, give a failed result for the check. A common
  28. set of regular expressions will be included in addition to
  29. those given by FAIL_REGEX.
  30. OUTPUT_VARIABLE - Set <output> variable with details about any error.
  31. #]=]
  32. include_guard(GLOBAL)
  33. include(CMakeCheckCompilerFlagCommonPatterns)
  34. function(CMAKE_CHECK_COMPILER_FLAG lang flag result)
  35. # Cache results between runs similar to check_<lang>_source_compiles()
  36. if(DEFINED ${result})
  37. return()
  38. endif()
  39. set(comment "Is the '${flag}' option(s) supported")
  40. string(REPLACE ";" " " comment "${comment}")
  41. if (NOT lang MATCHES "^(C|CXX|Fortran|ASM)$")
  42. # other possible languages are not supported
  43. # log message to keep trace of this problem...
  44. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  45. "Function 'CMAKE_CHECK_COMPILER_FLAG' called with unsupported language: ${lang}\n")
  46. set(${result} FALSE CACHE INTERNAL ${comment})
  47. return()
  48. endif()
  49. if (lang STREQUAL "ASM")
  50. # assume ASM compiler is a multi-language compiler, so supports C language as well
  51. set(check_lang C)
  52. else()
  53. set(check_lang ${lang})
  54. endif()
  55. cmake_parse_arguments(CCCF "" "SRC_EXT;COMMAND_PATTERN;OUTPUT_VARIABLE" "FAIL_REGEX" ${ARGN})
  56. if (NOT CCCF_COMMAND_PATTERN)
  57. set (CCCF_COMMAND_PATTERN "<FLAG> -o <OUTPUT> <SOURCE>")
  58. endif()
  59. list (APPEND CCCF_FAIL_REGEX "argument unused during compilation") # clang
  60. if (check_lang STREQUAL "C")
  61. list(APPEND CCCF_FAIL_REGEX
  62. "command line option .* is valid for .* but not for C") # GNU
  63. elseif(check_lang STREQUAL "CXX")
  64. list(APPEND CCCF_FAIL_REGEX
  65. "command line option .* is valid for .* but not for C\\+\\+") # GNU
  66. elseif(check_lang STREQUAL "Fortran")
  67. list(APPEND CCCF_FAIL_REGEX
  68. "command line option .* is valid for .* but not for Fortran") # GNU
  69. endif()
  70. # Add patterns for common errors
  71. check_compiler_flag_common_patterns(COMPILER_FLAG_COMMON_PATTERNS)
  72. foreach(arg IN LISTS COMPILER_FLAG_COMMON_PATTERNS)
  73. if(arg MATCHES "^FAIL_REGEX$")
  74. continue()
  75. endif()
  76. list(APPEND CCCF_FAIL_REGEX "${arg}")
  77. endforeach()
  78. if(NOT CCCF_SRC_EXT)
  79. if (check_lang STREQUAL "C")
  80. set(CCCF_SRC_EXT c)
  81. elseif(check_lang STREQUAL "CXX")
  82. set(CCCF_SRC_EXT cxx)
  83. elseif(check_lang STREQUAL "Fortran")
  84. set(CCCF_SRC_EXT F)
  85. endif()
  86. endif()
  87. if (CCCF_OUTPUT_VARIABLE)
  88. unset(${CCCF_OUTPUT_VARIABLE} PARENT_SCOPE)
  89. endif()
  90. # Compute the directory in which to run the test.
  91. set(COMPILER_FLAG_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
  92. # Compute source and output files.
  93. set(COMPILER_FLAG_SRC
  94. "${COMPILER_FLAG_DIR}/CompilerFlag${lang}.${CCCF_SRC_EXT}")
  95. if(check_lang STREQUAL "Fortran")
  96. file(WRITE "${COMPILER_FLAG_SRC}"
  97. " program simple\n end program simple\n")
  98. else()
  99. file(WRITE "${COMPILER_FLAG_SRC}" "int main (void)\n{ return 0; }\n")
  100. endif()
  101. get_filename_component(COMPILER_FLAG_EXE "${COMPILER_FLAG_SRC}" NAME_WE)
  102. string(APPEND COMPILER_FLAG_EXE "${CMAKE_EXECUTABLE_SUFFIX}")
  103. # Build command line
  104. separate_arguments(CCCF_COMMAND_PATTERN UNIX_COMMAND
  105. "${CCCF_COMMAND_PATTERN}")
  106. list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<SOURCE>" "${COMPILER_FLAG_SRC}")
  107. list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<OUTPUT>" "${COMPILER_FLAG_EXE}")
  108. list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<FLAG>" "${flag}")
  109. execute_process(
  110. COMMAND "${CMAKE_COMMAND}" -E env LC_ALL=C LC_MESSAGES=C LANG=C
  111. "${CMAKE_${lang}_COMPILER}" ${CCCF_COMMAND_PATTERN}
  112. WORKING_DIRECTORY "${COMPILER_FLAG_DIR}"
  113. OUTPUT_VARIABLE COMPILER_FLAG_OUTPUT
  114. ERROR_VARIABLE COMPILER_FLAG_OUTPUT
  115. RESULT_VARIABLE COMPILER_FLAG_RESULT)
  116. # Record result in the cache so we can avoid re-testing every CMake run
  117. if (COMPILER_FLAG_RESULT)
  118. set(${result} FALSE CACHE INTERNAL ${comment})
  119. else()
  120. foreach(regex IN LISTS CCCF_FAIL_REGEX)
  121. if(COMPILER_FLAG_OUTPUT MATCHES "${regex}")
  122. set(${result} FALSE CACHE INTERNAL ${comment})
  123. endif()
  124. endforeach()
  125. endif()
  126. if (DEFINED ${result})
  127. file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  128. "Determining if the ${flag} option "
  129. "is supported for ${lang} language failed with the following output:\n"
  130. "${COMPILER_FLAG_OUTPUT}\n")
  131. if (CCCF_OUTPUT_VARIABLE)
  132. set(${CCCF_OUTPUT_VARIABLE} "${COMPILER_FLAG_OUTPUT}" PARENT_SCOPE)
  133. endif()
  134. return()
  135. endif()
  136. set(${result} TRUE CACHE INTERNAL ${comment})
  137. endfunction()