Bug 1253203 - Move parts of configure.py into sandboxed moz.configure. r=nalexander,r=chmanchester

This moves all the reading mozconfig, finding autoconf, refreshing the
old configure, and running the old configure into sandboxed
moz.configure. This effectively bootstraps the sandboxed python configure.
This commit is contained in:
Mike Hommey
2016-03-04 17:31:10 +09:00
parent 49ce6e849d
commit c860d6f331
10 changed files with 646 additions and 287 deletions

View File

@@ -20,6 +20,15 @@ dnl MOZ_ARG_WITH_STRING( NAME, HELP, IF-SET [, ELSE])
dnl MOZ_ARG_HEADER(Comment) dnl MOZ_ARG_HEADER(Comment)
dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
define([MOZ_DIVERSION_ARGS], 12)
AC_DEFUN([MOZ_ARG],[dnl
AC_DIVERT_PUSH(MOZ_DIVERSION_ARGS)dnl
'$1',
AC_DIVERT_POP()dnl
])
AC_DEFUN([MOZ_AC_ARG_ENABLE],[MOZ_ARG([--enable-]translit([$1],[_],[-]))AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
AC_DEFUN([MOZ_AC_ARG_WITH],[MOZ_ARG([--with-]translit([$1],[_],[-]))AC_ARG_WITH([$1], [$2], [$3], [$4])])
dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE]) dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE])
AC_DEFUN([MOZ_TWO_STRING_TEST], AC_DEFUN([MOZ_TWO_STRING_TEST],
@@ -35,19 +44,19 @@ AC_DEFUN([MOZ_TWO_STRING_TEST],
dnl MOZ_ARG_ENABLE_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]]) dnl MOZ_ARG_ENABLE_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]])
AC_DEFUN([MOZ_ARG_ENABLE_BOOL], AC_DEFUN([MOZ_ARG_ENABLE_BOOL],
[AC_ARG_ENABLE([$1], [$2], [MOZ_AC_ARG_ENABLE([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4])], [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4])],
[$5])]) [$5])])
dnl MOZ_ARG_DISABLE_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]]) dnl MOZ_ARG_DISABLE_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]])
AC_DEFUN([MOZ_ARG_DISABLE_BOOL], AC_DEFUN([MOZ_ARG_DISABLE_BOOL],
[AC_ARG_ENABLE([$1], [$2], [MOZ_AC_ARG_ENABLE([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$enableval], no, [$3], yes, [$4])], [MOZ_TWO_STRING_TEST([$1], [$enableval], no, [$3], yes, [$4])],
[$5])]) [$5])])
dnl MOZ_ARG_ENABLE_STRING(NAME, HELP, IF-SET [, ELSE]) dnl MOZ_ARG_ENABLE_STRING(NAME, HELP, IF-SET [, ELSE])
AC_DEFUN([MOZ_ARG_ENABLE_STRING], AC_DEFUN([MOZ_ARG_ENABLE_STRING],
[AC_ARG_ENABLE([$1], [$2], [$3], [$4])]) [MOZ_AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
dnl MOZ_ARG_ENABLE_BOOL_OR_STRING(NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]]) dnl MOZ_ARG_ENABLE_BOOL_OR_STRING(NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING], AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING],
@@ -55,25 +64,25 @@ AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING],
[errprint([Option, $1, needs an "IF-SET" argument. [errprint([Option, $1, needs an "IF-SET" argument.
]) ])
m4exit(1)], m4exit(1)],
[AC_ARG_ENABLE([$1], [$2], [MOZ_AC_ARG_ENABLE([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4], [$5])], [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4], [$5])],
[$6])])]) [$6])])])
dnl MOZ_ARG_WITH_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]) dnl MOZ_ARG_WITH_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE])
AC_DEFUN([MOZ_ARG_WITH_BOOL], AC_DEFUN([MOZ_ARG_WITH_BOOL],
[AC_ARG_WITH([$1], [$2], [MOZ_AC_ARG_WITH([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$withval], yes, [$3], no, [$4])], [MOZ_TWO_STRING_TEST([$1], [$withval], yes, [$3], no, [$4])],
[$5])]) [$5])])
dnl MOZ_ARG_WITHOUT_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]) dnl MOZ_ARG_WITHOUT_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE])
AC_DEFUN([MOZ_ARG_WITHOUT_BOOL], AC_DEFUN([MOZ_ARG_WITHOUT_BOOL],
[AC_ARG_WITH([$1], [$2], [MOZ_AC_ARG_WITH([$1], [$2],
[MOZ_TWO_STRING_TEST([$1], [$withval], no, [$3], yes, [$4])], [MOZ_TWO_STRING_TEST([$1], [$withval], no, [$3], yes, [$4])],
[$5])]) [$5])])
dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE]) dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE])
AC_DEFUN([MOZ_ARG_WITH_STRING], AC_DEFUN([MOZ_ARG_WITH_STRING],
[AC_ARG_WITH([$1], [$2], [$3], [$4])]) [MOZ_AC_ARG_WITH([$1], [$2], [$3], [$4])])
dnl MOZ_ARG_HEADER(Comment) dnl MOZ_ARG_HEADER(Comment)
dnl This is used by webconfig to group options dnl This is used by webconfig to group options
@@ -82,42 +91,5 @@ define(MOZ_ARG_HEADER, [# $1])
dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
AC_DEFUN([MOZ_READ_MOZCONFIG], AC_DEFUN([MOZ_READ_MOZCONFIG],
[AC_REQUIRE([AC_INIT_BINSH])dnl [AC_REQUIRE([AC_INIT_BINSH])dnl
inserted= . ./old-configure.vars
dnl Shell is hard, so here is what the following does:
dnl - Reset $@ (command line arguments)
dnl - Add the configure options from mozconfig to $@ one by one
dnl - Add the original command line arguments after that, one by one
dnl
dnl There are several tricks involved:
dnl - It is not possible to preserve the whitespaces in $@ by assigning to
dnl another variable, so the two first steps above need to happen in the first
dnl iteration of the third step.
dnl - We always want the configure options to be added, so the loop must be
dnl iterated at least once, so we add a dummy argument first, and discard it.
dnl - something | while read line ... makes the while run in a subshell, meaning
dnl that anything it does is not propagated to the main shell, so we can't do
dnl set -- foo there. As a consequence, what the while loop reading mach
dnl environment output does is output a set of shell commands for the main shell
dnl to eval.
dnl - Extra care is due when lines from mach environment output contain special
dnl shell characters, so we use ' for quoting and ensure no ' end up in between
dnl the quoting mark unescaped.
dnl Some of the above is directly done in mach environment --format=configure.
failed_eval() {
echo "Failed eval'ing the following:"
$(dirname [$]0)/[$1]/mach environment --format=configure
exit 1
}
set -- dummy "[$]@"
for ac_option
do
if test -z "$inserted"; then
set --
eval "$($(dirname [$]0)/[$1]/mach environment --format=configure)" || failed_eval
inserted=1
else
set -- "[$]@" "$ac_option"
fi
done
]) ])

View File

@@ -157,6 +157,10 @@ fi
cat >> $CONFIG_STATUS <<EOF cat >> $CONFIG_STATUS <<EOF
] ]
flags = [
undivert(MOZ_DIVERSION_ARGS)dnl
]
EOF EOF
changequote([, ]) changequote([, ])

