3 # Thomas Nagy, 2016-2018 (ita)
6 Various configuration tests.
9 from waflib
import Task
10 from waflib
.Configure
import conf
11 from waflib
.TaskGen
import feature
, before_method
, after_method
15 #define testEXPORT __declspec(dllexport)
19 testEXPORT int lib_func(void) { return 9; }
24 #define testEXPORT __declspec(dllimport)
28 testEXPORT int lib_func(void);
29 int main(int argc, char **argv) {
30 (void)argc; (void)argv;
31 return !(lib_func() == 9);
35 @feature('link_lib_test')
36 @before_method('process_source')
37 def link_lib_test_fun(self
):
39 The configuration test :py:func:`waflib.Configure.run_build` declares a unique task generator,
40 so we need to create other task generators from here to check if the linker is able to link libraries.
42 def write_test_file(task
):
43 task
.outputs
[0].write(task
.generator
.code
)
46 if getattr(self
, 'add_rpath', False):
47 rpath
= [self
.bld
.path
.get_bld().abspath()]
50 m
= '%s %s' % (mode
, mode
)
51 ex
= self
.test_exec
and 'test_exec' or ''
53 bld(rule
=write_test_file
, target
='test.' + mode
, code
=LIB_CODE
)
54 bld(rule
=write_test_file
, target
='main.' + mode
, code
=MAIN_CODE
)
55 bld(features
='%sshlib' % m
, source
='test.' + mode
, target
='test')
56 bld(features
='%sprogram %s' % (m
, ex
), source
='main.' + mode
, target
='app', use
='test', rpath
=rpath
)
59 def check_library(self
, mode
=None, test_exec
=True):
61 Checks if libraries can be linked with the current linker. Uses :py:func:`waflib.Tools.c_tests.link_lib_test_fun`.
63 :param mode: c or cxx or d
71 compile_filename
= [],
72 features
= 'link_lib_test',
73 msg
= 'Checking for libraries',
75 test_exec
= test_exec
)
77 ########################################################################################
81 static %s foo_t static_foo () {return 0; }
86 INLINE_VALUES
= ['inline', '__inline__', '__inline']
89 def check_inline(self
, **kw
):
91 Checks for the right value for inline macro.
92 Define INLINE_MACRO to 1 if the define is found.
93 If the inline macro is not 'inline', add a define to the ``config.h`` (#define inline __inline__)
95 :param define_name: define INLINE_MACRO by default to 1 if the macro is defined
96 :type define_name: string
97 :param features: by default *c* or *cxx* depending on the compiler present
98 :type features: list of string
100 self
.start_msg('Checking for inline')
102 if not 'define_name' in kw
:
103 kw
['define_name'] = 'INLINE_MACRO'
104 if not 'features' in kw
:
106 kw
['features'] = ['cxx']
108 kw
['features'] = ['c']
110 for x
in INLINE_VALUES
:
111 kw
['fragment'] = INLINE_CODE
% (x
, x
)
115 except self
.errors
.ConfigurationError
:
120 self
.define('inline', x
, quote
=False)
122 self
.fatal('could not use inline functions')
124 ########################################################################################
126 LARGE_FRAGMENT
= '''#include <unistd.h>
127 int main(int argc, char **argv) {
128 (void)argc; (void)argv;
129 return !(sizeof(off_t) >= 8);
134 def check_large_file(self
, **kw
):
136 Checks for large file support and define the macro HAVE_LARGEFILE
137 The test is skipped on win32 systems (DEST_BINFMT == pe).
139 :param define_name: define to set, by default *HAVE_LARGEFILE*
140 :type define_name: string
141 :param execute: execute the test (yes by default)
144 if not 'define_name' in kw
:
145 kw
['define_name'] = 'HAVE_LARGEFILE'
146 if not 'execute' in kw
:
149 if not 'features' in kw
:
151 kw
['features'] = ['cxx', 'cxxprogram']
153 kw
['features'] = ['c', 'cprogram']
155 kw
['fragment'] = LARGE_FRAGMENT
157 kw
['msg'] = 'Checking for large file support'
160 if self
.env
.DEST_BINFMT
!= 'pe':
161 ret
= self
.check(**kw
)
162 except self
.errors
.ConfigurationError
:
168 kw
['msg'] = 'Checking for -D_FILE_OFFSET_BITS=64'
169 kw
['defines'] = ['_FILE_OFFSET_BITS=64']
171 ret
= self
.check(**kw
)
172 except self
.errors
.ConfigurationError
:
175 self
.define('_FILE_OFFSET_BITS', 64)
178 self
.fatal('There is no support for large files')
180 ########################################################################################
182 ENDIAN_FRAGMENT
= '''
183 short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
184 short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
185 int use_ascii (int i) {
186 return ascii_mm[i] + ascii_ii[i];
188 short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
189 short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
190 int use_ebcdic (int i) {
191 return ebcdic_mm[i] + ebcdic_ii[i];
196 class grep_for_endianness(Task
.Task
):
198 Task that reads a binary and tries to determine the endianness
202 txt
= self
.inputs
[0].read(flags
='rb').decode('latin-1')
203 if txt
.find('LiTTleEnDian') > -1:
204 self
.generator
.tmp
.append('little')
205 elif txt
.find('BIGenDianSyS') > -1:
206 self
.generator
.tmp
.append('big')
210 @feature('grep_for_endianness')
211 @after_method('process_source')
212 def grep_for_endianness_fun(self
):
214 Used by the endianness configuration test
216 self
.create_task('grep_for_endianness', self
.compiled_tasks
[0].outputs
[0])
219 def check_endianness(self
):
221 Executes a configuration test to determine the endianness
226 self
.check(fragment
=ENDIAN_FRAGMENT
, features
='c grep_for_endianness',
227 msg
='Checking for endianness', define
='ENDIANNESS', tmp
=tmp
, okmsg
=check_msg
)