1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5TestBigEndian
6-------------
7
8.. deprecated:: 3.20
9
10  Supserseded by the :variable:`CMAKE_<LANG>_BYTE_ORDER` variable.
11
12Check if the target architecture is big endian or little endian.
13
14.. command:: test_big_endian
15
16  .. code-block:: cmake
17
18    test_big_endian(<var>)
19
20  Stores in variable ``<var>`` either 1 or 0 indicating whether the
21  target architecture is big or little endian.
22
23#]=======================================================================]
24include_guard()
25
26include(CheckTypeSize)
27
28function(TEST_BIG_ENDIAN VARIABLE)
29  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);")
30    set(order "${CMAKE_MATCH_1}")
31    if(order STREQUAL "BIG_ENDIAN")
32      set("${VARIABLE}" 1 PARENT_SCOPE)
33    else()
34      set("${VARIABLE}" 0 PARENT_SCOPE)
35    endif()
36  else()
37    __TEST_BIG_ENDIAN_LEGACY_IMPL(is_big)
38    set("${VARIABLE}" "${is_big}" PARENT_SCOPE)
39  endif()
40endfunction()
41
42macro(__TEST_BIG_ENDIAN_LEGACY_IMPL VARIABLE)
43  if(NOT DEFINED HAVE_${VARIABLE})
44    message(CHECK_START "Check if the system is big endian")
45    message(CHECK_START "Searching 16 bit integer")
46
47    if(CMAKE_C_COMPILER_LOADED)
48      set(_test_language "C")
49    elseif(CMAKE_CXX_COMPILER_LOADED)
50      set(_test_language "CXX")
51    else()
52      message(FATAL_ERROR "TEST_BIG_ENDIAN needs either C or CXX language enabled")
53    endif()
54
55    CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT LANGUAGE ${_test_language})
56    if(CMAKE_SIZEOF_UNSIGNED_SHORT EQUAL 2)
57      message(CHECK_PASS "Using unsigned short")
58      set(CMAKE_16BIT_TYPE "unsigned short")
59    else()
60      CHECK_TYPE_SIZE("unsigned int"   CMAKE_SIZEOF_UNSIGNED_INT LANGUAGE ${_test_language})
61      if(CMAKE_SIZEOF_UNSIGNED_INT)
62        message(CHECK_PASS "Using unsigned int")
63        set(CMAKE_16BIT_TYPE "unsigned int")
64
65      else()
66
67        CHECK_TYPE_SIZE("unsigned long"  CMAKE_SIZEOF_UNSIGNED_LONG LANGUAGE ${_test_language})
68        if(CMAKE_SIZEOF_UNSIGNED_LONG)
69          message(CHECK_PASS "Using unsigned long")
70          set(CMAKE_16BIT_TYPE "unsigned long")
71        else()
72          message(FATAL_ERROR "no suitable type found")
73        endif()
74
75      endif()
76
77    endif()
78
79    if(_test_language STREQUAL "CXX")
80      set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.cpp")
81    else()
82      set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c")
83    endif()
84
85    configure_file("${CMAKE_ROOT}/Modules/TestEndianess.c.in"
86                   ${_test_file}
87                   @ONLY)
88
89     file(READ ${_test_file} TEST_ENDIANESS_FILE_CONTENT)
90
91     try_compile(HAVE_${VARIABLE}
92      "${CMAKE_BINARY_DIR}"
93      ${_test_file}
94      OUTPUT_VARIABLE OUTPUT
95      COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin" )
96
97      if(HAVE_${VARIABLE})
98
99        file(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin"
100            CMAKE_TEST_ENDIANESS_STRINGS_LE LIMIT_COUNT 1 REGEX "THIS IS LITTLE ENDIAN")
101
102        file(STRINGS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin"
103            CMAKE_TEST_ENDIANESS_STRINGS_BE LIMIT_COUNT 1 REGEX "THIS IS BIG ENDIAN")
104
105        # on mac, if there are universal binaries built both will be true
106        # return the result depending on the machine on which cmake runs
107        if(CMAKE_TEST_ENDIANESS_STRINGS_BE  AND  CMAKE_TEST_ENDIANESS_STRINGS_LE)
108          if(CMAKE_SYSTEM_PROCESSOR MATCHES powerpc)
109            set(CMAKE_TEST_ENDIANESS_STRINGS_BE TRUE)
110            set(CMAKE_TEST_ENDIANESS_STRINGS_LE FALSE)
111          else()
112            set(CMAKE_TEST_ENDIANESS_STRINGS_BE FALSE)
113            set(CMAKE_TEST_ENDIANESS_STRINGS_LE TRUE)
114          endif()
115          message(STATUS "TEST_BIG_ENDIAN found different results, consider setting CMAKE_OSX_ARCHITECTURES or CMAKE_TRY_COMPILE_OSX_ARCHITECTURES to one or no architecture !")
116        endif()
117
118        if(CMAKE_TEST_ENDIANESS_STRINGS_LE)
119          set(${VARIABLE} 0 CACHE INTERNAL "Result of TEST_BIG_ENDIAN" FORCE)
120          message(CHECK_PASS "little endian")
121        endif()
122
123        if(CMAKE_TEST_ENDIANESS_STRINGS_BE)
124          set(${VARIABLE} 1 CACHE INTERNAL "Result of TEST_BIG_ENDIAN" FORCE)
125          message(CHECK_PASS "big endian")
126        endif()
127
128        if(NOT CMAKE_TEST_ENDIANESS_STRINGS_BE  AND  NOT CMAKE_TEST_ENDIANESS_STRINGS_LE)
129          message(CHECK_FAIL "TEST_BIG_ENDIAN found no result!")
130          message(SEND_ERROR "TEST_BIG_ENDIAN found no result!")
131        endif()
132
133        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
134          "Determining if the system is big endian passed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n")
135
136      else()
137        message(CHECK_FAIL "failed")
138        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
139          "Determining if the system is big endian failed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n")
140        set(${VARIABLE})
141      endif()
142  endif()
143endmacro()
144