File: TestBigEndian.cmake

package info (click to toggle)
cmake 4.2.1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 152,348 kB
  • sloc: ansic: 403,894; cpp: 303,807; sh: 4,097; python: 3,582; yacc: 3,106; lex: 1,279; f90: 538; asm: 471; lisp: 375; cs: 270; java: 266; fortran: 239; objc: 215; perl: 213; xml: 198; makefile: 108; javascript: 83; pascal: 63; tcl: 55; php: 25; ruby: 22
file content (196 lines) | stat: -rw-r--r-- 6,488 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
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.

#[=======================================================================[.rst:
TestBigEndian
-------------

.. deprecated:: 3.20

  Superseded by the :variable:`CMAKE_<LANG>_BYTE_ORDER` variable.

This module provides a command to check the endianness (byte order) of the
target architecture.

Load this module in a CMake project with:

.. code-block:: cmake

  include(TestBigEndian)

Commands
^^^^^^^^

This module provides the following command:

.. command:: test_big_endian

  Checks if the target architecture is big-endian or little-endian:

  .. code-block:: cmake

    test_big_endian(<var>)

  This command stores in variable ``<var>`` either 1 or 0 indicating whether
  the target architecture is big or little endian.

  At least one of the supported languages must be enabled in
  CMake project when using this command.

  Supported languages are ``C``, ``CXX``.

  .. versionchanged:: 3.20
    This command is now mainly a wrapper around the
    :variable:`CMAKE_<LANG>_BYTE_ORDER` where also ``OBJC``, ``OBJCXX``,
    and ``CUDA`` languages are supported.

Examples
^^^^^^^^

Example: Checking Endianness
""""""""""""""""""""""""""""

Checking endianness of the target architecture with this module and storing
the result in a CMake variable ``WORDS_BIGENDIAN``:

.. code-block:: cmake

  include(TestBigEndian)
  test_big_endian(WORDS_BIGENDIAN)

Example: Checking Endianness in New Code
""""""""""""""""""""""""""""""""""""""""

As of CMake 3.20, this module should be replaced with the
:variable:`CMAKE_<LANG>_BYTE_ORDER` variable.  For example, in a project,
where ``C`` language is one of the enabled languages:

.. code-block:: cmake

  if(CMAKE_C_BYTE_ORDER STREQUAL "BIG_ENDIAN")
    set(WORDS_BIGENDIAN TRUE)
  elseif(CMAKE_C_BYTE_ORDER STREQUAL "LITTLE_ENDIAN")
    set(WORDS_BIGENDIAN FALSE)
  else()
    set(WORDS_BIGENDIAN FALSE)
    message(WARNING "Endianness could not be determined.")
  endif()
#]=======================================================================]
include_guard()

include(CheckTypeSize)

function(TEST_BIG_ENDIAN VARIABLE)
  if(";${CMAKE_C_BYTE_ORDER};${CMAKE_CXX_BYTE_ORDER};${CMAKE_CUDA_BYTE_ORDER};${CMAKE_OBJC_BYTE_ORDER};${CMAKE_OBJCXX_BYTE_ORDER};" MATCHES ";(BIG_ENDIAN|LITTLE_ENDIAN);")
    set(order "${CMAKE_MATCH_1}")
    if(order STREQUAL "BIG_ENDIAN")
      set("${VARIABLE}" 1 PARENT_SCOPE)
    else()
      set("${VARIABLE}" 0 PARENT_SCOPE)
    endif()
  else()
    __TEST_BIG_ENDIAN_LEGACY_IMPL(is_big)
    set("${VARIABLE}" "${is_big}" PARENT_SCOPE)
  endif()
endfunction()