View File

@@ -0,0 +1,122 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
include('util.configure')
option(env='DIST', nargs=1, help='DIST directory')
# Do not allow objdir == srcdir builds.
# ==============================================================
@depends('--help', 'DIST')
def check_build_environment(help, dist):
topobjdir = os.path.realpath(os.path.abspath('.'))
topsrcdir = os.path.realpath(os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', '..')))
set_config('TOPSRCDIR', topsrcdir)
set_config('TOPOBJDIR', topobjdir)
set_config('MOZ_BUILD_ROOT', topobjdir)
if dist:
set_config('DIST', normsep(dist[0]))
else:
set_config('DIST', os.path.join(topobjdir, 'dist'))
if help:
return
if topsrcdir == topobjdir:
error(
' ***\n'
' * Building directly in the main source directory is not allowed.\n'
' *\n'
' * To build, you must run configure from a separate directory\n'
' * (referred to as an object directory).\n'
' *\n'
' * If you are building with a mozconfig, you will need to change your\n'
' * mozconfig to point to a different object directory.\n'
' ***'
)
# Check for a couple representative files in the source tree
conflict_files = [
'* %s' % f for f in ('Makefile', 'config/autoconf.mk')
if os.path.exists(os.path.join(topsrcdir, f))
]
if conflict_files:
error(
' ***\n'
' * Your source tree contains these files:\n'
' %s\n'
' * This indicates that you previously built in the source tree.\n'
' * A source tree build can confuse the separate objdir build.\n'
' *\n'
' * To clean up the source tree:\n'
' * 1. cd %s\n'
' * 2. gmake distclean\n'
' ***'
% ('\n '.join(conflict_files), topsrcdir)
)
option(env='MOZ_CURRENT_PROJECT', nargs=1, help='Current build project')
option(env='MOZCONFIG', nargs=1, help='Mozconfig location')
# Read user mozconfig
# ==============================================================
# Note: the dependency on --help is only there to always read the mozconfig,
# even when --help is passed. Without this dependency, the function wouldn't
# be called when --help is passed, and the mozconfig wouldn't be read.
@depends('MOZ_CURRENT_PROJECT', 'MOZCONFIG', check_build_environment, '--help')
@advanced
def mozconfig(current_project, mozconfig, build_env, help):
from mozbuild.mozconfig import MozconfigLoader
# Don't read the mozconfig for the js configure (yay backwards
# compatibility)
if build_env['TOPOBJDIR'].endswith('/js/src'):
return {'path': None}
loader = MozconfigLoader(build_env['TOPSRCDIR'])
current_project = current_project[0] if current_project else None
mozconfig = mozconfig[0] if mozconfig else None
mozconfig = loader.find_mozconfig(env={'MOZCONFIG': mozconfig})
mozconfig = loader.read_mozconfig(mozconfig, moz_build_app=current_project)
return mozconfig
@template
@advanced
def command_line_helper():
# This escapes the sandbox. Don't copy this. This is only here because
# it is a one off and because the required functionality doesn't need
# to be exposed for other usecases.
return depends.__self__._helper
@depends(mozconfig)
def mozconfig_options(mozconfig):
if mozconfig['path']:
helper = command_line_helper()
warn('Adding configure options from %s' % mozconfig['path'])
for arg in mozconfig['configure_args']:
warn(' %s' % arg)
# We could be using imply_option() here, but it has other
# contraints that don't really apply to the command-line
# emulation that mozconfig provides.
helper.add(arg, origin='mozconfig', args=helper._args)
# Ideally we'd handle mozconfig['env'] and mozconfig['vars'] here,
# but at the moment, moz.configure has no knowledge of the options
# that may appear there. We'll opt-in when we move things from
# old-configure.in, which will be tedious but necessary until we
# can discriminate what old-configure.in supports.
del command_line_helper
option(env='MOZILLABUILD', nargs=1,
help='Path to Mozilla Build (Windows-only)')

View File

@@ -0,0 +1,399 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# It feels dirty replicating this from python/mozbuild/mozbuild/mozconfig.py,
# but the end goal being that the configure script would go away...
@depends('MOZILLABUILD')
@advanced
def shell(mozillabuild):
import sys
shell = 'sh'
if mozillabuild:
shell = mozillabuild[0] + '/msys/bin/sh'
if sys.platform == 'win32':
shell = shell + '.exe'
return shell
option(env='AUTOCONF', nargs=1, help='Path to autoconf 2.13')
@depends(mozconfig, 'AUTOCONF')
@advanced
def autoconf(mozconfig, autoconf):
import re
mozconfig_autoconf = None
if mozconfig['path']:
make_extra = mozconfig['make_extra']
if make_extra:
for assignment in make_extra:
m = re.match('(?:export\s+)?AUTOCONF\s*:?=\s*(.+)$',
assignment)
if m:
mozconfig_autoconf = m.group(1)
autoconf = autoconf[0] if autoconf else None
for ac in (mozconfig_autoconf, autoconf, 'autoconf-2.13', 'autoconf2.13',
'autoconf213'):
if ac:
autoconf = find_program(ac)
if autoconf:
break
else:
fink = find_program('fink')
if find:
autoconf = os.path.normpath(os.path.join(
fink, '..', '..', 'lib', 'autoconf2.13', 'bin', 'autoconf'))
if not autoconf:
error('Could not find autoconf 2.13')
set_config('AUTOCONF', autoconf)
return autoconf
option(env='OLD_CONFIGURE', nargs=1, help='Path to the old configure script')
@depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell)
@advanced
def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell):
import glob
import itertools
import subprocess
import sys
# Import getmtime without overwriting the sandbox os.path.
from os.path import getmtime
from mozbuild.shellutil import quote
if not old_configure:
error('The OLD_CONFIGURE environment variable must be set')
# os.path.abspath in the sandbox will ensure forward slashes on Windows,
# which is actually necessary because this path actually ends up literally
# as $0, and backslashes there breaks autoconf's detection of the source
# directory.
old_configure = os.path.abspath(old_configure[0])
refresh = True
if os.path.exists(old_configure):
mtime = getmtime(old_configure)
aclocal = os.path.join(build_env['TOPSRCDIR'], 'build', 'autoconf',
'*.m4')
for input in itertools.chain(
(old_configure + '.in',
os.path.join(os.path.dirname(old_configure), 'aclocal.m4')),
glob.iglob(aclocal),
):
if getmtime(input) > mtime:
break
else:
refresh = False
if refresh:
warn('Refreshing %s with %s' % (old_configure, autoconf))
with open(old_configure, 'wb') as fh:
subprocess.check_call([
shell, autoconf,
'--localdir=%s' % os.path.dirname(old_configure),
old_configure + '.in'], stdout=fh)
cmd = [shell, old_configure] + sys.argv[1:]
with open('old-configure.vars', 'w') as out:
if mozconfig['path']:
if mozconfig['configure_args']:
cmd += mozconfig['configure_args']
for key, value in mozconfig['env']['added'].items():
print("export %s=%s" % (key, quote(value)), file=out)
for key, (old, value) in mozconfig['env']['modified'].items():
print("export %s=%s" % (key, quote(value)), file=out)
for key, value in mozconfig['vars']['added'].items():
print("%s=%s" % (key, quote(value)), file=out)
for key, (old, value) in mozconfig['vars']['modified'].items():
print("%s=%s" % (key, quote(value)), file=out)
for t in ('env', 'vars'):
for key in mozconfig[t]['removed'].keys():
print("unset %s" % key, file=out)
return cmd
@template
def old_configure_options(*options):
for opt in options:
option(opt, nargs='*', help='Help missing for old configure options')
@depends('--help')
def all_options(help):
return set(options)
return depends(prepare_configure, all_options, *options)
@old_configure_options(
'--cache-file',
'--enable-accessibility',
'--enable-address-sanitizer',
'--enable-alsa',
'--enable-android-apz',
'--enable-android-omx',
'--enable-android-resource-constrained',
'--enable-application',
'--enable-approximate-location',
'--enable-artifact-builds',
'--enable-b2g-bt',
'--enable-b2g-camera',
'--enable-b2g-ril',
'--enable-build-backend',
'--enable-bundled-fonts',
'--enable-callgrind',
'--enable-chrome-format',
'--enable-clang-plugin',
'--enable-compile-environment',
'--enable-content-sandbox',
'--enable-cookies',
'--enable-cpp-rtti',
'--enable-crashreporter',
'--enable-ctypes',
'--enable-dbm',
'--enable-dbus',
'--enable-debug',
'--enable-debug-js-modules',
'--enable-debug-symbols',
'--enable-default-toolkit',
'--enable-directshow',
'--enable-dmd',
'--enable-dtrace',
'--enable-dump-painting',
'--enable-elf-hack',
'--enable-eme',
'--enable-export-js',
'--enable-extensions',
'--enable-faststripe',
'--enable-feeds',
'--enable-ffmpeg',
'--enable-fmp4',
'--enable-gamepad',
'--enable-gc-trace',
'--enable-gconf',
'--enable-gczeal',
'--enable-gio',
'--enable-gnomeui',
'--enable-gold',
'--enable-gps-debug',
'--enable-hardware-aec-ns',
'--enable-icf',
'--enable-install-strip',
'--enable-instruments',
'--enable-ion',
'--enable-ios-target',
'--enable-ipdl-tests',
'--enable-jemalloc',
'--enable-jitspew',
'--enable-jprof',
'--enable-libjpeg-turbo',
'--enable-libproxy',
'--enable-llvm-hacks',
'--enable-logrefcnt',
'--enable-macos-target',
'--enable-maintenance-service',
'--enable-media-navigator',
'--enable-memory-sanitizer',
'--enable-mobile-optimize',
'--enable-more-deterministic',
'--enable-mozril-geoloc',
'--enable-necko-protocols',
'--enable-necko-wifi',
'--enable-negotiateauth',
'--enable-nfc',
'--enable-nspr-build',
'--enable-official-branding',
'--enable-omx-plugin',
'--enable-oom-breakpoint',
'--enable-optimize',
'--enable-parental-controls',
'--enable-perf',
'--enable-permissions',
'--enable-pie',
'--enable-png-arm-neon-support',
'--enable-posix-nspr-emulation',
'--enable-pref-extensions',
'--enable-printing',
'--enable-profilelocking',
'--enable-profiling',
'--enable-pulseaudio',
'--enable-raw',
'--enable-readline',
'--enable-reflow-perf',
'--enable-release',
'--enable-replace-malloc',
'--enable-require-all-d3dc-versions',
'--enable-rust',
'--enable-safe-browsing',
'--enable-sandbox',
'--enable-shared-js',
'--enable-signmar',
'--enable-simulator',
'--enable-skia',
'--enable-skia-gpu',
'--enable-small-chunk-size',
'--enable-startup-notification',
'--enable-startupcache',
'--enable-stdcxx-compat',
'--enable-strip',
'--enable-synth-pico',
'--enable-synth-speechd',
'--enable-system-cairo',
'--enable-system-extension-dirs',
'--enable-system-ffi',
'--enable-system-hunspell',
'--enable-system-pixman',
'--enable-system-sqlite',
'--enable-systrace',
'--enable-tasktracer',
'--enable-tests',
'--enable-thread-sanitizer',
'--enable-trace-logging',
'--enable-tree-freetype',
'--enable-ui-locale',
'--enable-universalchardet',
'--enable-update-channel',
'--enable-update-packaging',
'--enable-updater',
'--enable-url-classifier',
'--enable-valgrind',
'--enable-verify-mar',
'--enable-vtune',
'--enable-warnings-as-errors',
'--enable-webapp-runtime',
'--enable-webrtc',
'--enable-websms-backend',
'--enable-webspeech',
'--enable-webspeechtestbackend',
'--enable-wmf',
'--enable-xterm-updates',
'--enable-xul',
'--enable-zipwriter',
'--host',
'--no-create',
'--prefix',
'--target',
'--with-adjust-sdk-keyfile',
'--with-android-cxx-stl',
'--with-android-distribution-directory',
'--with-android-gnu-compiler-version',
'--with-android-max-sdk',
'--with-android-min-sdk',
'--with-android-ndk',
'--with-android-sdk',
'--with-android-toolchain',
'--with-android-version',
'--with-app-basename',
'--with-app-name',
'--with-arch',
'--with-arm-kuser',
'--with-bing-api-keyfile',
'--with-branding',
'--with-ccache',
'--with-compiler-wrapper',
'--with-crashreporter-enable-percent',
'--with-cross-lib',
'--with-debug-label',
'--with-default-mozilla-five-home',
'--with-distribution-id',
'--with-doc-include-dirs',
'--with-doc-input-dirs',
'--with-doc-output-dir',
'--with-external-source-dir',
'--with-float-abi',
'--with-fpu',
'--with-gl-provider',
'--with-gonk',
'--with-gonk-toolchain-prefix',
'--with-google-api-keyfile',
'--with-google-oauth-api-keyfile',
'--with-gradle',
'--with-intl-api',
'--with-ios-sdk',
'--with-java-bin-path',
'--with-jitreport-granularity',
'--with-l10n-base',
'--with-libxul-sdk',
'--with-linux-headers',
'--with-macbundlename-prefix',
'--with-macos-private-frameworks',
'--with-macos-sdk',
'--with-mozilla-api-keyfile',
'--with-nspr-cflags',
'--with-nspr-libs',
'--with-pthreads',
'--with-qemu-exe',
'--with-qtdir',
'--with-servo',
'--with-sixgill',
'--with-soft-float',
'--with-system-bz2',
'--with-system-icu',
'--with-system-jpeg',
'--with-system-libevent',
'--with-system-libvpx',
'--with-system-nspr',
'--with-system-nss',
'--with-system-png',
'--with-system-zlib',
'--with-thumb',
'--with-thumb-interwork',
'--with-unify-dist',
'--with-user-appdir',
'--with-windows-version',
'--with-x',
'--with-xulrunner-stub-name',
'--x-includes',
'--x-libraries',
)
@advanced
def old_configure(prepare_configure, all_options, *options):
import codecs
import os
import subprocess
import sys
import types
ret = subprocess.call(prepare_configure)
if ret:
sys.exit(ret)
raw_config = {}
encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
with codecs.open('config.data', 'r', encoding) as fh:
code = compile(fh.read(), 'config.data', 'exec')
# Every variation of the exec() function I tried led to:
# SyntaxError: unqualified exec is not allowed in function 'main' it
# contains a nested function with free variables
exec code in raw_config
# Ensure all the flags known to old-configure appear in the
# @old_configure_options above.
for flag in raw_config['flags']:
if flag not in all_options:
error('Missing option in `@old_configure_options` in %s: %s'
% (__file__, flag))
# If the code execution above fails, we want to keep the file around for
# debugging.
os.remove('config.data')
config = {}
for k, v in raw_config['substs']:
set_config(k[1:-1], v[1:-1] if isinstance(v, types.StringTypes) else v)
for k, v in dict(raw_config['defines']).iteritems():
set_define(k[1:-1], v[1:-1])
set_config('non_global_defines', raw_config['non_global_defines'])

