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.

1267 lines
37KB

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