forked from rizsotto/Bear
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FindC99.cmake
194 lines (166 loc) · 4.73 KB
/
FindC99.cmake
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
# - Finds C99 standard support
# This internally calls the check_c_source_compiles macro to determine the
# appropriate flags for a C99 standard compilation.
#=============================================================================
# Copyright 2013 Ian Liu Rodrigues <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#=============================================================================
include(CheckCSourceCompiles)
set(C99_C_TEST_SOURCE
"#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdio.h>
// Check varargs macros. These examples are taken from C99 6.10.3.5.
#define debug(...) fprintf (stderr, __VA_ARGS__)
#define showlist(...) puts (#__VA_ARGS__)
#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
static void
test_varargs_macros (void)
{
int x = 1234;
int y = 5678;
debug (\"Flag\");
debug (\"X = %d\\\\n\", x);
showlist (The first, second, and third items.);
report (x>y, \"x is %d but y is %d\", x, y);
}
// Check long long types.
#define BIG64 18446744073709551615ull
#define BIG32 4294967295ul
#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
#if !BIG_OK
your preprocessor is broken;
#endif
#if BIG_OK
#else
your preprocessor is broken;
#endif
static long long int bignum = -9223372036854775807LL;
static unsigned long long int ubignum = BIG64;
struct incomplete_array
{
int datasize;
double data[];
};
struct named_init {
int number;
const wchar_t *name;
double average;
};
typedef const char *ccp;
static inline int
test_restrict (ccp restrict text)
{
// See if C++-style comments work.
// Iterate through items via the restricted pointer.
// Also check for declarations in for loops.
for (unsigned int i = 0; *(text+i) != '\\\\0'; ++i)
continue;
return 0;
}
// Check varargs and va_copy.
static void
test_varargs (const char *format, ...)
{
va_list args;
va_start (args, format);
va_list args_copy;
va_copy (args_copy, args);
const char *str = NULL;
int number = 0;
float fnumber = 0.0;
while (*format)
{
switch (*format++)
{
case 's': // string
str = va_arg (args_copy, const char *);
break;
case 'd': // int
number = va_arg (args_copy, int);
break;
case 'f': // float
fnumber = va_arg (args_copy, double);
break;
default:
break;
}
}
va_end (args_copy);
va_end (args);
number = (number != 0) && (str != NULL) && (fnumber != 0.0);
}
int
main ()
{
// Check bool.
_Bool success = false;
// Check restrict.
if (test_restrict (\"String literal\") == 0)
success = true;
char *restrict newvar = \"Another string\";
// Check varargs.
test_varargs (\"s, d' f .\", \"string\", 65, 34.234);
test_varargs_macros ();
// Check flexible array members.
struct incomplete_array *ia =
malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
ia->datasize = 10;
for (int i = 0; i < ia->datasize; ++i)
ia->data[i] = i * 1.234;
// Check named initializers.
struct named_init ni = {
.number = 34,
.name = L\"Test wide string\",
.average = 543.34343,
};
ni.number = 58;
int dynamic_array[ni.number];
dynamic_array[ni.number - 1] = 543;
// work around unused variable warnings
return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
|| dynamic_array[ni.number - 1] != 543);
;
return 0;
}")
set(C99_C_FLAG_CANDIDATES
" "
"-std=c99"
"-std=gnu99"
"-c99"
"-AC99"
"-xc99=all"
"-qlanglvl=extc99"
)
if(DEFINED C99_C_FLAGS)
set(C99_C_FLAG_CANDIDATES)
endif(DEFINED C99_C_FLAGS)
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
foreach(FLAG ${C99_C_FLAG_CANDIDATES})
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
unset(C99_FLAG_DETECTED CACHE)
message(STATUS "Try C99 C flag = [${FLAG}]")
check_c_source_compiles("${C99_C_TEST_SOURCE}" C99_FLAG_DETECTED)
if(C99_FLAG_DETECTED)
set(C99_C_FLAGS_INTERNAL "${FLAG}")
break()
endif(C99_FLAG_DETECTED)
endforeach(FLAG ${C99_C_FLAG_CANDIDATES})
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
set(C99_C_FLAGS "${C99_C_FLAGS_INTERNAL}"
CACHE STRING "C compiler flags for C99 standard")
mark_as_advanced(C99_C_FLAGS)