View File

@@ -0,0 +1,69 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@template
@advanced
def warn(*args):
import sys
print(*args, file=sys.stderr)
sys.stderr.flush()
@template
@advanced
def error(*args):
import sys
print(*args, file=sys.stderr)
sys.stderr.flush()
sys.exit(1)
@template
@advanced
def is_absolute_or_relative(path):
import os
if os.altsep and os.altsep in path:
return True
return os.sep in path
@template
@advanced
def normsep(path):
import mozpack.path as mozpath
return mozpath.normsep(path)
@template
@advanced
def find_program(file):
if is_absolute_or_relative(file):
return os.path.abspath(file) if os.path.isfile(file) else None
from which import which, WhichError
try:
return normsep(which(file))
except WhichError:
return None
@depends('--help')
def _defines(help):
ret = {}
set_config('DEFINES', ret)
return ret
@template
def set_define(name, value):
@depends(_defines)
@advanced
def _add_define(defines):
from mozbuild.configure import ConfigureError
if name in defines:
raise ConfigureError("'%s' is already defined" % name)
defines[name] = value
del _defines

View File

@@ -5,168 +5,53 @@
from __future__ import print_function, unicode_literals from __future__ import print_function, unicode_literals
import codecs import codecs
import glob
import itertools
import json import json
import os import os
import subprocess import subprocess
import sys import sys
import re
import types
base_dir = os.path.abspath(os.path.dirname(__file__)) base_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.append(os.path.join(base_dir, 'python', 'which')) sys.path.append(os.path.join(base_dir, 'python', 'which'))
sys.path.append(os.path.join(base_dir, 'python', 'mozbuild')) sys.path.append(os.path.join(base_dir, 'python', 'mozbuild'))
from which import which, WhichError from mozbuild.configure import ConfigureSandbox
from mozbuild.mozconfig import MozconfigLoader
# If feel dirty replicating this from python/mozbuild/mozbuild/mozconfig.py, def main(argv):
# but the end goal being that the configure script would go away...
shell = 'sh'
if 'MOZILLABUILD' in os.environ:
shell = os.environ['MOZILLABUILD'] + '/msys/bin/sh'
if sys.platform == 'win32':
shell = shell + '.exe'
def is_absolute_or_relative(path):
if os.altsep and os.altsep in path:
return True
return os.sep in path
def find_program(file):
if is_absolute_or_relative(file):
return os.path.abspath(file) if os.path.isfile(file) else None
try:
return which(file)
except WhichError:
return None
def autoconf_refresh(configure):
if os.path.exists(configure):
mtime = os.path.getmtime(configure)
aclocal = os.path.join(base_dir, 'build', 'autoconf', '*.m4')
for input in itertools.chain(
(configure + '.in',
os.path.join(os.path.dirname(configure), 'aclocal.m4')),
glob.iglob(aclocal),
):
if os.path.getmtime(input) > mtime:
break
else:
return
mozconfig_autoconf = None
configure_dir = os.path.dirname(configure)
# Don't read the mozconfig for the js configure (yay backwards
# compatibility)
if not configure_dir.replace(os.sep, '/').endswith('/js/src'):
loader = MozconfigLoader(os.path.dirname(configure))
project = os.environ.get('MOZ_CURRENT_PROJECT')
mozconfig = loader.find_mozconfig(env=os.environ)
mozconfig = loader.read_mozconfig(mozconfig, moz_build_app=project)
make_extra = mozconfig['make_extra']
if make_extra:
for assignment in make_extra:
m = re.match('(?:export\s+)?AUTOCONF\s*:?=\s*(.+)$',
assignment)
if m:
mozconfig_autoconf = m.group(1)
for ac in (mozconfig_autoconf, os.environ.get('AUTOCONF'), 'autoconf-2.13',
'autoconf2.13', 'autoconf213'):
if ac:
autoconf = find_program(ac)
if autoconf:
break
else:
fink = find_program('fink')
if fink:
autoconf = os.path.normpath(os.path.join(
fink, '..', '..', 'lib', 'autoconf2.13', 'bin', 'autoconf'))
if not autoconf:
raise RuntimeError('Could not find autoconf 2.13')
# Add or adjust AUTOCONF for subprocesses, especially the js/src configure
os.environ['AUTOCONF'] = autoconf
print('Refreshing %s with %s' % (configure, autoconf), file=sys.stderr)
with open(configure, 'wb') as fh:
subprocess.check_call([
shell, autoconf, '--localdir=%s' % os.path.dirname(configure),
configure + '.in'], stdout=fh)
def main(args):
old_configure = os.environ.get('OLD_CONFIGURE')
if not old_configure:
raise Exception('The OLD_CONFIGURE environment variable must be set')
# We need to replace backslashes with forward slashes on Windows because
# this path actually ends up literally as $0, which breaks autoconf's
# detection of the source directory.
old_configure = os.path.abspath(old_configure).replace(os.sep, '/')
try:
autoconf_refresh(old_configure)
except RuntimeError as e:
print(e.message, file=sys.stderr)
return 1
ret = subprocess.call([shell, old_configure] + args)
# We don't want to create and run config.status if --help was one of the
# command line arguments.
if ret or '--help' in args:
return ret
raw_config = {}
encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
with codecs.open('config.data', 'r', encoding) as fh:
code = compile(fh.read(), 'config.data', 'exec')
# Every variation of the exec() function I tried led to:
# SyntaxError: unqualified exec is not allowed in function 'main' it
# contains a nested function with free variables
exec code in raw_config
# If the code execution above fails, we want to keep the file around for
# debugging.
os.remove('config.data')
# Sanitize config data
config = {} config = {}
substs = config['substs'] = { sandbox = ConfigureSandbox(config, os.environ, argv)
k[1:-1]: v[1:-1] if isinstance(v, types.StringTypes) else v sandbox.run(os.path.join(os.path.dirname(__file__), 'moz.configure'))
for k, v in raw_config['substs']
if sandbox._help:
return 0
# Sanitize config data to feed config.status
sanitized_config = {}
sanitized_config['substs'] = {
k: v for k, v in config.iteritems()
if k not in ('DEFINES', 'non_global_defines', 'TOPSRCDIR', 'TOPOBJDIR')
} }
config['defines'] = { sanitized_config['defines'] = config['DEFINES']
k[1:-1]: v[1:-1] sanitized_config['non_global_defines'] = config['non_global_defines']
for k, v in raw_config['defines'] sanitized_config['topsrcdir'] = config['TOPSRCDIR']
} sanitized_config['topobjdir'] = config['TOPOBJDIR']
config['non_global_defines'] = raw_config['non_global_defines']
config['topsrcdir'] = base_dir
config['topobjdir'] = os.path.abspath(os.getcwd())
# Create config.status. Eventually, we'll want to just do the work it does # Create config.status. Eventually, we'll want to just do the work it does
# here, when we're able to skip configure tests/use cached results/not rely # here, when we're able to skip configure tests/use cached results/not rely
# on autoconf. # on autoconf.
print("Creating config.status", file=sys.stderr) print("Creating config.status", file=sys.stderr)
encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8'
with codecs.open('config.status', 'w', encoding) as fh: with codecs.open('config.status', 'w', encoding) as fh:
fh.write('#!%s\n' % config['substs']['PYTHON']) fh.write('#!%s\n' % config['PYTHON'])
fh.write('# coding=%s\n' % encoding) fh.write('# coding=%s\n' % encoding)
for k, v in config.iteritems(): for k, v in sanitized_config.iteritems():
fh.write('%s = ' % k) fh.write('%s = ' % k)
json.dump(v, fh, sort_keys=True, indent=4, ensure_ascii=False) json.dump(v, fh, sort_keys=True, indent=4, ensure_ascii=False)
fh.write('\n') fh.write('\n')
fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', " fh.write("__all__ = ['topobjdir', 'topsrcdir', 'defines', "
"'non_global_defines', 'substs']") "'non_global_defines', 'substs']")
if not substs.get('BUILDING_JS') or substs.get('JS_STANDALONE'): if not config.get('BUILDING_JS') or config.get('JS_STANDALONE'):
fh.write(''' fh.write('''
if __name__ == '__main__': if __name__ == '__main__':
args = dict([(name, globals()[name]) for name in __all__]) args = dict([(name, globals()[name]) for name in __all__])
@@ -177,13 +62,13 @@ if __name__ == '__main__':
# Other things than us are going to run this file, so we need to give it # Other things than us are going to run this file, so we need to give it
# executable permissions. # executable permissions.
os.chmod('config.status', 0755) os.chmod('config.status', 0755)
if not substs.get('BUILDING_JS') or substs.get('JS_STANDALONE'): if not config.get('BUILDING_JS') or config.get('JS_STANDALONE'):
if not substs.get('JS_STANDALONE'): if not config.get('JS_STANDALONE'):
os.environ['WRITE_MOZINFO'] = '1' os.environ['WRITE_MOZINFO'] = '1'
# Until we have access to the virtualenv from this script, execute # Until we have access to the virtualenv from this script, execute
# config.status externally, with the virtualenv python. # config.status externally, with the virtualenv python.
return subprocess.call([config['substs']['PYTHON'], 'config.status']) return subprocess.call([config['PYTHON'], 'config.status'])
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.argv[1:])) sys.exit(main(sys.argv))

