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

4

5 6 7 8
# Function to compile a source file to identify the compiler ABI.
# This is used internally by CMake and should not be included by user
# code.

9
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitIncludeInfo.cmake)
10
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
Fred Baksik's avatar
Fred Baksik committed
11
include(CMakeTestCompilerCommon)
12

13
function(CMAKE_DETERMINE_COMPILER_ABI lang src)
14
  if(NOT DEFINED CMAKE_${lang}_ABI_COMPILED)
15
    message(STATUS "Detecting ${lang} compiler ABI info")
16 17

    # Compile the ABI identification source.
18
    set(BIN "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_${lang}.bin")
19
    set(CMAKE_FLAGS )
20
    set(COMPILE_DEFINITIONS )
21
    if(DEFINED CMAKE_${lang}_VERBOSE_FLAG)
22
      set(CMAKE_FLAGS "-DEXE_LINKER_FLAGS=${CMAKE_${lang}_VERBOSE_FLAG}")
23 24 25 26
      set(COMPILE_DEFINITIONS "${CMAKE_${lang}_VERBOSE_FLAG}")
    endif()
    if(DEFINED CMAKE_${lang}_VERBOSE_COMPILE_FLAG)
      set(COMPILE_DEFINITIONS "${CMAKE_${lang}_VERBOSE_COMPILE_FLAG}")
27
    endif()
28 29 30 31 32
    if(NOT "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC")
      # Avoid adding our own platform standard libraries for compilers
      # from which we might detect implicit link libraries.
      list(APPEND CMAKE_FLAGS "-DCMAKE_${lang}_STANDARD_LIBRARIES=")
    endif()
Fred Baksik's avatar
Fred Baksik committed
33
    __TestCompiler_setTryCompileTargetType()
34 35 36 37 38 39 40 41 42 43 44

    # Save the current LC_ALL, LC_MESSAGES, and LANG environment variables
    # and set them to "C" that way GCC's "search starts here" text is in
    # English and we can grok it.
    set(_orig_lc_all      $ENV{LC_ALL})
    set(_orig_lc_messages $ENV{LC_MESSAGES})
    set(_orig_lang        $ENV{LANG})
    set(ENV{LC_ALL}      C)
    set(ENV{LC_MESSAGES} C)
    set(ENV{LANG}        C)

45
    try_compile(CMAKE_${lang}_ABI_COMPILED
46
      ${CMAKE_BINARY_DIR} ${src}
47 48
      CMAKE_FLAGS ${CMAKE_FLAGS}
                  # Ignore unused flags when we are just determining the ABI.
49
                  "--no-warn-unused-cli"
50
      COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS}
51 52
      OUTPUT_VARIABLE OUTPUT
      COPY_FILE "${BIN}"
53
      COPY_FILE_ERROR _copy_error
54
      )
55 56 57 58 59 60

    # Restore original LC_ALL, LC_MESSAGES, and LANG
    set(ENV{LC_ALL}      ${_orig_lc_all})
    set(ENV{LC_MESSAGES} ${_orig_lc_messages})
    set(ENV{LANG}        ${_orig_lang})

61 62 63 64
    # Move result from cache to normal variable.
    set(CMAKE_${lang}_ABI_COMPILED ${CMAKE_${lang}_ABI_COMPILED})
    unset(CMAKE_${lang}_ABI_COMPILED CACHE)
    set(CMAKE_${lang}_ABI_COMPILED ${CMAKE_${lang}_ABI_COMPILED} PARENT_SCOPE)
65 66

    # Load the resulting information strings.
67
    if(CMAKE_${lang}_ABI_COMPILED AND NOT _copy_error)
68 69
      message(STATUS "Detecting ${lang} compiler ABI info - done")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
70
        "Detecting ${lang} compiler ABI info compiled with the following output:\n${OUTPUT}\n\n")
