third_party:waf: update to upstream 2.0.4 release
[samba.git] / third_party / waf / waflib / Tools / c_tests.py
1 #! /usr/bin/env python
2 # encoding: utf-8
3 # WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file
4
5 #!/usr/bin/env python
6 # encoding: utf-8
7 # Thomas Nagy, 2016-2018 (ita)
8
9 """
10 Various configuration tests.
11 """
12
13 from waflib import Task
14 from waflib.Configure import conf
15 from waflib.TaskGen import feature, before_method, after_method
16
17 LIB_CODE = '''
18 #ifdef _MSC_VER
19 #define testEXPORT __declspec(dllexport)
20 #else
21 #define testEXPORT
22 #endif
23 testEXPORT int lib_func(void) { return 9; }
24 '''
25
26 MAIN_CODE = '''
27 #ifdef _MSC_VER
28 #define testEXPORT __declspec(dllimport)
29 #else
30 #define testEXPORT
31 #endif
32 testEXPORT int lib_func(void);
33 int main(int argc, char **argv) {
34         (void)argc; (void)argv;
35         return !(lib_func() == 9);
36 }
37 '''
38
39 @feature('link_lib_test')
40 @before_method('process_source')
41 def link_lib_test_fun(self):
42         """
43         The configuration test :py:func:`waflib.Configure.run_build` declares a unique task generator,
44         so we need to create other task generators from here to check if the linker is able to link libraries.
45         """
46         def write_test_file(task):
47                 task.outputs[0].write(task.generator.code)
48
49         rpath = []
50         if getattr(self, 'add_rpath', False):
51                 rpath = [self.bld.path.get_bld().abspath()]
52
53         mode = self.mode
54         m = '%s %s' % (mode, mode)
55         ex = self.test_exec and 'test_exec' or ''
56         bld = self.bld
57         bld(rule=write_test_file, target='test.' + mode, code=LIB_CODE)
58         bld(rule=write_test_file, target='main.' + mode, code=MAIN_CODE)
59         bld(features='%sshlib' % m, source='test.' + mode, target='test')
60         bld(features='%sprogram %s' % (m, ex), source='main.' + mode, target='app', use='test', rpath=rpath)
61
62 @conf
63 def check_library(self, mode=None, test_exec=True):
64         """
65         Checks if libraries can be linked with the current linker. Uses :py:func:`waflib.Tools.c_tests.link_lib_test_fun`.
66
67         :param mode: c or cxx or d
68         :type mode: string
69         """
70         if not mode:
71                 mode = 'c'
72                 if self.env.CXX:
73                         mode = 'cxx'
74         self.check(
75                 compile_filename = [],
76                 features = 'link_lib_test',
77                 msg = 'Checking for libraries',
78                 mode = mode,
79                 test_exec = test_exec)
80
81 ########################################################################################
82
83 INLINE_CODE = '''
84 typedef int foo_t;
85 static %s foo_t static_foo () {return 0; }
86 %s foo_t foo () {
87         return 0;
88 }
89 '''
90 INLINE_VALUES = ['inline', '__inline__', '__inline']
91
92 @conf
93 def check_inline(self, **kw):
94         """
95         Checks for the right value for inline macro.
96         Define INLINE_MACRO to 1 if the define is found.
97         If the inline macro is not 'inline', add a define to the ``config.h`` (#define inline __inline__)
98
99         :param define_name: define INLINE_MACRO by default to 1 if the macro is defined
100         :type define_name: string
101         :param features: by default *c* or *cxx* depending on the compiler present
102         :type features: list of string
103         """
104         self.start_msg('Checking for inline')
105
106         if not 'define_name' in kw:
107                 kw['define_name'] = 'INLINE_MACRO'
108         if not 'features' in kw:
109                 if self.env.CXX:
110                         kw['features'] = ['cxx']
111                 else:
112                         kw['features'] = ['c']
113
114         for x in INLINE_VALUES:
115                 kw['fragment'] = INLINE_CODE % (x, x)
116
117                 try:
118                         self.check(**kw)
119                 except self.errors.ConfigurationError:
120                         continue
121                 else:
122                         self.end_msg(x)
123                         if x != 'inline':
124                                 self.define('inline', x, quote=False)
125                         return x
126         self.fatal('could not use inline functions')
127
128 ########################################################################################
129
130 LARGE_FRAGMENT = '''#include <unistd.h>
131 int main(int argc, char **argv) {
132         (void)argc; (void)argv;
133         return !(sizeof(off_t) >= 8);
134 }
135 '''
136
137 @conf
138 def check_large_file(self, **kw):
139         """
140         Checks for large file support and define the macro HAVE_LARGEFILE
141         The test is skipped on win32 systems (DEST_BINFMT == pe).
142
143         :param define_name: define to set, by default *HAVE_LARGEFILE*
144         :type define_name: string
145         :param execute: execute the test (yes by default)
146         :type execute: bool
147         """
148         if not 'define_name' in kw:
149                 kw['define_name'] = 'HAVE_LARGEFILE'
150         if not 'execute' in kw:
151                 kw['execute'] = True
152
153         if not 'features' in kw:
154                 if self.env.CXX:
155                         kw['features'] = ['cxx', 'cxxprogram']
156                 else:
157                         kw['features'] = ['c', 'cprogram']
158
159         kw['fragment'] = LARGE_FRAGMENT
160
161         kw['msg'] = 'Checking for large file support'
162         ret = True
163         try:
164                 if self.env.DEST_BINFMT != 'pe':
165                         ret = self.check(**kw)
166         except self.errors.ConfigurationError:
167                 pass
168         else:
169                 if ret:
170                         return True
171
172         kw['msg'] = 'Checking for -D_FILE_OFFSET_BITS=64'
173         kw['defines'] = ['_FILE_OFFSET_BITS=64']
174         try:
175                 ret = self.check(**kw)
176         except self.errors.ConfigurationError:
177                 pass
178         else:
179                 self.define('_FILE_OFFSET_BITS', 64)
180                 return ret
181
182         self.fatal('There is no support for large files')
183
184 ########################################################################################
185
186 ENDIAN_FRAGMENT = '''
187 short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
188 short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
189 int use_ascii (int i) {
190         return ascii_mm[i] + ascii_ii[i];
191 }
192 short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
193 short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
194 int use_ebcdic (int i) {
195         return ebcdic_mm[i] + ebcdic_ii[i];
196 }
197 extern int foo;
198 '''
199
200 class grep_for_endianness(Task.Task):
201         """
202         Task that reads a binary and tries to determine the endianness
203         """
204         color = 'PINK'
205         def run(self):
206                 txt = self.inputs[0].read(flags='rb').decode('latin-1')
207                 if txt.find('LiTTleEnDian') > -1:
208                         self.generator.tmp.append('little')
209                 elif txt.find('BIGenDianSyS') > -1:
210                         self.generator.tmp.append('big')
211                 else:
212                         return -1
213
214 @feature('grep_for_endianness')
215 @after_method('process_source')
216 def grep_for_endianness_fun(self):
217         """
218         Used by the endianness configuration test
219         """
220         self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0])
221
222 @conf
223 def check_endianness(self):
224         """
225         Executes a configuration test to determine the endianness
226         """
227         tmp = []
228         def check_msg(self):
229                 return tmp[0]
230         self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness',
231                 msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, okmsg=check_msg)
232         return tmp[0]
233