CMakeDetermineCompilerABI.cmake 7.5 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)
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()
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
      __CMAKE_INTERNAL ABI
55
      )
56 57 58 59 60 61

    # 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})

62 63 64 65
    # 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)
66 67

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

82 83 84 85
      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)
86
      endif()
87

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

92 93
      # Parse implicit include directory for this language, if available.
      if(CMAKE_${lang}_VERBOSE_FLAG)
94
        set (implicit_incdirs "")
95 96 97 98
        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")
99
        if("${rv}" STREQUAL "done")
100 101 102 103 104 105
          # Entries that we have been told to explicitly pass as standard include
          # directories will not be implicitly added by the compiler.
          if(CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES)
            list(REMOVE_ITEM implicit_incdirs ${CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES})
          endif()

106 107
          # We parsed implicit include directories, so override the default initializer.
          set(_CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT "${implicit_incdirs}")
108 109
        endif()
      endif()
110
      set(CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES "${_CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT}" PARENT_SCOPE)
111

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

145 146 147 148 149 150 151 152
      # 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()

153 154
      set(CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES "${implicit_libs}" PARENT_SCOPE)
      set(CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES "${implicit_dirs}" PARENT_SCOPE)
155
      set(CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "${implicit_fwks}" PARENT_SCOPE)
156

157
      # Detect library architecture directory name.
158 159 160 161 162 163 164 165 166
      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()
167

168
    else()
169 170
      message(STATUS "Detecting ${lang} compiler ABI info - failed")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
171
        "Detecting ${lang} compiler ABI info failed to compile with the following output:\n${OUTPUT}\n${_copy_error}\n\n")
172 173 174
    endif()
  endif()
endfunction()