View File

@@ -76,42 +76,6 @@ dnl ==============================================================
_topsrcdir=`cd $srcdir; pwd -W 2>/dev/null || pwd -P` _topsrcdir=`cd $srcdir; pwd -W 2>/dev/null || pwd -P`
_objdir=`pwd -P` _objdir=`pwd -P`
if test "$_topsrcdir" = "$_objdir"
then
echo " ***"
echo " * Building directly in the main source directory is not allowed."
echo " *"
echo " * To build, you must run configure from a separate directory"
echo " * (referred to as an object directory)."
echo " ***"
exit 1
fi
# Check for a couple representative files in the source tree
_conflict_files=
for file in $_topsrcdir/Makefile $_topsrcdir/config/autoconf.mk; do
if test -f $file; then
_conflict_files="$_conflict_files $file"
fi
done
if test "$_conflict_files"; then
echo "***"
echo "* Your source tree contains these files:"
for file in $_conflict_files; do
echo "* $file"
done
cat 1>&2 <<-EOF
* This indicates that you previously built in the source tree.
* A source tree build can confuse the separate objdir build.
*
* To clean up the source tree:
* 1. cd $_topsrcdir
* 2. gmake distclean
***
EOF
exit 1
break
fi
MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P` MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P`
MOZ_BUILD_BACKEND(../..) MOZ_BUILD_BACKEND(../..)
@@ -3435,8 +3399,6 @@ AC_SUBST(MOZ_FIX_LINK_PATHS)
AC_SUBST(USE_DEPENDENT_LIBS) AC_SUBST(USE_DEPENDENT_LIBS)
AC_SUBST(MOZ_BUILD_ROOT)
AC_SUBST(MOZ_POST_PROGRAM_COMMAND) AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
AC_SUBST(MOZ_APP_NAME) AC_SUBST(MOZ_APP_NAME)

