jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
5.8KB

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