File: CMakeDetermineCompilerABI.cmake

package info (click to toggle)
cmake 3.31.6-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 142,992 kB
  • sloc: ansic: 393,437; cpp: 288,767; sh: 3,958; yacc: 3,240; python: 3,015; lex: 1,337; asm: 438; f90: 429; lisp: 375; cs: 270; java: 266; perl: 217; objc: 212; xml: 198; fortran: 137; makefile: 96; javascript: 83; pascal: 63; tcl: 55; php: 25; ruby: 22
file content (273 lines) | stat: -rw-r--r-- 12,669 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.


# 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.

include(${CMAKE_ROOT}/Modules/Internal/CMakeDetermineLinkerId.cmake)
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitIncludeInfo.cmake)
include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
include(${CMAKE_ROOT}/Modules/CMakeParseLibraryArchitecture.cmake)
include(CMakeTestCompilerCommon)

function(CMAKE_DETERMINE_COMPILER_ABI lang src)
  if(NOT DEFINED CMAKE_${lang}_ABI_COMPILED)
    message(CHECK_START "Detecting ${lang} compiler ABI info")

    # Compile the ABI identification source.
    set(BIN "${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerABI_${lang}.bin")
    set(CMAKE_FLAGS )
    set(COMPILE_DEFINITIONS )
    set(LINK_OPTIONS )
    if(DEFINED CMAKE_${lang}_VERBOSE_FLAG)
      set(LINK_OPTIONS "${CMAKE_${lang}_VERBOSE_FLAG}")
      set(COMPILE_DEFINITIONS "${CMAKE_${lang}_VERBOSE_FLAG}")
    endif()
    if(DEFINED CMAKE_${lang}_VERBOSE_COMPILE_FLAG)
      set(COMPILE_DEFINITIONS "${CMAKE_${lang}_VERBOSE_COMPILE_FLAG}")
    endif()
    if(DEFINED CMAKE_${lang}_VERBOSE_LINK_FLAG)
      list(APPEND LINK_OPTIONS "${CMAKE_${lang}_VERBOSE_LINK_FLAG}")
    endif()
    if(lang MATCHES "^(CUDA|HIP)$")
      if(CMAKE_CUDA_ARCHITECTURES STREQUAL "native")
        # We are about to detect the native architectures, so we do
        # not yet know them.  Use all architectures during detection.
        set(CMAKE_${lang}_ARCHITECTURES "all")
      endif()
      set(CMAKE_${lang}_RUNTIME_LIBRARY "Static")
    endif()
    if(lang STREQUAL "CXX")
      set(CMAKE_${lang}_SCAN_FOR_MODULES OFF)
    endif()
    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()
    list(JOIN LINK_OPTIONS " " LINK_OPTIONS)
    list(APPEND CMAKE_FLAGS "-DEXE_LINKER_FLAGS=${LINK_OPTIONS}")

    __TestCompiler_setTryCompileTargetType()

    # Avoid failing ABI detection on warnings.
    if(CMAKE_TRY_COMPILE_CONFIGURATION)
      string(TOUPPER "${CMAKE_TRY_COMPILE_CONFIGURATION}" _tc_config)
    else()
      set(_tc_config "DEBUG")
    endif()
    foreach(v CMAKE_${lang}_FLAGS CMAKE_${lang}_FLAGS_${_tc_config})
      string(REGEX REPLACE "(^| )-Werror([= ][^-][^ ]*)?( |$)" " " ${v} "${${v}}")
    endforeach()

    # 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)
    try_compile(CMAKE_${lang}_ABI_COMPILED
      SOURCES ${src}
      CMAKE_FLAGS ${CMAKE_FLAGS}
                  # Ignore unused flags when we are just determining the ABI.
                  "--no-warn-unused-cli"
      COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS}
      OUTPUT_VARIABLE OUTPUT
      COPY_FILE "${BIN}"
      COPY_FILE_ERROR _copy_error
      __CMAKE_INTERNAL ABI
      )

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

    # Move result from cache to normal variable.
    set(CMAKE_${lang}_ABI_COMPILED ${CMAKE_${lang}_ABI_COMPILED})
    unset(CMAKE_${lang}_ABI_COMPILED CACHE)
    if(CMAKE_${lang}_ABI_COMPILED AND _copy_error)
      set(CMAKE_${lang}_ABI_COMPILED 0)
    endif()
    set(CMAKE_${lang}_ABI_COMPILED ${CMAKE_${lang}_ABI_COMPILED} PARENT_SCOPE)

    # Load the resulting information strings.
    if(CMAKE_${lang}_ABI_COMPILED)
      message(CHECK_PASS "done")
      if(CMAKE_HOST_APPLE AND CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES "\\$")
        file(READ_MACHO "${BIN}" ARCHITECTURES archs CAPTURE_ERROR macho_error) # undocumented file() subcommand
        if (NOT macho_error)
          # sort and prune the list of found architectures
          set(arch_list_sorted ${archs})
          list(SORT arch_list_sorted)
          list(REMOVE_DUPLICATES arch_list_sorted)
          # sort and prune the list of requested architectures
          set(requested_arch_list ${CMAKE_OSX_ARCHITECTURES})
          list(SORT requested_arch_list)
          list(REMOVE_DUPLICATES requested_arch_list)
          message(CONFIGURE_LOG
            "Effective list of requested architectures (possibly empty)  : \"${requested_arch_list}\"\n"
            "Effective list of architectures found in the ABI info binary: \"${arch_list_sorted}\"\n")
          # If all generated architectures were known to READ_MACHO (i.e. libmacho):
          # Compare requested and found:
          # - if no architecture(s) were requested explicitly, just check if READ_MACHO returned
          #   an architecture for the ABI info binary.
          # - otherwise, check if the requested and found lists are equal
          if(arch_list_sorted MATCHES "unknown")
            # Rare but not impossible: a host with a toolchain capable of generating binaries with
            # architectures that the system libmacho is too old to know. Report the found archs as
            # usual, warn about the unknowns and skip the comparison with CMAKE_OSX_ARCHITECTURES.
            message(WARNING "The ${lang} compiler generates universal binaries with at least 1 architecture not known to the host")
          elseif(requested_arch_list AND arch_list_sorted
              AND NOT "${requested_arch_list}" STREQUAL "${arch_list_sorted}")
            # inform the user of the mismatch but show the raw input and output lists
            message(FATAL_ERROR
              "The ${lang} compiler targets architectures:\n"
              "  \"${archs}\"\n"
              "but CMAKE_OSX_ARCHITECTURES is\n"
              "  \"${CMAKE_OSX_ARCHITECTURES}\"\n")
          endif()
        endif()
      endif()
      cmake_policy(PUSH)
      cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>
      file(STRINGS "${BIN}" ABI_STRINGS LIMIT_COUNT 32 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
      cmake_policy(POP)
      set(ABI_SIZEOF_DPTR "NOTFOUND")
      set(ABI_BYTE_ORDER "NOTFOUND")
      set(ABI_NAME "NOTFOUND")
      foreach(info ${ABI_STRINGS})
        if("${info}" MATCHES "INFO:sizeof_dptr\\[0*([^]]*)\\]" AND NOT ABI_SIZEOF_DPTR)
          set(ABI_SIZEOF_DPTR "${CMAKE_MATCH_1}")
        endif()
        if("${info}" MATCHES "INFO:byte_order\\[(BIG_ENDIAN|LITTLE_ENDIAN)\\]")
          set(byte_order "${CMAKE_MATCH_1}")
          if(ABI_BYTE_ORDER STREQUAL "NOTFOUND")
            # Tentatively use the value because this is the first occurrence.
            set(ABI_BYTE_ORDER "${byte_order}")
          elseif(NOT ABI_BYTE_ORDER STREQUAL "${byte_order}")
            # Drop value because multiple occurrences do not match.
            set(ABI_BYTE_ORDER "")
          endif()
        endif()
        if("${info}" MATCHES "INFO:abi\\[([^]]*)\\]" AND NOT ABI_NAME)
          set(ABI_NAME "${CMAKE_MATCH_1}")
        endif()
      endforeach()

      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)
      endif()

      if(ABI_BYTE_ORDER)
        set(CMAKE_${lang}_BYTE_ORDER "${ABI_BYTE_ORDER}" PARENT_SCOPE)
      endif()

      if(ABI_NAME)
        set(CMAKE_${lang}_COMPILER_ABI "${ABI_NAME}" PARENT_SCOPE)
      endif()

      # Parse implicit include directory for this language, if available.
      if(CMAKE_${lang}_VERBOSE_FLAG)
        set (implicit_incdirs "")
        cmake_parse_implicit_include_info("${OUTPUT}" "${lang}"
          implicit_incdirs log rv)
        message(CONFIGURE_LOG
          "Parsed ${lang} implicit include dir info: rv=${rv}\n${log}\n\n")
        if("${rv}" STREQUAL "done")
          # 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()

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

      if(_CMAKE_${lang}_IMPLICIT_LINK_INFORMATION_DETERMINED_EARLY)
        # Use implicit linker information detected during compiler id step.
        set(implicit_dirs "${CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES}")
        set(implicit_objs "")
        set(implicit_libs "${CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES}")
        set(implicit_fwks "${CMAKE_${lang}_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES}")
      else()
      # Parse implicit linker information for this language, if available.
      set(implicit_dirs "")
      set(implicit_objs "")
      set(implicit_libs "")
      set(implicit_fwks "")
      set(compute_artifacts COMPUTE_LINKER linker_tool)
      if(CMAKE_${lang}_VERBOSE_FLAG)
        list(APPEND compute_artifacts COMPUTE_IMPLICIT_LIBS implicit_libs
                                      COMPUTE_IMPLICIT_DIRS implicit_dirs
                                      COMPUTE_IMPLICIT_FWKS implicit_fwks
                                      COMPUTE_IMPLICIT_OBJECTS implicit_objs)
      endif()
      cmake_parse_implicit_link_info2("${OUTPUT}" log "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}"
        ${compute_artifacts} LANGUAGE ${lang})
      message(CONFIGURE_LOG
          "Parsed ${lang} implicit link information:\n${log}\n\n")
      # for VS IDE Intel Fortran we have to figure out the
      # implicit link path for the fortran run time using
      # a try-compile
      if("${lang}" MATCHES "Fortran"
          AND "${CMAKE_GENERATOR}" MATCHES "Visual Studio")
        message(CHECK_START "Determine Intel Fortran Compiler Implicit Link Path")
        # Build a sample project which reports symbols.
        try_compile(IFORT_LIB_PATH_COMPILED
          PROJECT IntelFortranImplicit
          SOURCE_DIR ${CMAKE_ROOT}/Modules/IntelVSImplicitPath
          BINARY_DIR ${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath
          CMAKE_FLAGS
          "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}"
          OUTPUT_VARIABLE _output)
        file(WRITE
          "${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath/output.txt"
          "${_output}")
        include(${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath/output.cmake OPTIONAL)
        message(CHECK_PASS "done")
      endif()
      endif()

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

      if(DEFINED ENV{CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES_EXCLUDE})
        list(REMOVE_ITEM implicit_dirs $ENV{CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES_EXCLUDE})
      endif()

      set(CMAKE_${lang}_COMPILER_LINKER "${linker_tool}" PARENT_SCOPE)
      cmake_determine_linker_id(${lang} "${linker_tool}")
      set(CMAKE_${lang}_COMPILER_LINKER_ID "${CMAKE_${lang}_COMPILER_LINKER_ID}" PARENT_SCOPE)
      set(CMAKE_${lang}_COMPILER_LINKER_VERSION ${CMAKE_${lang}_COMPILER_LINKER_VERSION} PARENT_SCOPE)
      set(CMAKE_${lang}_COMPILER_LINKER_FRONTEND_VARIANT ${CMAKE_${lang}_COMPILER_LINKER_FRONTEND_VARIANT} PARENT_SCOPE)

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

      cmake_parse_library_architecture(${lang} "${implicit_dirs}" "${implicit_objs}" architecture_flag)
      if(architecture_flag)
        set(CMAKE_${lang}_LIBRARY_ARCHITECTURE "${architecture_flag}" PARENT_SCOPE)
      endif()

    else()
      message(CHECK_FAIL "failed")
    endif()
  endif()
endfunction()