10
moz.configure Normal file
View File

@@ -0,0 +1,10 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
include('build/moz.configure/init.configure')
# Fallthrough to autoconf-based configure
include('build/moz.configure/old.configure')

View File

@@ -96,44 +96,6 @@ dnl ==============================================================
_topsrcdir=`cd \`dirname $0\`; pwd -W 2>/dev/null || pwd -P` _topsrcdir=`cd \`dirname $0\`; pwd -W 2>/dev/null || pwd -P`
_objdir=`pwd -P` _objdir=`pwd -P`
if test "$_topsrcdir" = "$_objdir"; then
echo " ***"
echo " * Building directly in the main source directory is not allowed."
echo " *"
echo " * To build, you must run configure from a separate directory"
echo " * (referred to as an object directory)."
echo " *"
echo " * If you are building with a mozconfig, you will need to change your"
echo " * mozconfig to point to a different object directory."
echo " ***"
exit 1
fi
# Check for a couple representative files in the source tree
_conflict_files=
for file in $_topsrcdir/Makefile $_topsrcdir/config/autoconf.mk; do
if test -f $file; then
_conflict_files="$_conflict_files $file"
fi
done
if test "$_conflict_files"; then
echo "***"
echo "* Your source tree contains these files:"
for file in $_conflict_files; do
echo "* $file"
done
cat 1>&2 <<-EOF
* This indicates that you previously built in the source tree.
* A source tree build can confuse the separate objdir build.
*
* To clean up the source tree:
* 1. cd $_topsrcdir
* 2. gmake distclean
***
EOF
exit 1
break
fi
MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P` MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P`
DIST="$MOZ_BUILD_ROOT/dist" DIST="$MOZ_BUILD_ROOT/dist"
@@ -8474,8 +8436,6 @@ AC_SUBST(MOZ_FIX_LINK_PATHS)
AC_SUBST(USE_DEPENDENT_LIBS) AC_SUBST(USE_DEPENDENT_LIBS)
AC_SUBST(MOZ_BUILD_ROOT)
AC_SUBST(MOZ_POST_PROGRAM_COMMAND) AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
AC_SUBST(MOZ_LINKER_EXTRACT) AC_SUBST(MOZ_LINKER_EXTRACT)