macro(__TEST_BIG_ENDIAN_LEGACY_IMPL VARIABLE)
  if(NOT DEFINED HAVE_${VARIABLE})
    message(CHECK_START "Check if the system is big endian")
    message(CHECK_START "Searching 16 bit integer")

    if(CMAKE_C_COMPILER_LOADED)
      set(_test_language "C")
    elseif(CMAKE_CXX_COMPILER_LOADED)
      set(_test_language "CXX")
    else()
      message(FATAL_ERROR "TEST_BIG_ENDIAN needs either C or CXX language enabled")
    endif()

    check_type_size("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT LANGUAGE ${_test_language})
    if(CMAKE_SIZEOF_UNSIGNED_SHORT EQUAL 2)
      message(CHECK_PASS "Using unsigned short")
      set(CMAKE_16BIT_TYPE "unsigned short")
    else()
      check_type_size("unsigned int"   CMAKE_SIZEOF_UNSIGNED_INT LANGUAGE ${_test_language})
      if(CMAKE_SIZEOF_UNSIGNED_INT)
        message(CHECK_PASS "Using unsigned int")
        set(CMAKE_16BIT_TYPE "unsigned int")

      else()

        check_type_size("unsigned long"  CMAKE_SIZEOF_UNSIGNED_LONG LANGUAGE ${_test_language})
        if(CMAKE_SIZEOF_UNSIGNED_LONG)
          message(CHECK_PASS "Using unsigned long")
          set(CMAKE_16BIT_TYPE "unsigned long")
        else()
          message(FATAL_ERROR "no suitable type found")
        endif()

      endif()

    endif()

    if(_test_language STREQUAL "CXX")
      set(_test_file TestEndianness.cpp)
    else()
      set(_test_file TestEndianness.c)
    endif()

    file(READ "${CMAKE_ROOT}/Modules/TestEndianness.c.in" TEST_ENDIANNESS_FILE_CONTENT)
    string(CONFIGURE "${TEST_ENDIANNESS_FILE_CONTENT}" TEST_ENDIANNESS_FILE_CONTENT @ONLY)

     try_compile(HAVE_${VARIABLE}
      SOURCE_FROM_VAR "${_test_file}" TEST_ENDIANNESS_FILE_CONTENT
      COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianness.bin" )

      if(HAVE_${VARIABLE})

        cmake_policy(PUSH)
        cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_<n>

        file(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianness.bin"
            CMAKE_TEST_ENDIANNESS_STRINGS_LE LIMIT_COUNT 1 REGEX "THIS IS LITTLE ENDIAN")

        file(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianness.bin"
            CMAKE_TEST_ENDIANNESS_STRINGS_BE LIMIT_COUNT 1 REGEX "THIS IS BIG ENDIAN")

        cmake_policy(POP)

        # on mac, if there are universal binaries built both will be true
        # return the result depending on the machine on which cmake runs
        if(CMAKE_TEST_ENDIANNESS_STRINGS_BE  AND  CMAKE_TEST_ENDIANNESS_STRINGS_LE)
          if(CMAKE_SYSTEM_PROCESSOR MATCHES powerpc)
            set(CMAKE_TEST_ENDIANNESS_STRINGS_BE TRUE)
            set(CMAKE_TEST_ENDIANNESS_STRINGS_LE FALSE)
          else()
            set(CMAKE_TEST_ENDIANNESS_STRINGS_BE FALSE)
            set(CMAKE_TEST_ENDIANNESS_STRINGS_LE TRUE)
          endif()
          message(
            STATUS
            "TEST_BIG_ENDIAN found different results, consider setting CMAKE_OSX_ARCHITECTURES or "
            "CMAKE_TRY_COMPILE_OSX_ARCHITECTURES to one or no architecture !"
          )
        endif()

        if(CMAKE_TEST_ENDIANNESS_STRINGS_LE)
          set(${VARIABLE} 0 CACHE INTERNAL "Result of TEST_BIG_ENDIAN" FORCE)
          message(CHECK_PASS "little endian")
        endif()

        if(CMAKE_TEST_ENDIANNESS_STRINGS_BE)
          set(${VARIABLE} 1 CACHE INTERNAL "Result of TEST_BIG_ENDIAN" FORCE)
          message(CHECK_PASS "big endian")
        endif()

        if(NOT CMAKE_TEST_ENDIANNESS_STRINGS_BE  AND  NOT CMAKE_TEST_ENDIANNESS_STRINGS_LE)
          message(CHECK_FAIL "TEST_BIG_ENDIAN found no result!")
          message(SEND_ERROR "TEST_BIG_ENDIAN found no result!")
        endif()
      else()
        message(CHECK_FAIL "failed")
        set(${VARIABLE})
      endif()
  endif()
endmacro()