old.configure 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
  2. # This Source Code Form is subject to the terms of the Mozilla Public
  3. # License, v. 2.0. If a copy of the MPL was not distributed with this
  4. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  5. @imports('codecs')
  6. @imports('sys')
  7. def encoded_open(path, mode):
  8. encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
  9. return codecs.open(path, mode, encoding)
  10. option(env='AUTOCONF', nargs=1, help='Path to autoconf 2.13')
  11. @depends(mozconfig, 'AUTOCONF')
  12. @checking('for autoconf')
  13. @imports(_from='os.path', _import='exists')
  14. @imports('re')
  15. def autoconf(mozconfig, autoconf):
  16. mozconfig_autoconf = None
  17. if mozconfig['path']:
  18. make_extra = mozconfig['make_extra']
  19. if make_extra:
  20. for assignment in make_extra:
  21. m = re.match('(?:export\s+)?AUTOCONF\s*:?=\s*(.+)$',
  22. assignment)
  23. if m:
  24. mozconfig_autoconf = m.group(1)
  25. autoconf = autoconf[0] if autoconf else None
  26. for ac in (mozconfig_autoconf, autoconf, 'autoconf-2.13', 'autoconf2.13',
  27. 'autoconf213'):
  28. if ac:
  29. autoconf = find_program(ac)
  30. if autoconf:
  31. break
  32. else:
  33. fink = find_program('fink')
  34. if fink:
  35. autoconf = os.path.normpath(os.path.join(
  36. fink, '..', '..', 'lib', 'autoconf2.13', 'bin', 'autoconf'))
  37. else:
  38. brew = find_program('brew')
  39. if brew:
  40. autoconf = os.path.normpath(os.path.join(
  41. brew, '..', '..', 'Cellar', 'autoconf213', '2.13', 'bin',
  42. 'autoconf213'))
  43. if not autoconf:
  44. die('Could not find autoconf 2.13')
  45. if not exists(autoconf):
  46. die('Could not find autoconf 2.13 at %s', autoconf)
  47. return autoconf
  48. set_config('AUTOCONF', autoconf)
  49. @depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell,
  50. old_configure_assignments, build_project)
  51. @imports(_from='__builtin__', _import='open')
  52. @imports(_from='__builtin__', _import='print')
  53. @imports('glob')
  54. @imports('itertools')
  55. @imports('subprocess')
  56. # Import getmtime without overwriting the sandbox os.path.
  57. @imports(_from='os.path', _import='getmtime')
  58. @imports(_from='os.path', _import='exists')
  59. @imports(_from='mozbuild.shellutil', _import='quote')
  60. def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
  61. old_configure_assignments, build_project):
  62. # os.path.abspath in the sandbox will ensure forward slashes on Windows,
  63. # which is actually necessary because this path actually ends up literally
  64. # as $0, and backslashes there breaks autoconf's detection of the source
  65. # directory.
  66. old_configure = os.path.abspath(old_configure[0])
  67. if build_project == 'js':
  68. old_configure_dir = os.path.dirname(old_configure)
  69. if not old_configure_dir.endswith('/js/src'):
  70. old_configure = os.path.join(old_configure_dir, 'js', 'src',
  71. os.path.basename(old_configure))
  72. refresh = True
  73. if exists(old_configure):
  74. mtime = getmtime(old_configure)
  75. aclocal = os.path.join(build_env.topsrcdir, 'build', 'autoconf',
  76. '*.m4')
  77. for input in itertools.chain(
  78. (old_configure + '.in',
  79. os.path.join(os.path.dirname(old_configure), 'aclocal.m4')),
  80. glob.iglob(aclocal),
  81. ):
  82. if getmtime(input) > mtime:
  83. break
  84. else:
  85. refresh = False
  86. if refresh:
  87. log.info('Refreshing %s with %s', old_configure, autoconf)
  88. script = subprocess.check_output([
  89. shell, autoconf,
  90. '--localdir=%s' % os.path.dirname(old_configure),
  91. old_configure + '.in'])
  92. # Make old-configure append to config.log, where we put our own log.
  93. # This could be done with a m4 macro, but it's way easier this way
  94. script = script.replace('>./config.log', '>>./config.log')
  95. with open(old_configure, 'wb') as fh:
  96. fh.write(script)
  97. cmd = [shell, old_configure]
  98. with encoded_open('old-configure.vars', 'w') as out:
  99. log.debug('Injecting the following to old-configure:')
  100. def inject(command):
  101. print(command, file=out)
  102. log.debug('| %s', command)
  103. if mozconfig['path']:
  104. for key, value in mozconfig['vars']['added'].items():
  105. inject("%s=%s" % (key, quote(value)))
  106. for key, (old, value) in mozconfig['vars']['modified'].items():
  107. inject("%s=%s" % (key, quote(value)))
  108. for t in ('env', 'vars'):
  109. for key in mozconfig[t]['removed'].keys():
  110. inject("unset %s" % key)
  111. # Autoconf is special, because it might be passed from
  112. # mozconfig['make_extra'], which we don't pass automatically above.
  113. inject('export AUTOCONF=%s' % quote(autoconf))
  114. for assignment in old_configure_assignments:
  115. inject(assignment)
  116. return cmd
  117. @template
  118. def old_configure_options(*options):
  119. for opt in options:
  120. option(opt, nargs='*', help='Help missing for old configure options')
  121. @dependable
  122. def all_options():
  123. return list(options)
  124. return depends(prepare_configure, extra_old_configure_args, all_options,
  125. *options)
  126. @old_configure_options(
  127. '--cache-file',
  128. '--datadir',
  129. '--enable-accessibility',
  130. '--enable-address-sanitizer',
  131. '--enable-alsa',
  132. '--enable-av1',
  133. '--enable-b2g-bt',
  134. '--enable-b2g-camera',
  135. '--enable-b2g-ril',
  136. '--enable-bundled-fonts',
  137. '--enable-chrome-compression',
  138. '--enable-chrome-format',
  139. '--enable-clang-plugin',
  140. '--enable-content-sandbox',
  141. '--enable-cookies',
  142. '--enable-cpp-rtti',
  143. '--enable-crashreporter',
  144. '--enable-dbm',
  145. '--enable-dbus',
  146. '--enable-debug-js-modules',
  147. '--enable-jetpack',
  148. '--enable-devtools-server',
  149. '--enable-devtools',
  150. '--enable-directshow',
  151. '--enable-dtrace',
  152. '--enable-dump-painting',
  153. '--enable-eme',
  154. '--enable-elf-hack',
  155. '--enable-extensions',
  156. '--enable-faststripe',
  157. '--enable-feeds',
  158. '--enable-gamepad',
  159. '--enable-gconf',
  160. '--enable-gczeal',
  161. '--enable-gio',
  162. '--enable-gnomeui',
  163. '--enable-gold',
  164. '--enable-hardware-aec-ns',
  165. '--enable-icf',
  166. '--enable-install-strip',
  167. '--enable-ion',
  168. '--enable-ios-target',
  169. '--enable-jitspew',
  170. '--enable-libjpeg-turbo',
  171. '--enable-libproxy',
  172. '--enable-llvm-hacks',
  173. '--enable-logrefcnt',
  174. '--enable-maintenance-service',
  175. '--enable-memory-sanitizer',
  176. '--enable-mozril-geoloc',
  177. '--enable-necko-wifi',
  178. '--enable-negotiateauth',
  179. '--enable-nfc',
  180. '--enable-nspr-build',
  181. '--enable-official-branding',
  182. '--enable-official-vendor',
  183. '--enable-oom-breakpoint',
  184. '--enable-optimize',
  185. '--enable-parental-controls',
  186. '--enable-pie',
  187. '--enable-png-arm-neon-support',
  188. '--enable-posix-nspr-emulation',
  189. '--enable-precompiled-startupcache',
  190. '--enable-pref-extensions',
  191. '--enable-private-build',
  192. '--enable-pulseaudio',
  193. '--enable-sndio',
  194. '--enable-raw',
  195. '--enable-readline',
  196. '--enable-reflow-perf',
  197. '--enable-release',
  198. '--enable-safe-browsing',
  199. '--enable-sandbox',
  200. '--enable-security-sqlstore',
  201. '--enable-shared-media',
  202. '--enable-signmar',
  203. '--enable-simulator',
  204. '--enable-small-chunk-size',
  205. '--enable-startup-notification',
  206. '--enable-startupcache',
  207. '--enable-stdcxx-compat',
  208. '--enable-strip',
  209. '--enable-synth-pico',
  210. '--enable-system-cairo',
  211. '--enable-system-extension-dirs',
  212. '--enable-system-pixman',
  213. '--enable-tasktracer',
  214. '--enable-tests',
  215. '--enable-thread-sanitizer',
  216. '--enable-trace-logging',
  217. '--enable-ui-locale',
  218. '--enable-universalchardet',
  219. '--enable-updater',
  220. '--enable-url-classifier',
  221. '--enable-userinfo',
  222. '--enable-valgrind',
  223. '--enable-verify-mar',
  224. '--enable-webrtc',
  225. '--enable-xul',
  226. '--enable-zipwriter',
  227. '--includedir',
  228. '--libdir',
  229. '--no-create',
  230. '--prefix',
  231. '--with-android-cxx-stl',
  232. '--with-android-distribution-directory',
  233. '--with-android-max-sdk',
  234. '--with-android-min-sdk',
  235. '--with-android-sdk',
  236. '--with-app-basename',
  237. '--with-app-name',
  238. '--with-arch',
  239. '--with-branding',
  240. '--with-chrome-name',
  241. '--with-crashreporter-enable-percent',
  242. '--with-cross-lib',
  243. '--with-debug-label',
  244. '--with-default-mozilla-five-home',
  245. '--with-distribution-id',
  246. '--with-doc-include-dirs',
  247. '--with-doc-input-dirs',
  248. '--with-doc-output-dir',
  249. '--with-float-abi',
  250. '--with-fpu',
  251. '--with-ios-sdk',
  252. '--with-jitreport-granularity',
  253. '--with-macbundlename-prefix',
  254. '--with-macos-private-frameworks',
  255. '--with-macos-sdk',
  256. '--with-nspr-cflags',
  257. '--with-nspr-exec-prefix',
  258. '--with-nspr-libs',
  259. '--with-nspr-prefix',
  260. '--with-nss-exec-prefix',
  261. '--with-nss-prefix',
  262. '--with-pthreads',
  263. '--with-qemu-exe',
  264. '--with-sixgill',
  265. '--with-soft-float',
  266. '--with-system-bz2',
  267. '--with-system-jpeg',
  268. '--with-system-zlib',
  269. '--with-thumb',
  270. '--with-thumb-interwork',
  271. '--with-unify-dist',
  272. '--with-user-appdir',
  273. '--x-includes',
  274. '--x-libraries',
  275. # Below are the configure flags used by comm-central.
  276. '--enable-ldap',
  277. '--enable-mapi',
  278. '--enable-calendar',
  279. '--enable-incomplete-external-linkage',
  280. '--enable-mailnews',
  281. '--enable-mailnews-oauth2',
  282. # Below are configure flags used by Pale Moon
  283. '--disable-browser-statusbar',
  284. '--disable-sync',
  285. '--disable-personas',
  286. # Below are configure flags used by Basilisk
  287. '--disable-webextensions',
  288. )
  289. @imports(_from='__builtin__', _import='compile')
  290. @imports(_from='__builtin__', _import='open')
  291. @imports('logging')
  292. @imports('os')
  293. @imports('subprocess')
  294. @imports('sys')
  295. @imports(_from='mozbuild.shellutil', _import='quote')
  296. def old_configure(prepare_configure, extra_old_configure_args, all_options,
  297. *options):
  298. cmd = prepare_configure
  299. # old-configure only supports the options listed in @old_configure_options
  300. # so we don't need to pass it every single option we've been passed. Only
  301. # the ones that are not supported by python configure need to.
  302. cmd += [
  303. value.format(name)
  304. for name, value in zip(all_options, options)
  305. if value.origin != 'default'
  306. ]
  307. # We also pass it the options from js/moz.configure so that it can pass
  308. # them down to js/src/configure. Note this list is empty when running
  309. # js/src/configure, in which case we don't need to pass those options
  310. # to old-configure since old-configure doesn't handle them anyways.
  311. if extra_old_configure_args:
  312. cmd += extra_old_configure_args
  313. # For debugging purpose, in case it's not what we'd expect.
  314. log.debug('Running %s', quote(*cmd))
  315. # Our logging goes to config.log, the same file old.configure uses.
  316. # We can't share the handle on the file, so close it. We assume nothing
  317. # beyond this point is going to be interesting to log to config.log from
  318. # our end, so we don't make the effort to recreate a logging.FileHandler.
  319. logger = logging.getLogger('moz.configure')
  320. for handler in logger.handlers:
  321. if isinstance(handler, logging.FileHandler):
  322. handler.close()
  323. logger.removeHandler(handler)
  324. log_size = os.path.getsize('config.log')
  325. ret = subprocess.call(cmd)
  326. if ret:
  327. with log.queue_debug():
  328. with encoded_open('config.log', 'r') as fh:
  329. fh.seek(log_size)
  330. for line in fh:
  331. log.debug(line.rstrip())
  332. log.error('old-configure failed')
  333. sys.exit(ret)
  334. raw_config = {}
  335. with encoded_open('config.data', 'r') as fh:
  336. code = compile(fh.read(), 'config.data', 'exec')
  337. # Every variation of the exec() function I tried led to:
  338. # SyntaxError: unqualified exec is not allowed in function 'main' it
  339. # contains a nested function with free variables
  340. exec code in raw_config
  341. # Ensure all the flags known to old-configure appear in the
  342. # @old_configure_options above.
  343. all_options = set(all_options)
  344. for flag in raw_config['flags']:
  345. if flag not in all_options:
  346. die('Missing option in `@old_configure_options` in %s: %s',
  347. __file__, flag)
  348. # If the code execution above fails, we want to keep the file around for
  349. # debugging.
  350. os.remove('config.data')
  351. return raw_config
  352. # set_config is only available in the global namespace, not directly in
  353. # @depends functions, but we do need to enumerate the result of
  354. # old_configure, so we cheat.
  355. @imports('__sandbox__')
  356. def set_old_configure_config(name, value):
  357. __sandbox__.set_config_impl(name, value)
  358. # Same as set_old_configure_config, but for set_define.
  359. @imports('__sandbox__')
  360. def set_old_configure_define(name, value):
  361. __sandbox__.set_define_impl(name, value)
  362. @depends(old_configure)
  363. @imports('types')
  364. def post_old_configure(raw_config):
  365. for k, v in raw_config['substs']:
  366. set_old_configure_config(
  367. k[1:-1], v[1:-1] if isinstance(v, types.StringTypes) else v)
  368. for k, v in dict(raw_config['defines']).iteritems():
  369. set_old_configure_define(k[1:-1], v[1:-1])
  370. set_old_configure_config('non_global_defines',
  371. raw_config['non_global_defines'])
  372. # Assuming no other option is declared after this function, handle the
  373. # env options that were injected by mozconfig_options by creating dummy
  374. # Option instances and having the sandbox's CommandLineHelper handle
  375. # them. We only do so for options that haven't been declared so far,
  376. # which should be a proxy for the options that old-configure handles
  377. # and that we don't know anything about.
  378. @depends('--help')
  379. @imports('__sandbox__')
  380. @imports(_from='mozbuild.configure.options', _import='Option')
  381. def remaining_mozconfig_options(_):
  382. helper = __sandbox__._helper
  383. for arg in helper:
  384. if helper._origins[arg] != 'mozconfig':
  385. continue
  386. name = arg.split('=', 1)[0]
  387. if name.isupper() and name not in __sandbox__._options:
  388. option = Option(env=name, nargs='*', help=name)
  389. helper.handle(option)
  390. # Please do not add anything after remaining_mozconfig_options()