View File

@@ -1391,30 +1391,6 @@ class MachDebug(MachCommandBase):
print('FOUND_MOZCONFIG=%s' % mozpath.normsep(self.mozconfig['path']), print('FOUND_MOZCONFIG=%s' % mozpath.normsep(self.mozconfig['path']),
file=out) file=out)
def _environment_configure(self, out, verbose):
if self.mozconfig['path']:
# Replace ' with '"'"', so that shell quoting e.g.
# a'b becomes 'a'"'"'b'.
quote = lambda s: s.replace("'", """'"'"'""")
if self.mozconfig['configure_args']:
print('echo Adding configure options from %s' %
mozpath.normsep(self.mozconfig['path']), file=out)
for arg in self.mozconfig['configure_args']:
quoted_arg = quote(arg)
print("echo ' %s'" % quoted_arg, file=out)
print("""set -- "$@" '%s'""" % quoted_arg, file=out)
for key, value in self.mozconfig['env']['added'].items():
print("export %s='%s'" % (key, quote(value)), file=out)
for key, (old, value) in self.mozconfig['env']['modified'].items():
print("export %s='%s'" % (key, quote(value)), file=out)
for key, value in self.mozconfig['vars']['added'].items():
print("%s='%s'" % (key, quote(value)), file=out)
for key, (old, value) in self.mozconfig['vars']['modified'].items():
print("%s='%s'" % (key, quote(value)), file=out)
for key in self.mozconfig['env']['removed'].keys() + \
self.mozconfig['vars']['removed'].keys():
print("unset %s" % key, file=out)
def _environment_json(self, out, verbose): def _environment_json(self, out, verbose):
import json import json
class EnvironmentEncoder(json.JSONEncoder): class EnvironmentEncoder(json.JSONEncoder):