| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| # file Copyright.txt or https://cmake.org/licensing for details. |
| |
| #[=[ |
| |
| NOTE: This function is used internally by CMake. Projects should not include |
| this file directly. |
| |
| The cmake_check_compiler_flag() function can be used to compile and link a |
| source file to check whether a specific compiler or linker flag is supported. |
| The function does not use the try_compile() command so as to avoid infinite |
| recursion. It may not work for all platforms or toolchains, the caller is |
| responsible for ensuring it is only called in valid situations. |
| |
| cmake_check_compiler_flag(<lang> <flag> <result> |
| [SRC_EXT <ext>] [COMMAND_PATTERN <pattern>] |
| [FAIL_REGEX <regex> ...] |
| [OUTPUT_VARIABLE <output>]) |
| |
| Parameters: |
| <lang> - Language to check. |
| <flag> - The flag to add to the compile/link command line. |
| <result> - Boolean output variable. It will be stored in the cache as an |
| internal variable and if true, will cause future tests that assign |
| to that variable to be bypassed. |
| |
| Optional parameters: |
| SRC_EXT - Overrides the extension of the source file used for the |
| check. Defaults are 'c' (C), 'cxx' (CXX), 'F' (Fortran). |
| COMMAND_PATTERN - Pattern to be used for the command line. The default is |
| '<FLAG> -o <OUTPUT> <SOURCE>' |
| FAIL_REGEX - List of additional regular expressions that, if matched by |
| the output, give a failed result for the check. A common |
| set of regular expressions will be included in addition to |
| those given by FAIL_REGEX. |
| OUTPUT_VARIABLE - Set <output> variable with details about any error. |
| #]=] |
| |
| include_guard(GLOBAL) |
| include(CMakeCheckCompilerFlagCommonPatterns) |
| |
| function(CMAKE_CHECK_COMPILER_FLAG lang flag result) |
| # Cache results between runs similar to check_<lang>_source_compiles() |
| if(DEFINED ${result}) |
| return() |
| endif() |
| |
| set(comment "Is the '${flag}' option(s) supported") |
| string(REPLACE ";" " " comment "${comment}") |
| |
| if (NOT lang MATCHES "^(C|CXX|Fortran|ASM)$") |
| # other possible languages are not supported |
| # log message to keep trace of this problem... |
| file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log |
| "Function 'CMAKE_CHECK_COMPILER_FLAG' called with unsupported language: ${lang}\n") |
| set(${result} FALSE CACHE INTERNAL ${comment}) |
| return() |
| endif() |
| if (lang STREQUAL "ASM") |
| # assume ASM compiler is a multi-language compiler, so supports C language as well |
| set(check_lang C) |
| else() |
| set(check_lang ${lang}) |
| endif() |
| |
| cmake_parse_arguments(CCCF "" "SRC_EXT;COMMAND_PATTERN;OUTPUT_VARIABLE" "FAIL_REGEX" ${ARGN}) |
| |
| if (NOT CCCF_COMMAND_PATTERN) |
| set (CCCF_COMMAND_PATTERN "<FLAG> -o <OUTPUT> <SOURCE>") |
| endif() |
| |
| list (APPEND CCCF_FAIL_REGEX "argument unused during compilation") # clang |
| if (check_lang STREQUAL "C") |
| list(APPEND CCCF_FAIL_REGEX |
| "command line option .* is valid for .* but not for C") # GNU |
| elseif(check_lang STREQUAL "CXX") |
| list(APPEND CCCF_FAIL_REGEX |
| "command line option .* is valid for .* but not for C\\+\\+") # GNU |
| elseif(check_lang STREQUAL "Fortran") |
| list(APPEND CCCF_FAIL_REGEX |
| "command line option .* is valid for .* but not for Fortran") # GNU |
| endif() |
| |
| # Add patterns for common errors |
| check_compiler_flag_common_patterns(COMPILER_FLAG_COMMON_PATTERNS) |
| foreach(arg IN LISTS COMPILER_FLAG_COMMON_PATTERNS) |
| if(arg MATCHES "^FAIL_REGEX$") |
| continue() |
| endif() |
| list(APPEND CCCF_FAIL_REGEX "${arg}") |
| endforeach() |
| |
| if(NOT CCCF_SRC_EXT) |
| if (check_lang STREQUAL "C") |
| set(CCCF_SRC_EXT c) |
| elseif(check_lang STREQUAL "CXX") |
| set(CCCF_SRC_EXT cxx) |
| elseif(check_lang STREQUAL "Fortran") |
| set(CCCF_SRC_EXT F) |
| endif() |
| endif() |
| |
| if (CCCF_OUTPUT_VARIABLE) |
| unset(${CCCF_OUTPUT_VARIABLE} PARENT_SCOPE) |
| endif() |
| |
| # Compute the directory in which to run the test. |
| set(COMPILER_FLAG_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp") |
| # Compute source and output files. |
| set(COMPILER_FLAG_SRC |
| "${COMPILER_FLAG_DIR}/CompilerFlag${lang}.${CCCF_SRC_EXT}") |
| if(check_lang STREQUAL "Fortran") |
| file(WRITE "${COMPILER_FLAG_SRC}" |
| " program simple\n end program simple\n") |
| else() |
| file(WRITE "${COMPILER_FLAG_SRC}" "int main (void)\n{ return 0; }\n") |
| endif() |
| get_filename_component(COMPILER_FLAG_EXE "${COMPILER_FLAG_SRC}" NAME_WE) |
| string(APPEND COMPILER_FLAG_EXE "${CMAKE_EXECUTABLE_SUFFIX}") |
| |
| # Build command line |
| separate_arguments(CCCF_COMMAND_PATTERN UNIX_COMMAND |
| "${CCCF_COMMAND_PATTERN}") |
| list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<SOURCE>" "${COMPILER_FLAG_SRC}") |
| list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<OUTPUT>" "${COMPILER_FLAG_EXE}") |
| list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<FLAG>" "${flag}") |
| |
| execute_process( |
| COMMAND "${CMAKE_COMMAND}" -E env LC_ALL=C LC_MESSAGES=C LANG=C |
| "${CMAKE_${lang}_COMPILER}" ${CCCF_COMMAND_PATTERN} |
| WORKING_DIRECTORY "${COMPILER_FLAG_DIR}" |
| OUTPUT_VARIABLE COMPILER_FLAG_OUTPUT |
| ERROR_VARIABLE COMPILER_FLAG_OUTPUT |
| RESULT_VARIABLE COMPILER_FLAG_RESULT) |
| |
| # Record result in the cache so we can avoid re-testing every CMake run |
| if (COMPILER_FLAG_RESULT) |
| set(${result} FALSE CACHE INTERNAL ${comment}) |
| else() |
| foreach(regex IN LISTS CCCF_FAIL_REGEX) |
| if(COMPILER_FLAG_OUTPUT MATCHES "${regex}") |
| set(${result} FALSE CACHE INTERNAL ${comment}) |
| endif() |
| endforeach() |
| endif() |
| if (DEFINED ${result}) |
| file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log |
| "Determining if the ${flag} option " |
| "is supported for ${lang} language failed with the following output:\n" |
| "${COMPILER_FLAG_OUTPUT}\n") |
| if (CCCF_OUTPUT_VARIABLE) |
| set(${CCCF_OUTPUT_VARIABLE} "${COMPILER_FLAG_OUTPUT}" PARENT_SCOPE) |
| endif() |
| return() |
| endif() |
| |
| set(${result} TRUE CACHE INTERNAL ${comment}) |
| endfunction() |