summaryrefslogtreecommitdiff
path: root/xmake/includes/check/check_bigendian.lua
blob: 56b13487f930a2d3c8e3c368641d7730db974a3b (plain)
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
--!A cross-platform build utility based on Lua
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- Copyright (C) 2024, Xmake Open Source Community.
--
-- @author      CarbeneHu
-- @file        check_bigendian.lua
--

-- check compiler byteorder(big-endian/little-endian) add to macro definition
--
-- from https://github.com/xmake-io/xmake/issues/4843
--
-- e.g.
--
-- check_bigendian("IS_BIG_ENDIAN") => IS_BIG_ENDIAN=0
--
-- configvar_check_bigendian("IS_BIG_ENDIAN") => #define IS_BIG_ENDIAN 0
--

local check_bigendian_template = [[
#include <inttypes.h>
/* A 16 bit integer is required. */
typedef uint16_t byteorder_int16_t;

/* On a little endian machine, these 16bit ints will give "THIS IS LITTLE ENDIAN."
    On a big endian machine the characters will be exchanged pairwise. */
const byteorder_int16_t info_little[] =  {0x4854, 0x5349, 0x4920, 0x2053, 0x494c, 0x5454, 0x454c, 0x4520, 0x444e, 0x4149, 0x2e4e, 0x0000};

/* on a big endian machine, these 16bit ints will give "THIS IS BIG ENDIAN."
    On a little endian machine the characters will be exchanged pairwise. */
const byteorder_int16_t info_big[] =     {0x5448, 0x4953, 0x2049, 0x5320, 0x4249, 0x4720, 0x454e, 0x4449, 0x414e, 0x2e2e, 0x0000};

int main(int argc, char *argv[])
{
  int require = 0;
  require += info_little[argc];
  require += info_big[argc];
  (void)argv;
  return require;
}]]

local function _byteorder_binary_match(content)
  local match = content:match("THIS IS BIG ENDIAN")
  return match and true or false
end

function check_bigendian(definition, opt)
  opt = opt or {}
  local optname = opt.name or ("__" .. definition)
  interp_save_scope()
  option(optname)
      set_showmenu(false)
      add_cxxsnippets(definition, check_bigendian_template, {binary_match = _byteorder_binary_match})
      if opt.links then
          add_links(opt.links)
      end
      if opt.includes then
          add_cxxincludes(opt.includes)
      end
      if opt.languages then
          set_languages(opt.languages)
      end
      if opt.cflags then
          add_cflags(opt.cflags)
      end
      if opt.cxflags then
          add_cxflags(opt.cxflags)
      end
      if opt.defines then
          add_defines(opt.defines)
      end
      if opt.warnings then
          set_warnings(opt.warnings)
      end
      after_check(function(option)
          option:add("defines", definition .. "=" .. (option:value() and 1 or 0))
      end)
  option_end()
  interp_restore_scope()
  add_options(optname)
end

function configvar_check_bigendian(definition, opt)
  opt = opt or {}
  local optname = opt.name or ("__" .. definition)
  local defname, defval = table.unpack(definition:split('='))
  interp_save_scope()
  option(optname)
      set_showmenu(false)
      add_cxxsnippets(definition, check_bigendian_template, {binary_match = _byteorder_binary_match})
      if opt.default == nil then
          set_configvar(defname, defval or 1, { quote = false })
      end
      if opt.links then
          add_links(opt.links)
      end
      if opt.includes then
          add_cxxincludes(opt.includes)
      end
      if opt.languages then
          set_languages(opt.languages)
      end
      if opt.cflags then
          add_cflags(opt.cflags)
      end
      if opt.cxflags then
          add_cxflags(opt.cxflags)
      end
      if opt.defines then
          add_defines(opt.defines)
      end
      if opt.warnings then
          set_warnings(opt.warnings)
      end
      after_check(function(option)
          option:set("configvar", defname, option:value() and 1 or 0, { quote = false })
      end)
  option_end()
  interp_restore_scope()
  if opt.default == nil then
      add_options(optname)
  else
      set_configvar(defname, has_config(optname) and (defval or 1) or opt.default, { quote = false })
  end
end