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.

1205 lines
35KB

  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # Thomas Nagy, 2005-2010 (ita)
  4. """
  5. C/C++/D configuration helpers
  6. """
  7. import os, re, shlex, sys
  8. from waflib import Build, Utils, Task, Options, Logs, Errors, Runner
  9. from waflib.TaskGen import after_method, feature
  10. from waflib.Configure import conf
  11. WAF_CONFIG_H = 'config.h'
  12. """default name for the config.h file"""
  13. DEFKEYS = 'define_key'
  14. INCKEYS = 'include_key'
  15. cfg_ver = {
  16. 'atleast-version': '>=',
  17. 'exact-version': '==',
  18. 'max-version': '<=',
  19. }
  20. SNIP_FUNCTION = '''
  21. int main(int argc, char **argv) {
  22. void *p;
  23. (void)argc; (void)argv;
  24. p=(void*)(%s);
  25. return (int)p;
  26. }
  27. '''
  28. """Code template for checking for functions"""
  29. SNIP_TYPE = '''
  30. int main(int argc, char **argv) {
  31. (void)argc; (void)argv;
  32. if ((%(type_name)s *) 0) return 0;
  33. if (sizeof (%(type_name)s)) return 0;
  34. return 1;
  35. }
  36. '''
  37. """Code template for checking for types"""
  38. SNIP_EMPTY_PROGRAM = '''
  39. int main(int argc, char **argv) {
  40. (void)argc; (void)argv;
  41. return 0;
  42. }
  43. '''
  44. SNIP_FIELD = '''
  45. int main(int argc, char **argv) {
  46. char *off;
  47. (void)argc; (void)argv;
  48. off = (char*) &((%(type_name)s*)0)->%(field_name)s;
  49. return (size_t) off < sizeof(%(type_name)s);
  50. }
  51. '''
  52. MACRO_TO_DESTOS = {
  53. '__linux__' : 'linux',
  54. '__GNU__' : 'gnu', # hurd
  55. '__FreeBSD__' : 'freebsd',
  56. '__NetBSD__' : 'netbsd',
  57. '__OpenBSD__' : 'openbsd',
  58. '__sun' : 'sunos',
  59. '__hpux' : 'hpux',
  60. '__sgi' : 'irix',
  61. '_AIX' : 'aix',
  62. '__CYGWIN__' : 'cygwin',
  63. '__MSYS__' : 'cygwin',
  64. '_UWIN' : 'uwin',
  65. '_WIN64' : 'win32',
  66. '_WIN32' : 'win32',
  67. # Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file.
  68. '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin',
  69. '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone
  70. '__QNX__' : 'qnx',
  71. '__native_client__' : 'nacl' # google native client platform
  72. }
  73. MACRO_TO_DEST_CPU = {
  74. '__x86_64__' : 'x86_64',
  75. '__amd64__' : 'x86_64',
  76. '__i386__' : 'x86',
  77. '__ia64__' : 'ia',
  78. '__mips__' : 'mips',
  79. '__sparc__' : 'sparc',
  80. '__alpha__' : 'alpha',
  81. '__aarch64__' : 'aarch64',
  82. '__thumb__' : 'thumb',
  83. '__arm__' : 'arm',
  84. '__hppa__' : 'hppa',
  85. '__powerpc__' : 'powerpc',
  86. '__ppc__' : 'powerpc',
  87. '__convex__' : 'convex',
  88. '__m68k__' : 'm68k',
  89. '__s390x__' : 's390x',
  90. '__s390__' : 's390',
  91. '__sh__' : 'sh',
  92. }
  93. @conf
  94. def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=None):
  95. """
  96. Parse the flags from the input lines, and add them to the relevant use variables::
  97. def configure(conf):
  98. conf.parse_flags('-O3', 'FOO')
  99. # conf.env.CXXFLAGS_FOO = ['-O3']
  100. # conf.env.CFLAGS_FOO = ['-O3']
  101. :param line: flags
  102. :type line: string
  103. :param uselib_store: where to add the flags
  104. :type uselib_store: string
  105. :param env: config set or conf.env by default
  106. :type env: :py:class:`waflib.ConfigSet.ConfigSet`
  107. """
  108. assert(isinstance(line, str))
  109. env = env or self.env
  110. # Issue 811 and 1371
  111. if posix is None:
  112. posix = True
  113. if '\\' in line:
  114. posix = ('\\ ' in line) or ('\\\\' in line)
  115. lex = shlex.shlex(line, posix=posix)
  116. lex.whitespace_split = True
  117. lex.commenters = ''
  118. lst = list(lex)
  119. # append_unique is not always possible
  120. # for example, apple flags may require both -arch i386 and -arch ppc
  121. app = env.append_value
  122. appu = env.append_unique
  123. uselib = uselib_store
  124. static = False
  125. while lst:
  126. x = lst.pop(0)
  127. st = x[:2]
  128. ot = x[2:]
  129. if st == '-I' or st == '/I':
  130. if not ot: ot = lst.pop(0)
  131. appu('INCLUDES_' + uselib, [ot])
  132. elif st == '-i':
  133. tmp = [x, lst.pop(0)]
  134. app('CFLAGS', tmp)
  135. app('CXXFLAGS', tmp)
  136. elif st == '-D' or (env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but..
  137. if not ot: ot = lst.pop(0)
  138. app('DEFINES_' + uselib, [ot])
  139. elif st == '-l':
  140. if not ot: ot = lst.pop(0)
  141. prefix = (force_static or static) and 'STLIB_' or 'LIB_'
  142. appu(prefix + uselib, [ot])
  143. elif st == '-L':
  144. if not ot: ot = lst.pop(0)
  145. prefix = (force_static or static) and 'STLIBPATH_' or 'LIBPATH_'
  146. appu(prefix + uselib, [ot])
  147. elif x.startswith('/LIBPATH:'):
  148. prefix = (force_static or static) and 'STLIBPATH_' or 'LIBPATH_'
  149. appu(prefix + uselib, [x.replace('/LIBPATH:', '')])
  150. elif x == '-pthread' or x.startswith('+') or x.startswith('-std'):
  151. app('CFLAGS_' + uselib, [x])
  152. app('CXXFLAGS_' + uselib, [x])
  153. app('LINKFLAGS_' + uselib, [x])
  154. elif x == '-framework':
  155. appu('FRAMEWORK_' + uselib, [lst.pop(0)])
  156. elif x.startswith('-F'):
  157. appu('FRAMEWORKPATH_' + uselib, [x[2:]])
  158. elif x == '-Wl,-rpath' or x == '-Wl,-R':
  159. app('RPATH_' + uselib, lst.pop(0).lstrip('-Wl,'))
  160. elif x.startswith('-Wl,-R,'):
  161. app('RPATH_' + uselib, x[7:])
  162. elif x.startswith('-Wl,-R'):
  163. app('RPATH_' + uselib, x[6:])
  164. elif x.startswith('-Wl,-rpath,'):
  165. app('RPATH_' + uselib, x[11:])
  166. elif x == '-Wl,-Bstatic' or x == '-Bstatic':
  167. static = True
  168. elif x == '-Wl,-Bdynamic' or x == '-Bdynamic':
  169. static = False
  170. elif x.startswith('-Wl'):
  171. app('LINKFLAGS_' + uselib, [x])
  172. elif x.startswith('-m') or x.startswith('-f') or x.startswith('-dynamic'):
  173. app('CFLAGS_' + uselib, [x])
  174. app('CXXFLAGS_' + uselib, [x])
  175. elif x.startswith('-bundle'):
  176. app('LINKFLAGS_' + uselib, [x])
  177. elif x.startswith('-undefined') or x.startswith('-Xlinker'):
  178. arg = lst.pop(0)
  179. app('LINKFLAGS_' + uselib, [x, arg])
  180. elif x.startswith('-arch') or x.startswith('-isysroot'):
  181. tmp = [x, lst.pop(0)]
  182. app('CFLAGS_' + uselib, tmp)
  183. app('CXXFLAGS_' + uselib, tmp)
  184. app('LINKFLAGS_' + uselib, tmp)
  185. elif x.endswith('.a') or x.endswith('.so') or x.endswith('.dylib') or x.endswith('.lib'):
  186. appu('LINKFLAGS_' + uselib, [x]) # not cool, #762
  187. @conf
  188. def validate_cfg(self, kw):
  189. """
  190. Search for the program *pkg-config* if missing, and validate the parameters to pass to
  191. :py:func:`waflib.Tools.c_config.exec_cfg`.
  192. :param path: the **-config program to use** (default is *pkg-config*)
  193. :type path: list of string
  194. :param msg: message to display to describe the test executed
  195. :type msg: string
  196. :param okmsg: message to display when the test is successful
  197. :type okmsg: string
  198. :param errmsg: message to display in case of error
  199. :type errmsg: string
  200. """
  201. if not 'path' in kw:
  202. if not self.env.PKGCONFIG:
  203. self.find_program('pkg-config', var='PKGCONFIG')
  204. kw['path'] = self.env.PKGCONFIG
  205. # pkg-config version
  206. if 'atleast_pkgconfig_version' in kw:
  207. if not 'msg' in kw:
  208. kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version']
  209. return
  210. if not 'okmsg' in kw:
  211. kw['okmsg'] = 'yes'
  212. if not 'errmsg' in kw:
  213. kw['errmsg'] = 'not found'
  214. if 'modversion' in kw:
  215. if not 'msg' in kw:
  216. kw['msg'] = 'Checking for %r version' % kw['modversion']
  217. return
  218. # checking for the version of a module, for the moment, one thing at a time
  219. for x in cfg_ver.keys():
  220. y = x.replace('-', '_')
  221. if y in kw:
  222. if not 'package' in kw:
  223. raise ValueError('%s requires a package' % x)
  224. if not 'msg' in kw:
  225. kw['msg'] = 'Checking for %r %s %s' % (kw['package'], cfg_ver[x], kw[y])
  226. return
  227. if not 'define_name' in kw:
  228. pkgname = kw.get('uselib_store', kw['package'].upper())
  229. kw['define_name'] = self.have_define(pkgname)
  230. if not 'uselib_store' in kw:
  231. self.undefine(kw['define_name'])
  232. if not 'msg' in kw:
  233. kw['msg'] = 'Checking for %r' % (kw['package'] or kw['path'])
  234. @conf
  235. def exec_cfg(self, kw):
  236. """
  237. Execute the program *pkg-config*:
  238. * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return
  239. * if modversion is given, then return the module version
  240. * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable
  241. :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests)
  242. :type atleast_pkgconfig_version: string
  243. :param package: package name, for example *gtk+-2.0*
  244. :type package: string
  245. :param uselib_store: if the test is successful, define HAVE\_*name*. It is also used to define *conf.env.FLAGS_name* variables.
  246. :type uselib_store: string
  247. :param modversion: if provided, return the version of the given module and define *name*\_VERSION
  248. :type modversion: string
  249. :param args: arguments to give to *package* when retrieving flags
  250. :type args: list of string
  251. :param variables: return the values of particular variables
  252. :type variables: list of string
  253. :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES)
  254. :type define_variable: dict(string: string)
  255. """
  256. path = Utils.to_list(kw['path'])
  257. def define_it():
  258. pkgname = kw.get('uselib_store', kw['package'].upper())
  259. if kw.get('global_define'):
  260. # compatibility
  261. self.define(self.have_define(kw['package']), 1, False)
  262. else:
  263. self.env.append_unique('DEFINES_%s' % pkgname, "%s=1" % self.have_define(pkgname))
  264. self.env[self.have_define(pkgname)] = 1
  265. # pkg-config version
  266. if 'atleast_pkgconfig_version' in kw:
  267. cmd = path + ['--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']]
  268. self.cmd_and_log(cmd)
  269. if not 'okmsg' in kw:
  270. kw['okmsg'] = 'yes'
  271. return
  272. # checking for the version of a module
  273. for x in cfg_ver:
  274. y = x.replace('-', '_')
  275. if y in kw:
  276. self.cmd_and_log(path + ['--%s=%s' % (x, kw[y]), kw['package']])
  277. if not 'okmsg' in kw:
  278. kw['okmsg'] = 'yes'
  279. define_it()
  280. break
  281. # retrieving the version of a module
  282. if 'modversion' in kw:
  283. version = self.cmd_and_log(path + ['--modversion', kw['modversion']]).strip()
  284. self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version)
  285. return version
  286. lst = [] + path
  287. defi = kw.get('define_variable', None)
  288. if not defi:
  289. defi = self.env.PKG_CONFIG_DEFINES or {}
  290. for key, val in defi.items():
  291. lst.append('--define-variable=%s=%s' % (key, val))
  292. static = kw.get('force_static', False)
  293. if 'args' in kw:
  294. args = Utils.to_list(kw['args'])
  295. if '--static' in args or '--static-libs' in args:
  296. static = True
  297. lst += args
  298. # tools like pkgconf expect the package argument after the -- ones -_-
  299. lst.extend(Utils.to_list(kw['package']))
  300. # retrieving variables of a module
  301. if 'variables' in kw:
  302. env = kw.get('env', self.env)
  303. uselib = kw.get('uselib_store', kw['package'].upper())
  304. vars = Utils.to_list(kw['variables'])
  305. for v in vars:
  306. val = self.cmd_and_log(lst + ['--variable=' + v]).strip()
  307. var = '%s_%s' % (uselib, v)
  308. env[var] = val
  309. if not 'okmsg' in kw:
  310. kw['okmsg'] = 'yes'
  311. return
  312. # so we assume the command-line will output flags to be parsed afterwards
  313. ret = self.cmd_and_log(lst)
  314. if not 'okmsg' in kw:
  315. kw['okmsg'] = 'yes'
  316. define_it()
  317. self.parse_flags(ret, kw.get('uselib_store', kw['package'].upper()), kw.get('env', self.env), force_static=static, posix=kw.get('posix', None))
  318. return ret
  319. @conf
  320. def check_cfg(self, *k, **kw):
  321. """
  322. Check for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc).
  323. Encapsulate the calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg`
  324. A few examples::
  325. def configure(conf):
  326. conf.load('compiler_c')
  327. conf.check_cfg(package='glib-2.0', args='--libs --cflags')
  328. conf.check_cfg(package='glib-2.0', uselib_store='GLIB', atleast_version='2.10.0',
  329. args='--cflags --libs')
  330. conf.check_cfg(package='pango')
  331. conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs'])
  332. conf.check_cfg(package='pango',
  333. args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'],
  334. msg="Checking for 'pango 0.1.0'")
  335. conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL')
  336. conf.check_cfg(path='mpicc', args='--showme:compile --showme:link',
  337. package='', uselib_store='OPEN_MPI', mandatory=False)
  338. """
  339. if k:
  340. lst = k[0].split()
  341. kw['package'] = lst[0]
  342. kw['args'] = ' '.join(lst[1:])
  343. self.validate_cfg(kw)
  344. if 'msg' in kw:
  345. self.start_msg(kw['msg'], **kw)
  346. ret = None
  347. try:
  348. ret = self.exec_cfg(kw)
  349. except self.errors.WafError:
  350. if 'errmsg' in kw:
  351. self.end_msg(kw['errmsg'], 'YELLOW', **kw)
  352. if Logs.verbose > 1:
  353. raise
  354. else:
  355. self.fatal('The configuration failed')
  356. else:
  357. if not ret:
  358. ret = True
  359. kw['success'] = ret
  360. if 'okmsg' in kw:
  361. self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw)
  362. return ret
  363. def build_fun(bld):
  364. if bld.kw['compile_filename']:
  365. node = bld.srcnode.make_node(bld.kw['compile_filename'])
  366. node.write(bld.kw['code'])
  367. o = bld(features=bld.kw['features'], source=bld.kw['compile_filename'], target='testprog')
  368. for k, v in bld.kw.items():
  369. setattr(o, k, v)
  370. if not bld.kw.get('quiet', None):
  371. bld.conf.to_log("==>\n%s\n<==" % bld.kw['code'])
  372. @conf
  373. def validate_c(self, kw):
  374. """
  375. pre-check the parameters that will be given to :py:func:`waflib.Configure.run_build`
  376. :param compiler: c or cxx (tries to guess what is best)
  377. :type compiler: string
  378. :param type: cprogram, cshlib, cstlib - not required if *features are given directly*
  379. :type type: binary to create
  380. :param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib``
  381. :type feature: list of string
  382. :param fragment: provide a piece of code for the test (default is to let the system create one)
  383. :type fragment: string
  384. :param uselib_store: define variables after the test is executed (IMPORTANT!)
  385. :type uselib_store: string
  386. :param use: parameters to use for building (just like the normal *use* keyword)
  387. :type use: list of string
  388. :param define_name: define to set when the check is over
  389. :type define_name: string
  390. :param execute: execute the resulting binary
  391. :type execute: bool
  392. :param define_ret: if execute is set to True, use the execution output in both the define and the return value
  393. :type define_ret: bool
  394. :param header_name: check for a particular header
  395. :type header_name: string
  396. :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers
  397. :type auto_add_header_name: bool
  398. """
  399. if not 'build_fun' in kw:
  400. kw['build_fun'] = build_fun
  401. if not 'env' in kw:
  402. kw['env'] = self.env.derive()
  403. env = kw['env']
  404. if not 'compiler' in kw and not 'features' in kw:
  405. kw['compiler'] = 'c'
  406. if env['CXX_NAME'] and Task.classes.get('cxx', None):
  407. kw['compiler'] = 'cxx'
  408. if not self.env['CXX']:
  409. self.fatal('a c++ compiler is required')
  410. else:
  411. if not self.env['CC']:
  412. self.fatal('a c compiler is required')
  413. if not 'compile_mode' in kw:
  414. kw['compile_mode'] = 'c'
  415. if 'cxx' in Utils.to_list(kw.get('features',[])) or kw.get('compiler', '') == 'cxx':
  416. kw['compile_mode'] = 'cxx'
  417. if not 'type' in kw:
  418. kw['type'] = 'cprogram'
  419. if not 'features' in kw:
  420. kw['features'] = [kw['compile_mode'], kw['type']] # "cprogram c"
  421. else:
  422. kw['features'] = Utils.to_list(kw['features'])
  423. if not 'compile_filename' in kw:
  424. kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '')
  425. def to_header(dct):
  426. if 'header_name' in dct:
  427. dct = Utils.to_list(dct['header_name'])
  428. return ''.join(['#include <%s>\n' % x for x in dct])
  429. return ''
  430. #OSX
  431. if 'framework_name' in kw:
  432. fwkname = kw['framework_name']
  433. if not 'uselib_store' in kw:
  434. kw['uselib_store'] = fwkname.upper()
  435. if not kw.get('no_header', False):
  436. if not 'header_name' in kw:
  437. kw['header_name'] = []
  438. fwk = '%s/%s.h' % (fwkname, fwkname)
  439. if kw.get('remove_dot_h', None):
  440. fwk = fwk[:-2]
  441. kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk]
  442. kw['msg'] = 'Checking for framework %s' % fwkname
  443. kw['framework'] = fwkname
  444. #kw['frameworkpath'] = set it yourself
  445. if 'function_name' in kw:
  446. fu = kw['function_name']
  447. if not 'msg' in kw:
  448. kw['msg'] = 'Checking for function %s' % fu
  449. kw['code'] = to_header(kw) + SNIP_FUNCTION % fu
  450. if not 'uselib_store' in kw:
  451. kw['uselib_store'] = fu.upper()
  452. if not 'define_name' in kw:
  453. kw['define_name'] = self.have_define(fu)
  454. elif 'type_name' in kw:
  455. tu = kw['type_name']
  456. if not 'header_name' in kw:
  457. kw['header_name'] = 'stdint.h'
  458. if 'field_name' in kw:
  459. field = kw['field_name']
  460. kw['code'] = to_header(kw) + SNIP_FIELD % {'type_name' : tu, 'field_name' : field}
  461. if not 'msg' in kw:
  462. kw['msg'] = 'Checking for field %s in %s' % (field, tu)
  463. if not 'define_name' in kw:
  464. kw['define_name'] = self.have_define((tu + '_' + field).upper())
  465. else:
  466. kw['code'] = to_header(kw) + SNIP_TYPE % {'type_name' : tu}
  467. if not 'msg' in kw:
  468. kw['msg'] = 'Checking for type %s' % tu
  469. if not 'define_name' in kw:
  470. kw['define_name'] = self.have_define(tu.upper())
  471. elif 'header_name' in kw:
  472. if not 'msg' in kw:
  473. kw['msg'] = 'Checking for header %s' % kw['header_name']
  474. l = Utils.to_list(kw['header_name'])
  475. assert len(l)>0, 'list of headers in header_name is empty'
  476. kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM
  477. if not 'uselib_store' in kw:
  478. kw['uselib_store'] = l[0].upper()
  479. if not 'define_name' in kw:
  480. kw['define_name'] = self.have_define(l[0])
  481. if 'lib' in kw:
  482. if not 'msg' in kw:
  483. kw['msg'] = 'Checking for library %s' % kw['lib']
  484. if not 'uselib_store' in kw:
  485. kw['uselib_store'] = kw['lib'].upper()
  486. if 'stlib' in kw:
  487. if not 'msg' in kw:
  488. kw['msg'] = 'Checking for static library %s' % kw['stlib']
  489. if not 'uselib_store' in kw:
  490. kw['uselib_store'] = kw['stlib'].upper()
  491. if 'fragment' in kw:
  492. # an additional code fragment may be provided to replace the predefined code
  493. # in custom headers
  494. kw['code'] = kw['fragment']
  495. if not 'msg' in kw:
  496. kw['msg'] = 'Checking for code snippet'
  497. if not 'errmsg' in kw:
  498. kw['errmsg'] = 'no'
  499. for (flagsname,flagstype) in (('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')):
  500. if flagsname in kw:
  501. if not 'msg' in kw:
  502. kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname])
  503. if not 'errmsg' in kw:
  504. kw['errmsg'] = 'no'
  505. if not 'execute' in kw:
  506. kw['execute'] = False
  507. if kw['execute']:
  508. kw['features'].append('test_exec')
  509. if not 'errmsg' in kw:
  510. kw['errmsg'] = 'not found'
  511. if not 'okmsg' in kw:
  512. kw['okmsg'] = 'yes'
  513. if not 'code' in kw:
  514. kw['code'] = SNIP_EMPTY_PROGRAM
  515. # if there are headers to append automatically to the next tests
  516. if self.env[INCKEYS]:
  517. kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code']
  518. if not kw.get('success'): kw['success'] = None
  519. if 'define_name' in kw:
  520. self.undefine(kw['define_name'])
  521. if not 'msg' in kw:
  522. self.fatal('missing "msg" in conf.check(...)')
  523. @conf
  524. def post_check(self, *k, **kw):
  525. "Set the variables after a test executed in :py:func:`waflib.Tools.c_config.check` was run successfully"
  526. is_success = 0
  527. if kw['execute']:
  528. if kw['success'] is not None:
  529. if kw.get('define_ret', False):
  530. is_success = kw['success']
  531. else:
  532. is_success = (kw['success'] == 0)
  533. else:
  534. is_success = (kw['success'] == 0)
  535. if 'define_name' in kw:
  536. # TODO simplify?
  537. if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw:
  538. if kw['execute'] and kw.get('define_ret', None) and isinstance(is_success, str):
  539. self.define(kw['define_name'], is_success, quote=kw.get('quote', 1))
  540. else:
  541. self.define_cond(kw['define_name'], is_success)
  542. else:
  543. self.define_cond(kw['define_name'], is_success)
  544. if 'header_name' in kw:
  545. if kw.get('auto_add_header_name', False):
  546. self.env.append_value(INCKEYS, Utils.to_list(kw['header_name']))
  547. if is_success and 'uselib_store' in kw:
  548. from waflib.Tools import ccroot
  549. # TODO see get_uselib_vars from ccroot.py
  550. _vars = set([])
  551. for x in kw['features']:
  552. if x in ccroot.USELIB_VARS:
  553. _vars |= ccroot.USELIB_VARS[x]
  554. for k in _vars:
  555. lk = k.lower()
  556. if lk in kw:
  557. val = kw[lk]
  558. # remove trailing slash
  559. if isinstance(val, str):
  560. val = val.rstrip(os.path.sep)
  561. self.env.append_unique(k + '_' + kw['uselib_store'], Utils.to_list(val))
  562. return is_success
  563. @conf
  564. def check(self, *k, **kw):
  565. """
  566. Perform a configuration test by calling :py:func:`waflib.Configure.run_build`.
  567. For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`.
  568. To force a specific compiler, pass "compiler='c'" or "compiler='cxx'" in the arguments
  569. """
  570. self.validate_c(kw)
  571. self.start_msg(kw['msg'], **kw)
  572. ret = None
  573. try:
  574. ret = self.run_build(*k, **kw)
  575. except self.errors.ConfigurationError:
  576. self.end_msg(kw['errmsg'], 'YELLOW', **kw)
  577. if Logs.verbose > 1:
  578. raise
  579. else:
  580. self.fatal('The configuration failed')
  581. else:
  582. kw['success'] = ret
  583. ret = self.post_check(*k, **kw)
  584. if not ret:
  585. self.end_msg(kw['errmsg'], 'YELLOW', **kw)
  586. self.fatal('The configuration failed %r' % ret)
  587. else:
  588. self.end_msg(self.ret_msg(kw['okmsg'], kw), **kw)
  589. return ret
  590. class test_exec(Task.Task):
  591. """
  592. A task for executing a programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`.
  593. """
  594. color = 'PINK'
  595. def run(self):
  596. if getattr(self.generator, 'rpath', None):
  597. if getattr(self.generator, 'define_ret', False):
  598. self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()])
  599. else:
  600. self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()])
  601. else:
  602. env = self.env.env or {}
  603. env.update(dict(os.environ))
  604. for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'):
  605. env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '')
  606. if getattr(self.generator, 'define_ret', False):
  607. self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env)
  608. else:
  609. self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env)
  610. @feature('test_exec')
  611. @after_method('apply_link')
  612. def test_exec_fun(self):
  613. """
  614. The feature **test_exec** is used to create a task that will to execute the binary
  615. created (link task output) during the build. The exit status will be set
  616. on the build context, so only one program may have the feature *test_exec*.
  617. This is used by configuration tests::
  618. def configure(conf):
  619. conf.check(execute=True)
  620. """
  621. self.create_task('test_exec', self.link_task.outputs[0])
  622. @conf
  623. def check_cxx(self, *k, **kw):
  624. # DO NOT USE
  625. kw['compiler'] = 'cxx'
  626. return self.check(*k, **kw)
  627. @conf
  628. def check_cc(self, *k, **kw):
  629. # DO NOT USE
  630. kw['compiler'] = 'c'
  631. return self.check(*k, **kw)
  632. @conf
  633. def define(self, key, val, quote=True):
  634. """
  635. Store a single define and its state into conf.env.DEFINES. If the value is True, False or None it is cast to 1 or 0.
  636. :param key: define name
  637. :type key: string
  638. :param val: value
  639. :type val: int or string
  640. :param quote: enclose strings in quotes (yes by default)
  641. :type quote: bool
  642. """
  643. assert key and isinstance(key, str)
  644. if val is True:
  645. val = 1
  646. elif val in (False, None):
  647. val = 0
  648. if isinstance(val, int) or isinstance(val, float):
  649. s = '%s=%s'
  650. else:
  651. s = quote and '%s="%s"' or '%s=%s'
  652. app = s % (key, str(val))
  653. ban = key + '='
  654. lst = self.env['DEFINES']
  655. for x in lst:
  656. if x.startswith(ban):
  657. lst[lst.index(x)] = app
  658. break
  659. else:
  660. self.env.append_value('DEFINES', app)
  661. self.env.append_unique(DEFKEYS, key)
  662. @conf
  663. def undefine(self, key):
  664. """
  665. Remove a define from conf.env.DEFINES
  666. :param key: define name
  667. :type key: string
  668. """
  669. assert key and isinstance(key, str)
  670. ban = key + '='
  671. lst = [x for x in self.env['DEFINES'] if not x.startswith(ban)]
  672. self.env['DEFINES'] = lst
  673. self.env.append_unique(DEFKEYS, key)
  674. @conf
  675. def define_cond(self, key, val):
  676. """
  677. Conditionally define a name::
  678. def configure(conf):
  679. conf.define_cond('A', True)
  680. # equivalent to:
  681. # if val: conf.define('A', 1)
  682. # else: conf.undefine('A')
  683. :param key: define name
  684. :type key: string
  685. :param val: value
  686. :type val: int or string
  687. """
  688. assert key and isinstance(key, str)
  689. if val:
  690. self.define(key, 1)
  691. else:
  692. self.undefine(key)
  693. @conf
  694. def is_defined(self, key):
  695. """
  696. :param key: define name
  697. :type key: string
  698. :return: True if the define is set
  699. :rtype: bool
  700. """
  701. assert key and isinstance(key, str)
  702. ban = key + '='
  703. for x in self.env['DEFINES']:
  704. if x.startswith(ban):
  705. return True
  706. return False
  707. @conf
  708. def get_define(self, key):
  709. """
  710. :param key: define name
  711. :type key: string
  712. :return: the value of a previously stored define or None if it is not set
  713. """
  714. assert key and isinstance(key, str)
  715. ban = key + '='
  716. for x in self.env['DEFINES']:
  717. if x.startswith(ban):
  718. return x[len(ban):]
  719. return None
  720. @conf
  721. def have_define(self, key):
  722. """
  723. :param key: define name
  724. :type key: string
  725. :return: the input key prefixed by *HAVE_* and substitute any invalid characters.
  726. :rtype: string
  727. """
  728. return (self.env.HAVE_PAT or 'HAVE_%s') % Utils.quote_define_name(key)
  729. @conf
  730. def write_config_header(self, configfile='', guard='', top=False, defines=True, headers=False, remove=True, define_prefix=''):
  731. """
  732. Write a configuration header containing defines and includes::
  733. def configure(cnf):
  734. cnf.define('A', 1)
  735. cnf.write_config_header('config.h')
  736. :param configfile: relative path to the file to create
  737. :type configfile: string
  738. :param guard: include guard name to add, by default it is computed from the file name
  739. :type guard: string
  740. :param top: write the configuration header from the build directory (default is from the current path)
  741. :type top: bool
  742. :param defines: add the defines (yes by default)
  743. :type defines: bool
  744. :param headers: add #include in the file
  745. :type headers: bool
  746. :param remove: remove the defines after they are added (yes by default, works like in autoconf)
  747. :type remove: bool
  748. :type define_prefix: string
  749. :param define_prefix: prefix all the defines in the file with a particular prefix
  750. """
  751. if not configfile: configfile = WAF_CONFIG_H
  752. waf_guard = guard or 'W_%s_WAF' % Utils.quote_define_name(configfile)
  753. node = top and self.bldnode or self.path.get_bld()
  754. node = node.make_node(configfile)
  755. node.parent.mkdir()
  756. lst = ['/* WARNING! All changes made to this file will be lost! */\n']
  757. lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard))
  758. lst.append(self.get_config_header(defines, headers, define_prefix=define_prefix))
  759. lst.append('\n#endif /* %s */\n' % waf_guard)
  760. node.write('\n'.join(lst))
  761. # config files are not removed on "waf clean"
  762. self.env.append_unique(Build.CFG_FILES, [node.abspath()])
  763. if remove:
  764. for key in self.env[DEFKEYS]:
  765. self.undefine(key)
  766. self.env[DEFKEYS] = []
  767. @conf
  768. def get_config_header(self, defines=True, headers=False, define_prefix=''):
  769. """
  770. Create the contents of a ``config.h`` file from the defines and includes
  771. set in conf.env.define_key / conf.env.include_key. No include guards are added.
  772. :param defines: write the defines values
  773. :type defines: bool
  774. :param headers: write the headers
  775. :type headers: bool
  776. :type define_prefix: string
  777. :param define_prefix: prefix all the defines with a particular prefix
  778. :return: the contents of a ``config.h`` file
  779. :rtype: string
  780. """
  781. lst = []
  782. if headers:
  783. for x in self.env[INCKEYS]:
  784. lst.append('#include <%s>' % x)
  785. if defines:
  786. tbl = {}
  787. for k in self.env['DEFINES']:
  788. a, _, b = k.partition('=')
  789. tbl[a] = b
  790. for k in self.env[DEFKEYS]:
  791. try:
  792. txt = '#define %s%s %s' % (define_prefix, k, tbl[k])
  793. except KeyError:
  794. txt = '/* #undef %s%s */' % (define_prefix, k)
  795. lst.append(txt)
  796. return "\n".join(lst)
  797. @conf
  798. def cc_add_flags(conf):
  799. """
  800. Add CFLAGS / CPPFLAGS from os.environ to conf.env
  801. """
  802. conf.add_os_flags('CPPFLAGS', 'CFLAGS')
  803. conf.add_os_flags('CFLAGS')
  804. @conf
  805. def cxx_add_flags(conf):
  806. """
  807. Add CXXFLAGS / CPPFLAGS from os.environ to conf.env
  808. """
  809. conf.add_os_flags('CPPFLAGS', 'CXXFLAGS')
  810. conf.add_os_flags('CXXFLAGS')
  811. @conf
  812. def link_add_flags(conf):
  813. """
  814. Add LINKFLAGS / LDFLAGS from os.environ to conf.env
  815. """
  816. conf.add_os_flags('LINKFLAGS')
  817. conf.add_os_flags('LDFLAGS')
  818. @conf
  819. def cc_load_tools(conf):
  820. """
  821. Load the c tool
  822. """
  823. if not conf.env.DEST_OS:
  824. conf.env.DEST_OS = Utils.unversioned_sys_platform()
  825. conf.load('c')
  826. @conf
  827. def cxx_load_tools(conf):
  828. """
  829. Load the cxx tool
  830. """
  831. if not conf.env.DEST_OS:
  832. conf.env.DEST_OS = Utils.unversioned_sys_platform()
  833. conf.load('cxx')
  834. @conf
  835. def get_cc_version(conf, cc, gcc=False, icc=False, clang=False):
  836. """
  837. Run the preprocessor to determine the compiler version
  838. The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env*
  839. """
  840. cmd = cc + ['-dM', '-E', '-']
  841. env = conf.env.env or None
  842. try:
  843. p = Utils.subprocess.Popen(cmd, stdin=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE, env=env)
  844. p.stdin.write('\n'.encode())
  845. out = p.communicate()[0]
  846. except Exception:
  847. conf.fatal('Could not determine the compiler version %r' % cmd)
  848. if not isinstance(out, str):
  849. out = out.decode(sys.stdout.encoding or 'iso8859-1')
  850. if gcc:
  851. if out.find('__INTEL_COMPILER') >= 0:
  852. conf.fatal('The intel compiler pretends to be gcc')
  853. if out.find('__GNUC__') < 0 and out.find('__clang__') < 0:
  854. conf.fatal('Could not determine the compiler type')
  855. if icc and out.find('__INTEL_COMPILER') < 0:
  856. conf.fatal('Not icc/icpc')
  857. if clang and out.find('__clang__') < 0:
  858. conf.fatal('Not clang/clang++')
  859. if not clang and out.find('__clang__') >= 0:
  860. conf.fatal('Could not find g++, if renamed try eg: CXX=g++48 waf configure')
  861. k = {}
  862. if icc or gcc or clang:
  863. out = out.splitlines()
  864. for line in out:
  865. lst = shlex.split(line)
  866. if len(lst)>2:
  867. key = lst[1]
  868. val = lst[2]
  869. k[key] = val
  870. def isD(var):
  871. return var in k
  872. def isT(var):
  873. return var in k and k[var] != '0'
  874. # Some documentation is available at http://predef.sourceforge.net
  875. # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns.
  876. if not conf.env.DEST_OS:
  877. conf.env.DEST_OS = ''
  878. for i in MACRO_TO_DESTOS:
  879. if isD(i):
  880. conf.env.DEST_OS = MACRO_TO_DESTOS[i]
  881. break
  882. else:
  883. if isD('__APPLE__') and isD('__MACH__'):
  884. conf.env.DEST_OS = 'darwin'
  885. elif isD('__unix__'): # unix must be tested last as it's a generic fallback
  886. conf.env.DEST_OS = 'generic'
  887. if isD('__ELF__'):
  888. conf.env.DEST_BINFMT = 'elf'
  889. elif isD('__WINNT__') or isD('__CYGWIN__') or isD('_WIN32'):
  890. conf.env.DEST_BINFMT = 'pe'
  891. conf.env.LIBDIR = conf.env.BINDIR
  892. elif isD('__APPLE__'):
  893. conf.env.DEST_BINFMT = 'mac-o'
  894. if not conf.env.DEST_BINFMT:
  895. # Infer the binary format from the os name.
  896. conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS)
  897. for i in MACRO_TO_DEST_CPU:
  898. if isD(i):
  899. conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i]
  900. break
  901. Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')]))
  902. if icc:
  903. ver = k['__INTEL_COMPILER']
  904. conf.env['CC_VERSION'] = (ver[:-2], ver[-2], ver[-1])
  905. else:
  906. if isD('__clang__'):
  907. try:
  908. conf.env['CC_VERSION'] = (k['__clang_major__'], k['__clang_minor__'], k['__clang_patchlevel__'])
  909. except KeyError:
  910. # Some versions of OSX have a faux-gcc "clang" without clang version defines
  911. conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__'])
  912. else:
  913. try:
  914. conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__'])
  915. except KeyError:
  916. conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], 0)
  917. return k
  918. @conf
  919. def get_xlc_version(conf, cc):
  920. """Get the compiler version"""
  921. cmd = cc + ['-qversion']
  922. try:
  923. out, err = conf.cmd_and_log(cmd, output=0)
  924. except Errors.WafError:
  925. conf.fatal('Could not find xlc %r' % cmd)
  926. # the intention is to catch the 8.0 in "IBM XL C/C++ Enterprise Edition V8.0 for AIX..."
  927. for v in (r"IBM XL C/C\+\+.* V(?P<major>\d*)\.(?P<minor>\d*)",):
  928. version_re = re.compile(v, re.I).search
  929. match = version_re(out or err)
  930. if match:
  931. k = match.groupdict()
  932. conf.env['CC_VERSION'] = (k['major'], k['minor'])
  933. break
  934. else:
  935. conf.fatal('Could not determine the XLC version.')
  936. @conf
  937. def get_suncc_version(conf, cc):
  938. """Get the compiler version"""
  939. cmd = cc + ['-V']
  940. try:
  941. out, err = conf.cmd_and_log(cmd, output=0)
  942. except Errors.WafError as e:
  943. # Older versions of the compiler exit with non-zero status when reporting their version
  944. if not (hasattr(e, 'returncode') and hasattr(e, 'stdout') and hasattr(e, 'stderr')):
  945. conf.fatal('Could not find suncc %r' % cmd)
  946. out = e.stdout
  947. err = e.stderr
  948. version = (out or err)
  949. version = version.splitlines()[0]
  950. version_re = re.compile(r'cc:\s+sun\s+(c\+\+|c)\s+(?P<major>\d*)\.(?P<minor>\d*)', re.I).search
  951. match = version_re(version)
  952. if match:
  953. k = match.groupdict()
  954. conf.env['CC_VERSION'] = (k['major'], k['minor'])
  955. else:
  956. conf.fatal('Could not determine the suncc version.')
  957. # ============ the --as-needed flag should added during the configuration, not at runtime =========
  958. @conf
  959. def add_as_needed(self):
  960. """
  961. Add ``--as-needed`` to the *LINKFLAGS*
  962. On some platforms, it is a default flag. In some cases (e.g., in NS-3) it is necessary to explicitly disable this feature with `-Wl,--no-as-needed` flag.
  963. """
  964. if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME):
  965. self.env.append_unique('LINKFLAGS', '-Wl,--as-needed')
  966. # ============ parallel configuration
  967. class cfgtask(Task.TaskBase):
  968. """
  969. A task that executes configuration tests
  970. make sure that the checks write to conf.env in a thread-safe manner
  971. for the moment it only executes conf.check
  972. """
  973. def display(self):
  974. return ''
  975. def runnable_status(self):
  976. return Task.RUN_ME
  977. def uid(self):
  978. return Utils.SIG_NIL
  979. def run(self):
  980. conf = self.conf
  981. bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath())
  982. bld.env = conf.env
  983. bld.init_dirs()
  984. bld.in_msg = 1 # suppress top-level start_msg
  985. bld.logger = self.logger
  986. try:
  987. bld.check(**self.args)
  988. except Exception:
  989. return 1
  990. @conf
  991. def multicheck(self, *k, **kw):
  992. """
  993. Use tuples to perform parallel configuration tests
  994. """
  995. self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k)), **kw)
  996. class par(object):
  997. def __init__(self):
  998. self.keep = False
  999. self.returned_tasks = []
  1000. self.task_sigs = {}
  1001. def total(self):
  1002. return len(tasks)
  1003. def to_log(self, *k, **kw):
  1004. return
  1005. bld = par()
  1006. tasks = []
  1007. for dct in k:
  1008. x = cfgtask(bld=bld)
  1009. tasks.append(x)
  1010. x.args = dct
  1011. x.bld = bld
  1012. x.conf = self
  1013. x.args = dct
  1014. # bind a logger that will keep the info in memory
  1015. x.logger = Logs.make_mem_logger(str(id(x)), self.logger)
  1016. def it():
  1017. yield tasks
  1018. while 1:
  1019. yield []
  1020. p = Runner.Parallel(bld, Options.options.jobs)
  1021. p.biter = it()
  1022. p.start()
  1023. # flush the logs in order into the config.log
  1024. for x in tasks:
  1025. x.logger.memhandler.flush()
  1026. for x in tasks:
  1027. if x.hasrun != Task.SUCCESS:
  1028. self.end_msg(kw.get('errmsg', 'no'), color='YELLOW', **kw)
  1029. self.fatal(kw.get('fatalmsg', None) or 'One of the tests has failed, see the config.log for more information')
  1030. self.end_msg('ok', **kw)