# 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_try_compiler_or_linker_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_try_compiler_or_linker_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_TRY_COMPILER_OR_LINKER_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()