71
      file(STRINGS "${BIN}" ABI_STRINGS LIMIT_COUNT 2 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
72
      foreach(info ${ABI_STRINGS})
73
        if("${info}" MATCHES "INFO:sizeof_dptr\\[0*([^]]*)\\]")
74
          set(ABI_SIZEOF_DPTR "${CMAKE_MATCH_1}")
75
        endif()
76
        if("${info}" MATCHES "INFO:abi\\[([^]]*)\\]")
77
          set(ABI_NAME "${CMAKE_MATCH_1}")
78 79
        endif()
      endforeach()
80

81 82 83 84
      if(ABI_SIZEOF_DPTR)
        set(CMAKE_${lang}_SIZEOF_DATA_PTR "${ABI_SIZEOF_DPTR}" PARENT_SCOPE)
      elseif(CMAKE_${lang}_SIZEOF_DATA_PTR_DEFAULT)
        set(CMAKE_${lang}_SIZEOF_DATA_PTR "${CMAKE_${lang}_SIZEOF_DATA_PTR_DEFAULT}" PARENT_SCOPE)
85
      endif()
86

87 88
      if(ABI_NAME)
        set(CMAKE_${lang}_COMPILER_ABI "${ABI_NAME}" PARENT_SCOPE)
89
      endif()
90

91 92 93 94 95 96 97 98 99 100 101 102
      # Parse implicit include directory for this language, if available.
      set (implicit_incdirs "")
      if(CMAKE_${lang}_VERBOSE_FLAG)
        cmake_parse_implicit_include_info("${OUTPUT}" "${lang}"
          implicit_incdirs log rv)
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
          "Parsed ${lang} implicit include dir info from above output: rv=${rv}\n${log}\n\n")
        if("${rv}" STREQUAL "done")  # update parent if parse completed ok
          set(CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES "${implicit_incdirs}" PARENT_SCOPE)
        endif()
      endif()

103
      # Parse implicit linker information for this language, if available.
104 105
      set(implicit_dirs "")
      set(implicit_libs "")
106
      set(implicit_fwks "")
107
      if(CMAKE_${lang}_VERBOSE_FLAG)
108
        CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs implicit_fwks log
109
          "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}")
110
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
111
          "Parsed ${lang} implicit link information from above output:\n${log}\n\n")
112
      endif()
113 114 115
      # for VS IDE Intel Fortran we have to figure out the
      # implicit link path for the fortran run time using
      # a try-compile
116
      if("${lang}" MATCHES "Fortran"
117
          AND "${CMAKE_GENERATOR}" MATCHES "Visual Studio")
118 119
        set(_desc "Determine Intel Fortran Compiler Implicit Link Path")
        message(STATUS "${_desc}")
120
        # Build a sample project which reports symbols.
121
        try_compile(IFORT_LIB_PATH_COMPILED
122
          ${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath
123
          ${CMAKE_ROOT}/Modules/IntelVSImplicitPath
124 125 126 127
          IntelFortranImplicit
          CMAKE_FLAGS
          "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}"
          OUTPUT_VARIABLE _output)
128
        file(WRITE
129 130
          "${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath/output.txt"
          "${_output}")
131 132 133 134
        include(${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath/output.cmake OPTIONAL)
        set(_desc "Determine Intel Fortran Compiler Implicit Link Path -- done")
        message(STATUS "${_desc}")
      endif()
135

136 137 138 139 140 141 142 143
      # Implicit link libraries cannot be used explicitly for multiple
      # OS X architectures, so we skip it.
      if(DEFINED CMAKE_OSX_ARCHITECTURES)
        if("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";")
          set(implicit_libs "")
        endif()
      endif()

144 145
      set(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE)
      set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE)
146
      set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE)
147

148
      # Detect library architecture directory name.
149 150 151 152 153 154 155 156 157
      if(CMAKE_LIBRARY_ARCHITECTURE_REGEX)
        foreach(dir ${implicit_dirs})
          if("${dir}" MATCHES "/lib/${CMAKE_LIBRARY_ARCHITECTURE_REGEX}$")
            get_filename_component(arch "${dir}" NAME)
            set(CMAKE_${lang}_LIBRARY_ARCHITECTURE "${arch}" PARENT_SCOPE)
            break()
          endif()
        endforeach()
      endif()
158

159
    else()
160 161
      message(STATUS "Detecting ${lang} compiler ABI info - failed")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
162
        "Detecting ${lang} compiler ABI info failed to compile with the following output:\n${OUTPUT}\n${_copy_error}\n\n")
163 164 165
    endif()
  endif()
endfunction()