☠☠ backed out by fdbec826407a ☠ ☠ | |
author | Sylvestre Ledru <sledru@mozilla.com> |
Wed, 11 Oct 2017 16:28:29 +0200 | |
changeset 385820 | 4dc78384cb58c67de770ef207bbd700e7a982960 |
parent 385819 | f758ec7889141e1c8eae484c1907623fa8be343e |
child 385821 | e993235fbdf336a9da7a37e50023e649a4550e61 |
push id | 53155 |
push user | sledru@mozilla.com |
push date | Thu, 12 Oct 2017 12:58:56 +0000 |
treeherder | autoland@4dc78384cb58 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | glandium |
bugs | 1406668 |
milestone | 58.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/build/moz.configure/.flake8 @@ -0,0 +1,5 @@ +[flake8] +# F821: undefined name +# This is the moz.configure style +ignore = F821 +
--- a/build/moz.configure/android-ndk.configure +++ b/build/moz.configure/android-ndk.configure @@ -6,28 +6,31 @@ js_option('--with-android-ndk', nargs=1, help='location where the Android NDK can be found') js_option('--with-android-toolchain', nargs=1, help='location of the Android toolchain') + @depends(target) def min_android_version(target): if target.cpu in ['aarch64', 'x86_64', 'mips64']: # 64-bit support was added in API 21. return '21' return '9' + js_option('--with-android-version', nargs=1, help='android platform version', default=min_android_version) + @depends('--with-android-version', min_android_version, '--help') @imports(_from='__builtin__', _import='ValueError') def android_version(value, min_version, _): if not value: # Someone has passed --without-android-version. die('--with-android-version cannot be disabled.') try: @@ -36,31 +39,35 @@ def android_version(value, min_version, die('--with-android-version expects an integer value') if version < int(min_version): die('--with-android-version must be at least %s (got %s)', min_version, value[0]) return version + add_old_configure_assignment('android_version', android_version) + @depends('--with-android-ndk', build_project, '--help') def ndk(value, build_project, help): if help: return if build_project == 'mobile/android' and not value: die('You must specify --with-android-ndk=/path/to/ndk when ' 'building mobile/android') if value: return value[0] + set_config('ANDROID_NDK', ndk) add_old_configure_assignment('android_ndk', ndk) + @depends(ndk) @checking('for android ndk version') @imports(_from='__builtin__', _import='open') def ndk_version(ndk): if not ndk: # Building 'js/src' for non-Android. return with open(os.path.join(ndk, 'source.properties'), 'r') as f: @@ -68,39 +75,44 @@ def ndk_version(ndk): if not line.startswith('Pkg.Revision'): continue (_, version) = line.split('=') if version: return version.strip() die('Unexpected Pkg.Revision line in source.properties') die('Cannot determine NDK version from source.properties') + @depends(ndk_version) def ndk_major_version(ndk_version): if not ndk_version: # Building 'js/src' for non-Android. return (major, minor, revision) = ndk_version.split('.') if major: return major die('Unexpected NDK version string: ' + ndk_version) -set_config('ANDROID_NDK_MAJOR_VERSION', ndk_major_version); + +set_config('ANDROID_NDK_MAJOR_VERSION', ndk_major_version) + @depends(ndk_version) def ndk_minor_version(ndk_version): if not ndk_version: # Building 'js/src' for non-Android. return (major, minor, revision) = ndk_version.split('.') if minor: return minor die('Unexpected NDK version string: ' + ndk_version) -set_config('ANDROID_NDK_MINOR_VERSION', ndk_minor_version); + +set_config('ANDROID_NDK_MINOR_VERSION', ndk_minor_version) + @depends(target, android_version, ndk, '--help') @checking('for android platform directory') @imports(_from='os.path', _import='isdir') def android_platform(target, android_version, ndk, _): if target.os != 'Android': return @@ -126,25 +138,28 @@ def android_platform(target, android_ver 'arch-%s' % target_dir_name) if not isdir(platform_dir): die("Android platform directory not found. With the current " "configuration, it should be in %s" % platform_dir) return platform_dir + add_old_configure_assignment('android_platform', android_platform) + @depends(android_platform) def extra_toolchain_flags(platform_dir): if not platform_dir: return [] return ['-idirafter', os.path.join(platform_dir, 'usr', 'include')] + @depends(target, host, ndk, '--with-android-toolchain', '--help') @checking('for the Android toolchain directory', lambda x: x or 'not found') @imports(_from='os.path', _import='isdir') @imports(_from='mozbuild.shellutil', _import='quote') def android_toolchain(target, host, ndk, toolchain, _): if not ndk: return if toolchain: @@ -170,38 +185,43 @@ def android_toolchain(target, host, ndk, toolchain = toolchain_format % (ndk, target_base, version, host.kernel.lower(), 'x86') log.debug('Trying %s' % quote(toolchain)) if isdir(toolchain): return toolchain die('You have to specify --with-android-toolchain=' '/path/to/ndk/toolchain.') + set_config('ANDROID_TOOLCHAIN', android_toolchain) + @depends(target) def android_toolchain_prefix_base(target): if target.cpu == 'x86': # Ideally, the --target should just have the right x86 variant # in the first place. return 'i686-linux-android' return target.toolchain + @depends(android_toolchain_prefix_base, android_toolchain) def android_toolchain_prefix(prefix_base, toolchain): if toolchain: return '%s/bin/%s-' % (toolchain, prefix_base) + imply_option('--with-toolchain-prefix', android_toolchain_prefix, reason='--with-android-ndk') option(env='STLPORT_CPPFLAGS', nargs=1, help='Options compiler should pass for standard C++ library') + @depends('STLPORT_CPPFLAGS', ndk, '--help') @imports(_from='os.path', _import='isdir') def stlport_cppflags(value, ndk, _): if value and len(value): return value if not ndk: return @@ -226,25 +246,28 @@ def stlport_cppflags(value, ndk, _): # Add android/support/include/ for prototyping long double math # functions, locale-specific C library functions, multibyte support, # etc. return "-I%s -I%s -I%s" % (cxx_include, os.path.join(ndk, 'sources', 'android', 'support', 'include'), cxxabi_include) + add_old_configure_assignment('stlport_cppflags', stlport_cppflags) + @depends(stlport_cppflags, android_platform, android_toolchain, android_toolchain_prefix_base, '--help') def bindgen_cflags_defaults(stlport_cppflags, android_platform, toolchain, toolchain_prefix, _): if not stlport_cppflags: return - gcc_include = os.path.join(toolchain, 'lib', 'gcc', toolchain_prefix, '4.9') + gcc_include = os.path.join( + toolchain, 'lib', 'gcc', toolchain_prefix, '4.9') cflags_format = "%s -isystem %s -gcc-toolchain %s -I%s -I%s" return cflags_format % (stlport_cppflags, os.path.join(android_platform, 'usr', 'include'), toolchain, os.path.join(gcc_include, 'include'), os.path.join(gcc_include, 'include-fixed'))
--- a/build/moz.configure/checks.configure +++ b/build/moz.configure/checks.configure @@ -6,26 +6,29 @@ # Templates implementing some generic checks. # ============================================================== # Declare some exceptions. This is cumbersome, but since we shouldn't need a # lot of them, let's stack them all here. When adding a new one, put it in the # _declare_exceptions template, and add it to the return statement. Then # destructure in the assignment below the function declaration. + + @template @imports(_from='__builtin__', _import='Exception') def _declare_exceptions(): class FatalCheckError(Exception): '''An exception to throw from a function decorated with @checking. It will result in calling die() with the given message. Debugging messages emitted from the decorated function will also be printed out.''' return (FatalCheckError,) + (FatalCheckError,) = _declare_exceptions() del _declare_exceptions # Helper to display "checking" messages # @checking('for foo') # def foo(): # return 'foo' @@ -37,16 +40,18 @@ del _declare_exceptions # return ret # This can be combined with e.g. @depends: # @depends(some_option) # @checking('for something') # def check(value): # ... # An optional callback can be given, that will be used to format the returned # value when displaying it. + + @template def checking(what, callback=None): def decorator(func): def wrapped(*args, **kwargs): log.info('checking %s... ', what) with log.queue_debug(): error, ret = None, None try:
--- a/build/moz.configure/compile-checks.configure +++ b/build/moz.configure/compile-checks.configure @@ -63,28 +63,31 @@ def check_header(header, language='C++', set_define(header_var, have_header) return have_header # A convenience wrapper for check_header for checking multiple headers. # returns an array of the resulting checks in order corresponding to the # provided headers. # - `headers` are the headers to be checked. # - `kwargs` are keyword arguments passed verbatim to check_header. + + @template def check_headers(*headers, **kwargs): checks = [] for header in headers: checks.append(check_header(header, **kwargs)) return checks @dependable def warnings_cflags(): return [] + @dependable def warnings_cxxflags(): return [] # Tests whether GCC or clang support the given warning flag, and if it is, # add it to the list of warning flags for the build. # - `warning` is the warning flag (e.g. -Wfoo) @@ -144,11 +147,13 @@ def check_and_add_gcc_warning(warning, c # Add the given warning to the list of warning flags for the build. # - `warning` is the warning flag (e.g. -Wfoo) # - `compiler` (optional) is the compiler to add the flag for (c_compiler or # cxx_compiler, from toolchain.configure). When omitted, the warning flag # is added for both compilers. # - `when` (optional) is a @depends function or option name conditioning # when the warning flag is wanted. + + @template def add_gcc_warning(warning, compiler=None, when=None): check_and_add_gcc_warning(warning, compiler, when, check=False)
--- a/build/moz.configure/compilers-util.configure +++ b/build/moz.configure/compilers-util.configure @@ -1,14 +1,15 @@ # -*- Mode: python; 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 @imports('textwrap') @imports(_from='mozbuild.configure', _import='SandboxDependsFunction') def compiler_class(compiler, host_or_target): is_target = host_or_target is target class Compiler(SandboxDependsFunction): # Generates a test program and attempts to compile it. In case of @@ -49,17 +50,18 @@ def compiler_class(compiler, host_or_tar @checking_fn def func(compiler, flags, extra_flags): flags = flags or [] if is_target: flags += extra_flags or [] flags.append('-c') if try_invoke_compiler( - compiler.wrapper + [compiler.compiler] + compiler.flags, - compiler.language, source, flags, - onerror=onerror) is not None: + compiler.wrapper + + [compiler.compiler] + compiler.flags, + compiler.language, source, flags, + onerror=onerror) is not None: return True return func compiler.__class__ = Compiler return compiler
--- a/build/moz.configure/headers.configure +++ b/build/moz.configure/headers.configure @@ -67,27 +67,32 @@ check_headers( # TODO: Move these checks to file specific to --enable-project=js. have_perf_event_h = check_header('linux/perf_event.h', when=building_linux) js_option('--with-linux-headers', help='location where the Linux kernel headers can be found', nargs=1) -passed_linux_header_flags = depends_if('--with-linux-headers')(lambda v: ['-I%s' % v[0]]) +passed_linux_header_flags = depends_if( + '--with-linux-headers')(lambda v: ['-I%s' % v[0]]) + @depends(try_compile(includes=['asm/unistd.h'], body='return sizeof(__NR_perf_event_open);', flags=passed_linux_header_flags, check_msg='for perf_event_open system call'), when=have_perf_event_h) def have_perf_event_open(have_perf_event_open): if have_perf_event_open: return True + set_config('HAVE_LINUX_PERF_EVENT_H', have_perf_event_open) + @depends(passed_linux_header_flags, have_perf_event_open) def linux_headers_includes(passed_linux_header_flags, have_perf_event_open): if have_perf_event_open and passed_linux_header_flags: return passed_linux_header_flags[0] + set_config('LINUX_HEADERS_INCLUDES', linux_headers_includes)
--- a/build/moz.configure/init.configure +++ b/build/moz.configure/init.configure @@ -6,16 +6,18 @@ include('util.configure') include('checks.configure') option(env='DIST', nargs=1, help='DIST directory') # Do not allow objdir == srcdir builds. # ============================================================== + + @depends('--help', 'DIST') @imports(_from='os.path', _import='exists') 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__), '..', '..'))) if dist: @@ -37,17 +39,17 @@ def check_build_environment(help, dist): ' * 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 exists(os.path.join(topsrcdir, f)) ] if conflict_files: die(' ***\n' @@ -56,20 +58,21 @@ def check_build_environment(help, dist): ' * 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) - ) + ) return result + set_config('TOPSRCDIR', check_build_environment.topsrcdir) set_config('TOPOBJDIR', check_build_environment.topobjdir) set_config('MOZ_BUILD_ROOT', check_build_environment.topobjdir) set_config('DIST', check_build_environment.dist) add_old_configure_assignment( '_topsrcdir', check_build_environment.topsrcdir) add_old_configure_assignment( @@ -86,29 +89,33 @@ set_config('MOZ_AUTOMATION', depends_if( option(env='OLD_CONFIGURE', nargs=1, help='Path to the old configure script') option(env='MOZ_CURRENT_PROJECT', nargs=1, help='Current build project') option(env='MOZCONFIG', nargs=1, help='Mozconfig location') option('--with-external-source-dir', env='EXTERNAL_SOURCE_DIR', nargs=1, help='External directory containing additional build files') + @depends('--with-external-source-dir') def external_source_dir(value): if value: return value[0] + set_config('EXTERNAL_SOURCE_DIR', external_source_dir) add_old_configure_assignment('EXTERNAL_SOURCE_DIR', external_source_dir) # 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', 'OLD_CONFIGURE', check_build_environment, '--with-external-source-dir', '--help') @imports(_from='mozbuild.mozconfig', _import='MozconfigLoader') def mozconfig(current_project, mozconfig, old_configure, build_env, external_source_dir, help): if not old_configure: die('The OLD_CONFIGURE environment variable must be set') @@ -138,23 +145,26 @@ def mozconfig(current_project, mozconfig loader = MozconfigLoader(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 + set_config('MOZCONFIG', depends(mozconfig)(lambda m: m['path'])) option(env='PYTHON', nargs=1, help='Python interpreter') # Setup python virtualenv # ============================================================== + + @depends('PYTHON', check_build_environment, mozconfig, '--help') @imports('os') @imports('sys') @imports('subprocess') @imports(_from='mozbuild.configure.util', _import='LineIO') @imports(_from='mozbuild.virtualenv', _import='VirtualenvManager') @imports(_from='mozbuild.virtualenv', _import='verify_python_version') @imports('distutils.sysconfig') @@ -188,17 +198,18 @@ def virtualenv_python(env_python, build_ topsrcdir, topobjdir, os.path.join(topobjdir, '_virtualenv'), out, os.path.join(topsrcdir, 'build', 'virtualenv_packages.txt')) if python: # If we're not in the virtualenv, we need the which module for # find_program. if normsep(sys.executable) != normsep(manager.python_path): - sys.path.append(os.path.join(topsrcdir, 'third_party', 'python', 'which')) + sys.path.append(os.path.join( + topsrcdir, 'third_party', 'python', 'which')) found_python = find_program(python) if not found_python: die('The PYTHON environment variable does not contain ' 'a valid path. Cannot find %s', python) python = found_python else: python = sys.executable @@ -217,37 +228,42 @@ def virtualenv_python(env_python, build_ sys.exit(subprocess.call([python] + sys.argv)) # We are now in the virtualenv if not distutils.sysconfig.get_python_lib(): die('Could not determine python site packages directory') return python + set_config('PYTHON', virtualenv_python) add_old_configure_assignment('PYTHON', virtualenv_python) # Inject mozconfig options # ============================================================== # All options defined above this point can't be injected in mozconfig_options # below, so collect them. + + @template def early_options(): @dependable @imports('__sandbox__') def early_options(): return set( option.env for option in __sandbox__._options.itervalues() if option.env ) return early_options + early_options = early_options() + @depends(mozconfig, 'MOZ_AUTOMATION', '--help') # This gives access to the sandbox. Don't copy this blindly. @imports('__sandbox__') @imports('os') def mozconfig_options(mozconfig, automation, help): if mozconfig['path']: if 'MOZ_AUTOMATION_MOZCONFIG' in mozconfig['env']['added']: if not automation: @@ -288,16 +304,18 @@ def mozconfig_options(mozconfig, automat # ============================================================== option(env='MOZILLABUILD', nargs=1, help='Path to Mozilla Build (Windows-only)') option(env='CONFIG_SHELL', nargs=1, help='Path to a POSIX shell') # It feels dirty replicating this from python/mozbuild/mozbuild/mozconfig.py, # but the end goal being that the configure script would go away... + + @depends('CONFIG_SHELL', 'MOZILLABUILD') @checking('for a shell') @imports('sys') def shell(value, mozillabuild): if value: return find_program(value[0]) shell = 'sh' if mozillabuild: @@ -307,16 +325,17 @@ def shell(value, mozillabuild): return find_program(shell) # Python 3 # ======== option(env='PYTHON3', nargs=1, help='Python 3 interpreter (3.5 or later)') + @depends('PYTHON3') @checking('for Python 3', callback=lambda x: '%s (%s)' % (x.path, x.str_version) if x else 'no') @imports(_from='__builtin__', _import='Exception') @imports(_from='mozbuild.pythonutil', _import='find_python3_executable') @imports(_from='mozbuild.pythonutil', _import='python_executable_version') def python3(env_python): python = env_python[0] if env_python else None @@ -343,68 +362,75 @@ def python3(env_python): python = python.decode('utf-8') return namespace( path=python, version=version, str_version='.'.join(str(v) for v in version), ) + set_config('PYTHON3', depends_if(python3)(lambda p: p.path)) set_config('PYTHON3_VERSION', depends_if(python3)(lambda p: p.str_version)) # Source checkout and version control integration. # ================================================ + @depends(check_build_environment, 'MOZ_AUTOMATION', '--help') @checking('for vcs source checkout') @imports('os') def vcs_checkout_type(build_env, automation, _): if os.path.exists(os.path.join(build_env.topsrcdir, '.hg')): return 'hg' elif os.path.exists(os.path.join(build_env.topsrcdir, '.git')): return 'git' elif automation: raise FatalCheckError('unable to resolve VCS type; must run ' 'from a source checkout when MOZ_AUTOMATION ' 'is set') # Resolve VCS binary for detected repository type. + # TODO remove hg.exe once bug 1382940 addresses ambiguous executables case. hg = check_prog('HG', ('hg.exe', 'hg',), allow_missing=True, when=depends(vcs_checkout_type)(lambda x: x == 'hg')) git = check_prog('GIT', ('git',), allow_missing=True, when=depends(vcs_checkout_type)(lambda x: x == 'git')) + @depends_if(hg) @checking('for Mercurial version') @imports('os') @imports('re') def hg_version(hg): # HGPLAIN in Mercurial 1.5+ forces stable output, regardless of set # locale or encoding. env = dict(os.environ) env['HGPLAIN'] = '1' out = check_cmd_output(hg, '--version', env=env) match = re.search(r'Mercurial Distributed SCM \(version ([^\)]+)', out) if not match: - raise FatalCheckError('unable to determine Mercurial version: %s' % out) + raise FatalCheckError( + 'unable to determine Mercurial version: %s' % out) # The version string may be "unknown" for Mercurial run out of its own # source checkout or for bad builds. But LooseVersion handles it. return Version(match.group(1)) # Resolve Mercurial config items so other checks have easy access. # Do NOT set this in the config because it may contain sensitive data # like API keys. + + @depends_all(check_build_environment, hg, hg_version) @imports('os') def hg_config(build_env, hg, version): env = dict(os.environ) env['HGPLAIN'] = '1' # Warnings may get sent to stderr. But check_cmd_output() ignores # stderr if exit code is 0. And the command should always succeed if @@ -425,32 +451,35 @@ def hg_config(build_env, hg, version): config = {} for line in out.strip().splitlines(): key, value = [s.strip() for s in line.split('=', 1)] config[key] = value return config + @depends_if(git) @checking('for Git version') @imports('re') def git_version(git): out = check_cmd_output(git, '--version').rstrip() match = re.search('git version (.*)$', out) if not match: raise FatalCheckError('unable to determine Git version: %s' % out) return Version(match.group(1)) # Only set VCS_CHECKOUT_TYPE if we resolved the VCS binary. # Require resolved VCS info when running in automation so automation's # environment is more well-defined. + + @depends(vcs_checkout_type, hg_version, git_version, 'MOZ_AUTOMATION') def exposed_vcs_checkout_type(vcs_checkout_type, hg, git, automation): if vcs_checkout_type == 'hg': if hg: return 'hg' if automation: raise FatalCheckError('could not resolve Mercurial binary info') @@ -459,44 +488,50 @@ def exposed_vcs_checkout_type(vcs_checko if git: return 'git' if automation: raise FatalCheckError('could not resolve Git binary info') elif vcs_checkout_type: raise FatalCheckError('unhandled VCS type: %s' % vcs_checkout_type) + set_config('VCS_CHECKOUT_TYPE', exposed_vcs_checkout_type) # Obtain a Repository interface for the current VCS repository. + + @depends(check_build_environment, exposed_vcs_checkout_type, hg, git) @imports(_from='mozversioncontrol', _import='get_repository_object') def vcs_repository(build_env, vcs_checkout_type, hg, git): if vcs_checkout_type == 'hg': return get_repository_object(build_env.topsrcdir, hg=hg) elif vcs_checkout_type == 'git': return get_repository_object(build_env.topsrcdir, git=git) elif vcs_checkout_type: raise FatalCheckError('unhandled VCS type: %s' % vcs_checkout_type) + @depends_if(vcs_repository) @checking('for sparse checkout') def vcs_sparse_checkout(repo): return repo.sparse_checkout_present() + set_config('VCS_SPARSE_CHECKOUT', vcs_sparse_checkout) # Host and target systems # ============================================================== option('--host', nargs=1, help='Define the system type performing the build') option('--target', nargs=1, help='Define the system type where the resulting executables will be ' 'used') + @imports(_from='mozbuild.configure.constants', _import='CPU') @imports(_from='mozbuild.configure.constants', _import='CPU_bitness') @imports(_from='mozbuild.configure.constants', _import='Endianness') @imports(_from='mozbuild.configure.constants', _import='Kernel') @imports(_from='mozbuild.configure.constants', _import='OS') @imports(_from='__builtin__', _import='KeyError') @imports(_from='__builtin__', _import='ValueError') def split_triplet(triplet, allow_unknown=False): @@ -659,72 +694,83 @@ def host(value, shell): config_guess = os.path.join(os.path.dirname(__file__), '..', 'autoconf', 'config.guess') host = subprocess.check_output([shell, config_guess]).strip() else: host = value[0] return split_triplet(config_sub(shell, host)) + host = help_host_target | host @depends('--target', host, shell) @checking('for target system type', lambda t: t.alias) def target(value, host, shell): if not value: return host return split_triplet(config_sub(shell, value[0])) + target = help_host_target | target @depends(host, target) @checking('whether cross compiling') def cross_compiling(host, target): return host != target + set_config('CROSS_COMPILE', cross_compiling) set_define('CROSS_COMPILE', cross_compiling) add_old_configure_assignment('CROSS_COMPILE', cross_compiling) @depends(target) def have_64_bit(target): if target.bitness == 64: return True + set_config('HAVE_64BIT_BUILD', have_64_bit) set_define('HAVE_64BIT_BUILD', have_64_bit) add_old_configure_assignment('HAVE_64BIT_BUILD', have_64_bit) + @depends(host) def host_os_kernel_major_version(host): versions = host.raw_os.split('.') version = ''.join(x for x in versions[0] if x.isdigit()) return version + set_config('HOST_MAJOR_VERSION', host_os_kernel_major_version) # Autoconf needs these set + + @depends(host) def host_for_old_configure(host): return '--host=%s' % host.alias + add_old_configure_arg(host_for_old_configure) + @depends(target) def target_for_old_configure(target): target_alias = target.alias # old-configure does plenty of tests against $target and $target_os # and expects darwin for iOS, so make it happy. if target.os == 'iOS': target_alias = target_alias.replace('-ios', '-darwin') return '--target=%s' % target_alias + add_old_configure_arg(target_for_old_configure) # These variables are for compatibility with the current moz.builds and # old-configure. Eventually, we'll want to canonicalize better. @depends(target) def target_variables(target): if target.kernel == 'kFreeBSD': @@ -745,16 +791,17 @@ def target_variables(target): return namespace( OS_TARGET=os_target, OS_ARCH=os_arch, OS_TEST=os_test, INTEL_ARCHITECTURE=target.cpu in ('x86', 'x86_64') or None, ) + set_config('OS_TARGET', target_variables.OS_TARGET) add_old_configure_assignment('OS_TARGET', target_variables.OS_TARGET) set_config('OS_ARCH', target_variables.OS_ARCH) add_old_configure_assignment('OS_ARCH', target_variables.OS_ARCH) set_config('OS_TEST', target_variables.OS_TEST) add_old_configure_assignment('OS_TEST', @@ -771,95 +818,114 @@ def host_variables(host): if host.kernel == 'kFreeBSD': os_arch = 'GNU_kFreeBSD' else: os_arch = host.kernel return namespace( HOST_OS_ARCH=os_arch, ) + set_config('HOST_CPU_ARCH', host.cpu) set_config('HOST_OS_ARCH', host_variables.HOST_OS_ARCH) add_old_configure_assignment('HOST_OS_ARCH', host_variables.HOST_OS_ARCH) + @depends(target) def target_is_windows(target): if target.kernel == 'WINNT': return True + set_define('_WINDOWS', target_is_windows) set_define('WIN32', target_is_windows) set_define('XP_WIN', target_is_windows) set_define('XP_WIN32', target_is_windows) + @depends(target) def target_is_unix(target): if target.kernel != 'WINNT': return True + set_define('XP_UNIX', target_is_unix) + @depends(target) def target_is_darwin(target): if target.kernel == 'Darwin': return True + set_define('XP_DARWIN', target_is_darwin) + @depends(target) def target_is_ios(target): if target.kernel == 'Darwin' and target.os == 'iOS': return True + set_define('XP_IOS', target_is_ios) + @depends(target) def target_is_osx(target): if target.kernel == 'Darwin' and target.os == 'OSX': return True + set_define('XP_MACOSX', target_is_osx) + @depends(target) def target_is_linux(target): if target.kernel == 'Linux': return True + set_define('XP_LINUX', target_is_linux) + @depends(target) def target_is_solaris(target): if target.kernel == 'SunOS': return True + set_define('XP_SOLARIS', target_is_solaris) # The application/project to build # ============================================================== option('--enable-application', nargs=1, env='MOZ_BUILD_APP', help='Application to build. Same as --enable-project.') + @depends('--enable-application', '--help') def application(app, help): if app: return app + imply_option('--enable-project', application) @depends(check_build_environment, '--help') def default_project(build_env, help): if build_env.topobjdir.endswith('/js/src'): return 'js' return 'browser' + option('--enable-project', nargs=1, default=default_project, help='Project to build') + @depends('--enable-project', '--with-external-source-dir', check_build_environment, '--help') @imports(_from='os.path', _import='exists') def include_project_configure(project, external_source_dir, build_env, help): if not project: die('--enable-project is required.') base_dir = build_env.topsrcdir @@ -873,16 +939,17 @@ def include_project_configure(project, e @depends(include_project_configure, check_build_environment, '--help') def build_project(include_project_configure, build_env, help): ret = os.path.dirname(os.path.relpath(include_project_configure, build_env.topsrcdir)) return ret + set_config('MOZ_BUILD_APP', build_project) set_define('MOZ_BUILD_APP', build_project) add_old_configure_assignment('MOZ_BUILD_APP', build_project) # set RELEASE_OR_BETA and NIGHTLY_BUILD variables depending on the cycle we're in # The logic works like this: # - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD) @@ -903,16 +970,17 @@ def milestone(build_env, _): is_nightly = True elif 'a' not in milestone: is_release_or_beta = True return namespace(version=milestone, is_nightly=is_nightly, is_release_or_beta=is_release_or_beta) + set_config('GRE_MILESTONE', milestone.version) set_config('NIGHTLY_BUILD', milestone.is_nightly) set_define('NIGHTLY_BUILD', milestone.is_nightly) add_old_configure_assignment('NIGHTLY_BUILD', milestone.is_nightly) set_config('RELEASE_OR_BETA', milestone.is_release_or_beta) set_define('RELEASE_OR_BETA', milestone.is_release_or_beta) add_old_configure_assignment('RELEASE_OR_BETA', milestone.is_release_or_beta) @@ -920,22 +988,24 @@ add_old_configure_assignment('RELEASE_OR # The app update channel is 'default' when not supplied. The value is used in # the application's confvars.sh (and is made available to a project specific # moz.configure). option('--enable-update-channel', nargs=1, help='Select application update channel', default='default') + @depends('--enable-update-channel') def update_channel(channel): if channel[0] == '': return 'default' return channel[0].lower() + set_config('MOZ_UPDATE_CHANNEL', update_channel) set_define('MOZ_UPDATE_CHANNEL', update_channel) add_old_configure_assignment('MOZ_UPDATE_CHANNEL', update_channel) # A template providing a shorthand for setting a variable. The created # option will only be settable with imply_option. # It is expected that a project-specific moz.configure will call imply_option @@ -944,17 +1014,18 @@ add_old_configure_assignment('MOZ_UPDATE # will additionally cause the variable to be set using set_define and # add_old_configure_assignment. util.configure would be an appropriate place for # this, but it uses add_old_configure_assignment, which is defined in this file. @template def project_flag(env=None, set_for_old_configure=False, set_as_define=False, **kwargs): if not env: - configure_error("A project_flag must be passed a variable name to set.") + configure_error( + "A project_flag must be passed a variable name to set.") opt = option(env=env, possible_origins=('implied',), **kwargs) @depends(opt.option) def option_implementation(value): if value: if len(value): return value @@ -962,22 +1033,26 @@ def project_flag(env=None, set_for_old_c set_config(env, option_implementation) if set_as_define: set_define(env, option_implementation) if set_for_old_configure: add_old_configure_assignment(env, option_implementation) # milestone.is_nightly corresponds to cases NIGHTLY_BUILD is set. + + @depends(milestone, '--help') def enabled_in_nightly(milestone, _): return milestone.is_nightly # Set the MOZ_CONFIGURE_OPTIONS variable with all the options that # were passed somehow (environment, command line, mozconfig) + + @dependable @imports(_from='mozbuild.shellutil', _import='quote') @imports('__sandbox__') def all_configure_options(): result = [] previous = None for option in __sandbox__._options.itervalues(): # __sandbox__._options contains items for both option.name and @@ -999,16 +1074,17 @@ def all_configure_options(): # because we don't know their actual defaults. (Keep the conditions # separate for ease of understanding and ease of removal) elif (option.help == 'Help missing for old configure options' and option in __sandbox__._raw_options): result.append(__sandbox__._raw_options[option]) return quote(*result) + set_config('MOZ_CONFIGURE_OPTIONS', all_configure_options) # This is temporary until js/src/configure and configure are merged. # Use instead of option() in js/moz.configure and more generally, for # options that are shared between configure and js/src/configure. @template def js_option(*args, **kwargs):
--- a/build/moz.configure/java.configure +++ b/build/moz.configure/java.configure @@ -5,53 +5,58 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Java detection # ======================================================== option('--with-java-bin-path', nargs=1, help='Location of Java binaries (java, javac, jar)') + @depends('--with-java-bin-path') @imports(_from='os', _import='environ') def java_search_paths(path): if path: # Look for javac and jar in the specified path. return path # With no path specified, look for javac and jar in $JAVA_HOME (if set) # and $PATH. if 'JAVA_HOME' in environ: return [os.path.join(environ['JAVA_HOME'], 'bin'), environ.get('PATH', '')] return [environ.get('PATH')] # Finds the given java tool, failing with a custom error message if we can't # find it. + + @template def check_java_tool(tool): check = check_prog(tool.upper(), (tool,), paths=java_search_paths, allow_missing=True) @depends(check) def require_tool(result): if result is None: die("The program %s was not found. Set $JAVA_HOME to your Java " "SDK directory or use '--with-java-bin-path={java-bin-dir}'" % tool) return result return require_tool + check_java_tool('java') check_java_tool('javah') check_java_tool('jar') check_java_tool('jarsigner') check_java_tool('keytool') javac = check_java_tool('javac') + @depends(javac) @checking('for javac version') @imports('subprocess') def javac_version(javac): try: output = subprocess.check_output([javac, '-version'], stderr=subprocess.STDOUT).rstrip() version = Version(output.split(' ')[-1])
--- a/build/moz.configure/keyfiles.configure +++ b/build/moz.configure/keyfiles.configure @@ -54,12 +54,11 @@ def id_and_secret_keyfile(desc, default= secret=secret, ) content = keyfile(desc, help='Use the client id and secret key contained ' 'in the given keyfile for %s requests' % desc, default=default, callback=id_and_secret) - name = desc.upper().replace(' ', '_') set_config('MOZ_%s_CLIENTID' % name, content.id) set_config('MOZ_%s_KEY' % name, content.secret)
--- a/build/moz.configure/memory.configure +++ b/build/moz.configure/memory.configure @@ -8,16 +8,17 @@ @deprecated_option(env='MOZ_JEMALLOC4') def moz_jemalloc4(value): die('MOZ_JEMALLOC4 is deprecated') option('--enable-jemalloc', env='MOZ_MEMORY', help='Replace memory allocator with jemalloc') + @depends('--enable-jemalloc', target, build_project, c_compiler) def jemalloc(value, target, build_project, c_compiler): if value.origin != 'default': return bool(value) or None if build_project == 'js': return True @@ -43,27 +44,30 @@ add_old_configure_assignment('MOZ_MEMORY # Because --enable-jemalloc doesn't use a default because of the dependency # on the target, we can't use a js_option for it to propagate to js/src # through the old-configure. @depends(jemalloc) def jemalloc_for_old_configure(jemalloc): return '--%s-jemalloc' % ('enable' if jemalloc else 'disable') + add_old_configure_arg(jemalloc_for_old_configure) option('--enable-replace-malloc', help='Enable ability to dynamically replace the malloc implementation') + @depends('--enable-replace-malloc', jemalloc, milestone, build_project) def replace_malloc(value, jemalloc, milestone, build_project): # Enable on central for the debugging opportunities it adds. if value and not jemalloc: die('--enable-replace-malloc requires --enable-jemalloc') if value.origin != 'default': return bool(value) or None if milestone.is_nightly and jemalloc and build_project != 'js': return True + set_config('MOZ_REPLACE_MALLOC', replace_malloc) set_define('MOZ_REPLACE_MALLOC', replace_malloc) add_old_configure_assignment('MOZ_REPLACE_MALLOC', replace_malloc)
--- a/build/moz.configure/old.configure +++ b/build/moz.configure/old.configure @@ -1,23 +1,25 @@ # -*- Mode: python; 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/. + @imports('codecs') @imports('sys') def encoded_open(path, mode): encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8' return codecs.open(path, mode, encoding) option(env='AUTOCONF', nargs=1, help='Path to autoconf 2.13') + @depends(mozconfig, 'AUTOCONF') @checking('for autoconf') @imports(_from='os.path', _import='exists') @imports('re') def autoconf(mozconfig, autoconf): mozconfig_autoconf = None if mozconfig['path']: make_extra = mozconfig['make_extra'] @@ -51,16 +53,17 @@ def autoconf(mozconfig, autoconf): if not autoconf: die('Could not find autoconf 2.13') if not exists(autoconf): die('Could not find autoconf 2.13 at %s', autoconf) return autoconf + set_config('AUTOCONF', autoconf) @depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell, old_configure_assignments, build_project) @imports(_from='__builtin__', _import='open') @imports(_from='__builtin__', _import='print') @imports('glob') @@ -112,16 +115,17 @@ def prepare_configure(old_configure, moz script = script.replace('>./config.log', '>>./config.log') with open(old_configure, 'wb') as fh: fh.write(script) cmd = [shell, old_configure] with encoded_open('old-configure.vars', 'w') as out: log.debug('Injecting the following to old-configure:') + def inject(command): print(command, file=out) log.debug('| %s', command) if mozconfig['path']: for key, value in mozconfig['vars']['added'].items(): inject("%s=%s" % (key, quote(value))) for key, (old, value) in mozconfig['vars']['modified'].items(): @@ -355,17 +359,17 @@ def old_configure(prepare_configure, ext sys.exit(ret) raw_config = {} with encoded_open('config.data', 'r') 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 + exec code in raw_config # noqa # Ensure all the flags known to old-configure appear in the # @old_configure_options above. all_options = set(all_options) for flag in raw_config['flags']: if flag not in all_options: die('Missing option in `@old_configure_options` in %s: %s', __file__, flag) @@ -379,16 +383,18 @@ def old_configure(prepare_configure, ext # set_config is only available in the global namespace, not directly in # @depends functions, but we do need to enumerate the result of # old_configure, so we cheat. @imports('__sandbox__') def set_old_configure_config(name, value): __sandbox__.set_config_impl(name, value) # Same as set_old_configure_config, but for set_define. + + @imports('__sandbox__') def set_old_configure_define(name, value): __sandbox__.set_define_impl(name, value) @depends(old_configure) @imports('types') def post_old_configure(raw_config):
--- a/build/moz.configure/pkg.configure +++ b/build/moz.configure/pkg.configure @@ -1,21 +1,24 @@ # -*- Mode: python; 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/. + @depends('--enable-compile-environment') def pkg_config(compile_env): if compile_env: return ('pkg-config',) + pkg_config = check_prog('PKG_CONFIG', pkg_config, allow_missing=True) + @depends_if(pkg_config) @checking('for pkg-config version') @imports('subprocess') def pkg_config_version(pkg_config): return Version(check_cmd_output(pkg_config, '--version').rstrip()) # Locates the given module using pkg-config. # - `var` determines the name of variables to set when the package is found. @@ -24,16 +27,18 @@ def pkg_config_version(pkg_config): # strings describing packages to locate, or depends function that will # resolve to such a string or list of strings. # - `when` a depends function that will determine whether to perform # any checks (default is to always perform checks). # - `allow_missing` If set, failure to fulfill the package description # will not result in an error or logged message, and any error message # will be returned to the caller. # Returns `True` when the package description is fulfilled. + + @template def pkg_check_modules(var, package_desc, when=always, allow_missing=False): if isinstance(package_desc, (tuple, list)): package_desc = ' '.join(package_desc) package_desc = dependable(package_desc) @depends(when, '--enable-compile-environment')
--- a/build/moz.configure/rust.configure +++ b/build/moz.configure/rust.configure @@ -4,26 +4,28 @@ # 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/. # Rust is required by `rust_compiler` below. We allow_missing here # to propagate failures to the better error message there. rustc = check_prog('RUSTC', ['rustc'], allow_missing=True) cargo = check_prog('CARGO', ['cargo'], allow_missing=True) + @depends_if(rustc) @checking('rustc version', lambda info: info.version) def rustc_info(rustc): out = check_cmd_output(rustc, '--version', '--verbose').splitlines() info = dict((s.strip() for s in line.split(':', 1)) for line in out[1:]) return namespace( version=Version(info.get('release', '0')), commit=info.get('commit-hash', 'unknown'), ) + @depends_if(cargo) @checking('cargo version', lambda info: info.version) @imports('re') def cargo_info(cargo): out = check_cmd_output(cargo, '--version', '--verbose').splitlines() info = dict((s.strip() for s in line.split(':', 1)) for line in out[1:]) version = info.get('release') # Older versions of cargo didn't support --verbose, in which case, they @@ -38,16 +40,17 @@ def cargo_info(cargo): if not m: die('Could not determine cargo version from output: %s', out) version = m.group(1) return namespace( version=Version(version), ) + @depends(rustc_info, cargo_info) @imports(_from='textwrap', _import='dedent') def rust_compiler(rustc_info, cargo_info): if not rustc_info: die(dedent('''\ Rust compiler not found. To compile rust language sources, you must have 'rustc' in your path. See https://www.rust-lang.org/ for more information. @@ -168,17 +171,18 @@ def rust_triple_alias(host_or_target): rustc_target = rust_supported_targets.per_os.get( (host_or_target.cpu, host_or_target_os)) if rustc_target is None: rustc_target = rust_supported_targets.per_raw_os.get( (host_or_target.cpu, host_or_target_raw_os)) if rustc_target is None: - die("Don't know how to translate {} for rustc".format(host_or_target.alias)) + die("Don't know how to translate {} for rustc".format( + host_or_target.alias)) # Check to see whether our rustc has a reasonably functional stdlib # for our chosen target. target_arg = '--target=' + rustc_target.alias in_fd, in_path = mkstemp(prefix='conftest', suffix='.rs') out_fd, out_path = mkstemp(prefix='conftest', suffix='.rlib') os.close(out_fd) try: @@ -192,16 +196,17 @@ def rust_triple_alias(host_or_target): cmd = [ rustc, '--crate-type', 'staticlib', target_arg, '-o', out_path, in_path, ] + def failed(): die(dedent('''\ Cannot compile for {} with {} The target may be unsupported, or you may not have a rust std library for that target installed. Try: rustup target add {} '''.format(host_or_target.alias, rustc, rustc_target.alias))) @@ -212,25 +217,28 @@ def rust_triple_alias(host_or_target): os.remove(in_path) os.remove(out_path) # This target is usable. return rustc_target.alias return rust_target + rust_target_triple = rust_triple_alias(target) rust_host_triple = rust_triple_alias(host) set_config('RUST_TARGET', rust_target_triple) set_config('RUST_HOST_TARGET', rust_host_triple) + @depends(rust_target_triple) def rust_target_env_name(triple): - return triple.upper().replace('-','_') + return triple.upper().replace('-', '_') + # We need this to form various Cargo environment variables, as there is no # uppercase function in make, and we don't want to shell out just for # converting a string to uppercase. set_config('RUST_TARGET_ENV_NAME', rust_target_env_name) # This is used for putting source info into symbol files. set_config('RUSTC_COMMIT', depends(rustc_info)(lambda i: i.commit))
--- a/build/moz.configure/toolchain.configure +++ b/build/moz.configure/toolchain.configure @@ -10,32 +10,35 @@ option(env='MOZ_PGO', help='Build with p set_config('MOZ_PGO', depends('MOZ_PGO')(lambda x: bool(x))) add_old_configure_assignment('MOZ_PGO', depends('MOZ_PGO')(lambda x: bool(x))) # yasm detection # ============================================================== yasm = check_prog('YASM', ['yasm'], allow_missing=True) + @depends_if(yasm) @checking('yasm version') def yasm_version(yasm): version = check_cmd_output( yasm, '--version', onerror=lambda: die('Failed to get yasm version.') ).splitlines()[0].split()[1] return Version(version) + # Until we move all the yasm consumers out of old-configure. # bug 1257904 add_old_configure_assignment('_YASM_MAJOR_VERSION', yasm_version.major) add_old_configure_assignment('_YASM_MINOR_VERSION', yasm_version.minor) + @depends(yasm, target) def yasm_asflags(yasm, target): if yasm: asflags = { ('OSX', 'x86'): '-f macho32', ('OSX', 'x86_64'): '-f macho64', ('WINNT', 'x86'): '-f win32', ('WINNT', 'x86_64'): '-f x64', @@ -46,43 +49,49 @@ def yasm_asflags(yasm, target): if target.cpu == 'x86': asflags = '-f elf32' elif target.cpu == 'x86_64': asflags = '-f elf64' if asflags: asflags += ' -rnasm -pnasm' return asflags + set_config('YASM_ASFLAGS', yasm_asflags) + @depends(yasm_asflags) def have_yasm(value): if value: return True + set_config('HAVE_YASM', have_yasm) # Until the YASM variable is not necessary in old-configure. add_old_configure_assignment('YASM', have_yasm) # Android NDK # ============================================================== + @depends('--disable-compile-environment', build_project, '--help') def compiling_android(compile_env, build_project, _): return compile_env and build_project in ('mobile/android', 'js') + include('android-ndk.configure', when=compiling_android) # MacOS deployment target version # ============================================================== # This needs to happen before any compilation test is done. option('--enable-macos-target', env='MACOSX_DEPLOYMENT_TARGET', nargs=1, default='10.7', help='Set the minimum MacOS version needed at runtime') + @depends('--enable-macos-target', target) @imports(_from='os', _import='environ') def macos_target(value, target): if value and target.os == 'OSX': # Ensure every compiler process we spawn uses this value. environ['MACOSX_DEPLOYMENT_TARGET'] = value[0] return value[0] if value and value.origin != 'default': @@ -92,17 +101,18 @@ def macos_target(value, target): set_config('MACOSX_DEPLOYMENT_TARGET', macos_target) add_old_configure_assignment('MACOSX_DEPLOYMENT_TARGET', macos_target) # Xcode state # =========== js_option('--disable-xcode-checks', - help='Do not check that Xcode is installed and properly configured') + help='Do not check that Xcode is installed and properly configured') + @depends(host, '--disable-xcode-checks') def xcode_path(host, xcode_checks): if host.kernel != 'Darwin' or not xcode_checks: return # xcode-select -p prints the path to the installed Xcode. It # should exit 0 and return non-empty result if Xcode is installed. @@ -122,71 +132,83 @@ def xcode_path(host, xcode_checks): # Now look for the Command Line Tools. def no_cltools(): die('Could not find installed Xcode Command Line Tools; ' 'run `xcode-select --install` and follow the instructions ' 'to install them then try again; if you wish to build without ' 'Xcode Command Line Tools installed, ' 'add the --disable-xcode-checks configure flag') - res = check_cmd_output('pkgutil', '--pkg-info', - 'com.apple.pkg.CLTools_Executables', - onerror=no_cltools) + check_cmd_output('pkgutil', '--pkg-info', + 'com.apple.pkg.CLTools_Executables', + onerror=no_cltools) return xcode_path + set_config('XCODE_PATH', xcode_path) # Compiler wrappers # ============================================================== # Normally, we'd use js_option and automatically have those variables # propagated to js/src, but things are complicated by possible additional # wrappers in CC/CXX, and by other subconfigures that do not handle those # options and do need CC/CXX altered. option('--with-compiler-wrapper', env='COMPILER_WRAPPER', nargs=1, help='Enable compiling with wrappers such as distcc and ccache') option('--with-ccache', env='CCACHE', nargs='?', help='Enable compiling with ccache') + @depends_if('--with-ccache') def ccache(value): if len(value): return value # If --with-ccache was given without an explicit value, we default to # 'ccache'. return 'ccache' + ccache = check_prog('CCACHE', progs=(), input=ccache) # Distinguish ccache from sccache. + + @depends_if(ccache) def ccache_is_sccache(ccache): return check_cmd_output(ccache, '--version').startswith('sccache') + @depends(ccache, ccache_is_sccache) def using_ccache(ccache, ccache_is_sccache): return ccache and not ccache_is_sccache + @depends_if(ccache, ccache_is_sccache) def using_sccache(ccache, ccache_is_sccache): return ccache and ccache_is_sccache + set_config('MOZ_USING_CCACHE', using_ccache) set_config('MOZ_USING_SCCACHE', using_sccache) -option(env='SCCACHE_VERBOSE_STATS', help='Print verbose sccache stats after build') +option(env='SCCACHE_VERBOSE_STATS', + help='Print verbose sccache stats after build') + @depends(using_sccache, 'SCCACHE_VERBOSE_STATS') def sccache_verbose_stats(using_sccache, verbose_stats): return using_sccache and bool(verbose_stats) + set_config('SCCACHE_VERBOSE_STATS', sccache_verbose_stats) + @depends('--with-compiler-wrapper', ccache) @imports(_from='mozbuild.shellutil', _import='split', _as='shell_split') def compiler_wrapper(wrapper, ccache): if wrapper: raw_wrapper = wrapper[0] wrapper = shell_split(raw_wrapper) wrapper_program = find_program(wrapper[0]) if not wrapper_program: @@ -197,68 +219,78 @@ def compiler_wrapper(wrapper, ccache): if ccache: if wrapper: return tuple([ccache] + wrapper) else: return (ccache,) elif wrapper: return tuple(wrapper) + add_old_configure_assignment('COMPILER_WRAPPER', compiler_wrapper) + @depends_if(compiler_wrapper) def using_compiler_wrapper(compiler_wrapper): return True + set_config('MOZ_USING_COMPILER_WRAPPER', using_compiler_wrapper) # GC rooting and hazard analysis. # ============================================================== option(env='MOZ_HAZARD', help='Build for the GC rooting hazard analysis') + @depends('MOZ_HAZARD') def hazard_analysis(value): if value: return True + set_config('MOZ_HAZARD', hazard_analysis) # Cross-compilation related things. # ============================================================== js_option('--with-toolchain-prefix', env='TOOLCHAIN_PREFIX', nargs=1, help='Prefix for the target toolchain') + @depends('--with-toolchain-prefix', target, cross_compiling) def toolchain_prefix(value, target, cross_compiling): if value: return tuple(value) if cross_compiling: return ('%s-' % target.toolchain, '%s-' % target.alias) + @depends(toolchain_prefix, target) def first_toolchain_prefix(toolchain_prefix, target): # Pass TOOLCHAIN_PREFIX down to the build system if it was given from the # command line/environment (in which case there's only one value in the tuple), # or when cross-compiling for Android. if toolchain_prefix and (target.os == 'Android' or len(toolchain_prefix) == 1): return toolchain_prefix[0] + set_config('TOOLCHAIN_PREFIX', first_toolchain_prefix) add_old_configure_assignment('TOOLCHAIN_PREFIX', first_toolchain_prefix) # Compilers # ============================================================== include('compilers-util.configure') + def try_preprocess(compiler, language, source): return try_invoke_compiler(compiler, language, source, ['-E']) + @imports(_from='mozbuild.configure.constants', _import='CompilerType') @imports(_from='mozbuild.configure.constants', _import='CPU_preprocessor_checks') @imports(_from='mozbuild.configure.constants', _import='kernel_preprocessor_checks') @imports(_from='textwrap', _import='dedent') def get_compiler_info(compiler, language): '''Returns information about the given `compiler` (command line in the @@ -427,17 +459,17 @@ def check_compiler(compiler, language, t append_flag('-std=gnu++11') # MSVC 2015 headers include C++14 features, but don't guard them # with appropriate checks. if info.type == 'clang-cl' and info.language_version != cxx14_version: append_flag('-std=c++14') # GCC 4.9 indicates that it implements draft C++14 features # instead of the full language. elif info.type == 'gcc' and not \ - (info.language_version == draft_cxx14_version or info.language_version == cxx14_version): + (info.language_version == draft_cxx14_version or info.language_version == cxx14_version): append_flag('-std=gnu++14') # We force clang-cl to emulate Visual C++ 2015 Update 3. if info.type == 'clang-cl' and info.version != '19.00.24213': # This flag is a direct clang-cl flag that doesn't need -Xclang, # add it directly. flags.append('-fms-compatibility-version=19.00.24213') @@ -496,34 +528,39 @@ def get_vc_paths(topsrcdir): yield (Version(install['installationVersion']), { 'x64': [os.path.join(path, r'VC\bin\amd64')], # The x64->x86 cross toolchain requires DLLs from the native x64 toolchain. 'x86': [os.path.join(path, r'VC\bin\amd64_x86'), os.path.join(path, r'VC\bin\amd64')], }) # Then VS2017 and newer. for install in vswhere(['-requires', 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64']): path = install['installationPath'] - tools_version = open(os.path.join(path, r'VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt'), 'rb').read().strip() - tools_path = os.path.join(path, r'VC\Tools\MSVC', tools_version, r'bin\HostX64') + tools_version = open(os.path.join( + path, r'VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt'), 'rb').read().strip() + tools_path = os.path.join( + path, r'VC\Tools\MSVC', tools_version, r'bin\HostX64') yield (Version(install['installationVersion']), { 'x64': [os.path.join(tools_path, 'x64')], # The x64->x86 cross toolchain requires DLLs from the native x64 toolchain. 'x86': [os.path.join(tools_path, 'x86'), os.path.join(tools_path, 'x64')], }) + js_option('--with-visual-studio-version', nargs=1, choices=('2015', '2017'), help='Select a specific Visual Studio version to use') + @depends('--with-visual-studio-version') def vs_major_version(value): if value: return {'2015': 14, '2017': 15}[value[0]] + @depends(host, target, vs_major_version, check_build_environment, '--with-visual-studio-version') @imports(_from='__builtin__', _import='sorted') @imports(_from='operator', _import='itemgetter') @imports('platform') def vc_compiler_path(host, target, vs_major_version, env, vs_release_name): if host.kernel != 'WINNT': return vc_target = { @@ -533,17 +570,18 @@ def vc_compiler_path(host, target, vs_ma }.get(target.cpu) if vc_target is None: return all_versions = sorted(get_vc_paths(env.topsrcdir), key=itemgetter(0)) if not all_versions: return if vs_major_version: - versions = [d for (v, d) in all_versions if v.major == vs_major_version] + versions = [d for (v, d) in all_versions if v.major == + vs_major_version] if not versions: die('Visual Studio %s could not be found!' % vs_release_name) data = versions[0] else: # Choose the newest version. data = all_versions[-1][1] paths = data.get(vc_target) if not paths: @@ -649,17 +687,17 @@ def compiler(language, host_or_target, c ('C++', host): 'HOST_CXX', }[language, host_or_target] default_compilers = { 'C': lambda: default_c_compilers(host_or_target), 'C++': lambda: default_cxx_compilers(c_compiler), }[language]() - what='the %s %s compiler' % (host_or_target_str, language) + what = 'the %s %s compiler' % (host_or_target_str, language) option(env=var, nargs=1, help='Path to %s' % what) # Handle the compiler given by the user through one of the CC/CXX/HOST_CC/ # HOST_CXX variables. @depends_if(var) @imports(_from='itertools', _import='takewhile') @imports(_from='mozbuild.shellutil', _import='split', _as='shell_split') @@ -882,29 +920,28 @@ def compiler(language, host_or_target, c def compiler_error(): raise FatalCheckError('Failed compiling a simple %s source with %s' % (language, what)) valid_compiler.try_compile(check_msg='%s works' % what, onerror=compiler_error) - # Set CPP/CXXCPP for both the build system and old-configure. We don't # need to check this works for preprocessing, because we already relied # on $CC -E/$CXX -E doing preprocessing work to validate the compiler # in the first place. if host_or_target == target: pp_var = { 'C': 'CPP', 'C++': 'CXXCPP', }[language] preprocessor = depends_if(valid_compiler)( - lambda x: list(x.wrapper) + [x.compiler, '-E'] + list(x.flags)) + lambda x: list(x.wrapper) + [x.compiler, '-E'] + list(x.flags)) set_config(pp_var, preprocessor) add_old_configure_assignment(pp_var, preprocessor) if language == 'C': linker_var = { target: 'LD', host: 'HOST_LD', @@ -937,92 +974,103 @@ host_c_compiler = compiler('C', host, ot host_cxx_compiler = compiler('C++', host, c_compiler=host_c_compiler, other_compiler=cxx_compiler, other_c_compiler=c_compiler) # Generic compiler-based conditions. non_msvc_compiler = depends(c_compiler)(lambda info: info.type != 'msvc') building_with_gcc = depends(c_compiler)(lambda info: info.type == 'gcc') + @depends(c_compiler) def msvs_version(info): # clang-cl emulates the same version scheme as cl. And MSVS_VERSION needs to # be set for GYP on Windows. if info.type in ('clang-cl', 'msvc'): if info.version >= '19.10': return '2017' elif info.version >= '19.00': return '2015' return '' + set_config('MSVS_VERSION', msvs_version) include('compile-checks.configure') + @depends(have_64_bit, try_compile(body='static_assert(sizeof(void *) == 8, "")', check_msg='for 64-bit OS')) def check_have_64_bit(have_64_bit, compiler_have_64_bit): if have_64_bit != compiler_have_64_bit: configure_error('The target compiler does not agree with configure ' 'about the target bitness.') + option(env='BINDGEN_CFLAGS', nargs=1, default=bindgen_cflags_defaults, help='Options bindgen should pass to the C/C++ parser') + @depends('BINDGEN_CFLAGS') @checking('bindgen cflags', lambda s: s if s and s.strip() else 'no') def bindgen_cflags(value): if value and len(value): # Reformat the env value for substitution into a toml list. flags = value[0].split() return ', '.join('"' + flag + '"' for flag in flags) return '' + set_config('BINDGEN_CFLAGS', bindgen_cflags) + @depends(c_compiler) def default_debug_flags(compiler_info): # Debug info is ON by default. if compiler_info.type in ('msvc', 'clang-cl'): return '-Zi' return '-g' + option(env='MOZ_DEBUG_FLAGS', nargs=1, help='Debug compiler flags') imply_option('--enable-debug-symbols', depends_if('--enable-debug')(lambda v: v)) js_option('--enable-debug-symbols', nargs='?', default=True, help='Enable debug symbols using the given compiler flags') set_config('MOZ_DEBUG_SYMBOLS', depends_if('--enable-debug-symbols')(lambda _: True)) + @depends('MOZ_DEBUG_FLAGS', '--enable-debug-symbols', default_debug_flags) def debug_flags(env_debug_flags, enable_debug_flags, default_debug_flags): # If MOZ_DEBUG_FLAGS is set, and --enable-debug-symbols is set to a value, # --enable-debug-symbols takes precedence. Note, the value of # --enable-debug-symbols may be implied by --enable-debug. if len(enable_debug_flags): return enable_debug_flags[0] if env_debug_flags: return env_debug_flags[0] return default_debug_flags + set_config('MOZ_DEBUG_FLAGS', debug_flags) add_old_configure_assignment('MOZ_DEBUG_FLAGS', debug_flags) + @depends(c_compiler) def color_cflags(info): # We could test compiling with flags. By why incur the overhead when # color support should always be present in a specific toolchain # version? # Code for auto-adding this flag to compiler invocations needs to # determine if an existing flag isn't already present. That is likely @@ -1032,16 +1080,17 @@ def color_cflags(info): # before adding flags to return values. if info.type == 'gcc' and info.version >= '4.9.0': return '-fdiagnostics-color' elif info.type == 'clang': return '-fcolor-diagnostics' else: return '' + set_config('COLOR_CFLAGS', color_cflags) # Some standard library headers (notably bionic on Android) declare standard # functions (e.g. getchar()) and also #define macros for those standard # functions. libc++ deals with this by doing something like the following # (explanatory comments added): # # #ifdef FUNC @@ -1073,47 +1122,55 @@ set_config('COLOR_CFLAGS', color_cflags) # However, libc++ will only define _LIBCPP_INLINE_VISIBILITY if there is no # existing definition. We can therefore define it to the empty string (since # we are properly managing visibility ourselves) and avoid this whole mess. # Note that we don't need to do this with gcc, as libc++ detects gcc and # effectively does the same thing we are doing here. # # _LIBCPP_ALWAYS_INLINE needs similar workarounds, since it too declares # hidden visibility. + + @depends(c_compiler, target) def libcxx_override_visibility(c_compiler, target): if c_compiler.type == 'clang' and target.os == 'Android': return '' + set_define('_LIBCPP_INLINE_VISIBILITY', libcxx_override_visibility) -set_define('_LIBCPP_INLINE_VISIBILITY_EXCEPT_GCC49', libcxx_override_visibility) +set_define('_LIBCPP_INLINE_VISIBILITY_EXCEPT_GCC49', + libcxx_override_visibility) set_define('_LIBCPP_ALWAYS_INLINE', libcxx_override_visibility) set_define('_LIBCPP_ALWAYS_INLINE_EXCEPT_GCC49', libcxx_override_visibility) + @depends(target, check_build_environment) def visibility_flags(target, env): if target.os != 'WINNT': if target.kernel == 'Darwin': return ('-fvisibility=hidden', '-fvisibility-inlines-hidden') return ('-I%s/system_wrappers' % os.path.join(env.dist), '-include', '%s/config/gcc_hidden.h' % env.topsrcdir) + @depends(target, visibility_flags) def wrap_system_includes(target, visibility_flags): if visibility_flags and target.kernel != 'Darwin': return True + set_define('HAVE_VISIBILITY_HIDDEN_ATTRIBUTE', depends(visibility_flags)(lambda v: bool(v) or None)) set_define('HAVE_VISIBILITY_ATTRIBUTE', depends(visibility_flags)(lambda v: bool(v) or None)) set_config('WRAP_SYSTEM_INCLUDES', wrap_system_includes) set_config('VISIBILITY_FLAGS', visibility_flags) + @depends(c_compiler) @imports('multiprocessing') @imports(_from='__builtin__', _import='min') def pgo_flags(compiler): if compiler.type in ('gcc', 'clang'): return namespace( gen_cflags=['-fprofile-generate'], gen_ldflags=['-fprofile-generate'], @@ -1137,75 +1194,84 @@ def pgo_flags(compiler): # optimization/PGO case. I think it's probably a compiler bug, # but we work around it here. use_cflags=['-GL', '-wd4624', '-wd4952'], # XXX: should be -LTCG:PGOPTIMIZE, but that fails on libxul. # Probably also a compiler bug, but what can you do? use_ldflags=['-LTCG:PGUPDATE', cgthreads], ) + set_config('PROFILE_GEN_CFLAGS', pgo_flags.gen_cflags) set_config('PROFILE_GEN_LDFLAGS', pgo_flags.gen_ldflags) set_config('PROFILE_USE_CFLAGS', pgo_flags.use_cflags) set_config('PROFILE_USE_LDFLAGS', pgo_flags.use_ldflags) # We only want to include windows.configure when we are compiling on # Windows, for Windows. + + @depends(target, host) def is_windows(target, host): return host.kernel == 'WINNT' and target.kernel == 'WINNT' + include('windows.configure', when=is_windows) # Shader Compiler for Windows (and MinGW Cross Compile) # ============================================================== fxc = check_prog('FXC', ('fxc.exe', 'fxc2.exe'), when=depends(target) (lambda t: t.kernel == 'WINNT')) wine = check_prog('WINE', ['wine'], when=depends(target, host) (lambda t, h: t.kernel == 'WINNT' and h.kernel == 'Linux')) # Security Hardening # ============================================================== option('--enable-hardening', env='MOZ_SECURITY_HARDENING', help='Enables security hardening compiler options') + @depends('--enable-hardening', c_compiler) def security_hardening_cflags(value, c_compiler): if value and c_compiler.type in ['gcc', 'clang']: return '-fstack-protector-strong' + add_old_configure_assignment('HARDENING_CFLAGS', security_hardening_cflags) imply_option('--enable-pie', depends_if('--enable-hardening')(lambda v: v)) option(env='RUSTFLAGS', nargs=1, help='Rust compiler flags') set_config('RUSTFLAGS', depends('RUSTFLAGS')(lambda flags: flags)) imply_option('--enable-release', mozilla_official) imply_option('--enable-release', depends_if('MOZ_AUTOMATION')(lambda x: True)) js_option('--enable-release', help='Build with more conservative, release engineering-oriented ' 'options. This may slow down builds.') + @depends('--enable-release') def developer_options(value): if not value: return True + add_old_configure_assignment('DEVELOPER_OPTIONS', developer_options) set_config('DEVELOPER_OPTIONS', developer_options) # Linker detection # ============================================================== + @depends(target) def is_linker_option_enabled(target): if target.kernel not in ('Darwin', 'WINNT', 'SunOS'): return True option('--enable-gold', env='MOZ_FORCE_GOLD', @@ -1224,17 +1290,18 @@ def enable_gnu_linker(enable_gold_option if toolchain_flags: cmd_base += toolchain_flags def resolve_gold(): # Try to force the usage of gold targetDir = os.path.join(build_env.topobjdir, 'build', 'unix', 'gold') gold_detection_arg = '-print-prog-name=ld.gold' - gold = check_cmd_output(c_compiler.compiler, gold_detection_arg).strip() + gold = check_cmd_output(c_compiler.compiler, + gold_detection_arg).strip() if not gold: return goldFullPath = find_program(gold) if goldFullPath is None: return if os.path.exists(targetDir): @@ -1280,51 +1347,57 @@ def enable_gnu_linker(enable_gold_option KIND='gold' ) # For other platforms without gold or the GNU linker return namespace( KIND='other' ) + js_option('--enable-linker', nargs=1, choices=('bfd', 'gold', 'lld', 'other'), help='Select the linker', when=is_linker_option_enabled) + @depends('--enable-linker', c_compiler, developer_options, check_build_environment, extra_toolchain_flags, when=is_linker_option_enabled) @checking('for linker', lambda x: x.KIND) def select_linker(linker, c_compiler, developer_options, build_env, toolchain_flags): linker = linker[0] if linker else 'other' if linker in ('gold', 'bfd', 'other'): return enable_gnu_linker(linker == 'gold', c_compiler, developer_options, build_env, toolchain_flags, linker) if linker == 'lld': version_check = ['-Wl,--version'] - cmd_base = c_compiler.wrapper + [c_compiler.compiler] + c_compiler.flags + cmd_base = c_compiler.wrapper + \ + [c_compiler.compiler] + c_compiler.flags lld = "-fuse-ld=" + linker cmd = cmd_base + [lld] + version_check if 'LLD' in check_cmd_output(*cmd).decode('utf-8'): return namespace( KIND='lld', LINKER_FLAG=lld, ) else: die("Could not use lld as linker") -set_config('LD_IS_BFD', depends(select_linker.KIND)(lambda x: x == 'bfd' or None)) +set_config('LD_IS_BFD', depends(select_linker.KIND) + (lambda x: x == 'bfd' or None)) set_config('LINKER_LDFLAGS', select_linker.LINKER_FLAG) # Code Coverage # ============================================================== js_option('--enable-coverage', env='MOZ_CODE_COVERAGE', - help='Enable code coverage') + help='Enable code coverage') + @depends('--enable-coverage') def code_coverage(value): if value: return True + set_config('MOZ_CODE_COVERAGE', code_coverage) set_define('MOZ_CODE_COVERAGE', code_coverage)
--- a/build/moz.configure/util.configure +++ b/build/moz.configure/util.configure @@ -1,14 +1,15 @@ # -*- Mode: python; 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/. + @imports('sys') def die(*args): 'Print an error and terminate configure.' log.error(*args) sys.exit(1) @imports(_from='mozbuild.configure', _import='ConfigureError') @@ -17,16 +18,18 @@ def configure_error(message): Primarily for use in moz.configure templates to sanity check their inputs from moz.configure usage.''' raise ConfigureError(message) # A wrapper to obtain a process' output that returns the output generated # by running the given command if it exits normally, and streams that # output to log.debug and calls die or the given error callback if it # does not. + + @imports(_from='__builtin__', _import='unicode') @imports('subprocess') @imports('sys') @imports(_from='mozbuild.configure.util', _import='LineIO') @imports(_from='mozbuild.shellutil', _import='quote') def check_cmd_output(*args, **kwargs): onerror = kwargs.pop('onerror', None) @@ -62,16 +65,17 @@ def check_cmd_output(*args, **kwargs): log.debug('Its %s was:', desc) with LineIO(lambda l: log.debug('| %s', l)) as o: o.write(out) if onerror: return onerror() die('Command `%s` failed with exit status %d.' % (quote(*args), retcode)) + @imports('os') def is_absolute_or_relative(path): if os.altsep and os.altsep in path: return True return os.sep in path @imports(_import='mozpack.path', _as='mozpath') @@ -83,17 +87,18 @@ def normsep(path): @imports(_from='ctypes', _import='wintypes') @imports(_from='mozbuild.configure.constants', _import='WindowsBinaryType') def windows_binary_type(path): """Obtain the type of a binary on Windows. Returns WindowsBinaryType constant. """ GetBinaryTypeW = ctypes.windll.kernel32.GetBinaryTypeW - GetBinaryTypeW.argtypes = [wintypes.LPWSTR, wintypes.POINTER(wintypes.DWORD)] + GetBinaryTypeW.argtypes = [wintypes.LPWSTR, + wintypes.POINTER(wintypes.DWORD)] GetBinaryTypeW.restype = wintypes.BOOL bin_type = wintypes.DWORD() res = GetBinaryTypeW(path, ctypes.byref(bin_type)) if not res: die('could not obtain binary type of %s' % path) if bin_type.value == 0: @@ -142,16 +147,17 @@ def normalize_path(): size = needed else: def normalize_path(path): return normsep(path) return normalize_path + normalize_path = normalize_path() # Locates the given program using which, or returns the given path if it # exists. # The `paths` parameter may be passed to search the given paths instead of # $PATH. @imports(_from='which', _import='which') @@ -359,16 +365,18 @@ def Version(v): # Denotes a deprecated option. Combines option() and @depends: # @deprecated_option('--option') # def option(value): # ... # @deprecated_option() takes the same arguments as option(), except `help`. # The function may handle the option like a typical @depends function would, # but it is recommended it emits a deprecation error message suggesting an # alternative option to use if there is one. + + @template def deprecated_option(*args, **kwargs): assert 'help' not in kwargs kwargs['help'] = 'Deprecated' opt = option(*args, **kwargs) def decorator(func): @depends(opt.option) @@ -409,16 +417,17 @@ never = dependable(False) # arguments. @template def depends_tmpl(eval_args_fn, *args, **kwargs): if kwargs: assert len(kwargs) == 1 when = kwargs['when'] else: when = None + def decorator(func): @depends(*args, when=when) def wrapper(*args): if eval_args_fn(args): return func(*args) return wrapper return decorator @@ -439,20 +448,22 @@ def depends_all(*args, **kwargs): # Hacks related to old-configure # ============================== @dependable def old_configure_assignments(): return [] + @dependable def extra_old_configure_args(): return [] + @template def add_old_configure_assignment(var, value): var = dependable(var) value = dependable(value) @depends(old_configure_assignments, var, value) @imports(_from='mozbuild.shellutil', _import='quote') def add_assignment(assignments, var, value): @@ -462,14 +473,15 @@ def add_old_configure_assignment(var, va assignments.append('%s=1' % var) elif value is False: assignments.append('%s=' % var) else: if isinstance(value, (list, tuple)): value = quote(*value) assignments.append('%s=%s' % (var, quote(str(value)))) + @template def add_old_configure_arg(arg): @depends(extra_old_configure_args, arg) def add_arg(args, arg): if arg: args.append(arg)
--- a/build/moz.configure/windows.configure +++ b/build/moz.configure/windows.configure @@ -3,16 +3,17 @@ # 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/. option('--with-windows-version', nargs=1, default='603', help='Windows SDK version to target. Win 8.1 (603) is currently' 'the minimum supported version.') + @depends('--with-windows-version') @imports(_from='__builtin__', _import='ValueError') def valid_windows_version(value): if not value: die('Cannot build with --without-windows-version') try: version = int(value[0], 16) if version in (0x603,): @@ -21,16 +22,17 @@ def valid_windows_version(value): pass die('Invalid value for --with-windows-version (%s)', value[0]) option(env='WINDOWSSDKDIR', nargs=1, help='Directory containing the Windows SDK') + @depends('WINDOWSSDKDIR', host) def windows_sdk_dir(value, host): if value: return value if host.kernel != 'WINNT': return () return set(x[1] for x in get_registry_values( @@ -39,16 +41,18 @@ def windows_sdk_dir(value, host): # The Windows SDK 8.1 and 10 have different layouts. The former has # $SDK/include/$subdir, while the latter has $SDK/include/$version/$subdir. # The vcvars* scripts don't actually care about the version, they just take # the last alphanumerically. # The $SDK/lib directories always have version subdirectories, but while the # versions match the one in $SDK/include for SDK 10, it's "winv6.3" for SDK # 8.1. + + @imports('os') @imports('re') @imports(_from='__builtin__', _import='sorted') @imports(_from='__builtin__', _import='WindowsError') def get_sdk_dirs(sdk, subdir): def get_dirs_containing(sdk, stem, subdir): base = os.path.join(sdk, stem) try: @@ -84,16 +88,17 @@ def get_sdk_dirs(sdk, subdir): ) @imports(_from='mozbuild.shellutil', _import='quote') def valid_windows_sdk_dir_result(value): if value: return '0x%04x in %s' % (value.version, quote(value.path)) + @depends(c_compiler, windows_sdk_dir, valid_windows_version, 'WINDOWSSDKDIR') @checking('for Windows SDK', valid_windows_sdk_dir_result) @imports(_from='__builtin__', _import='sorted') @imports(_from='textwrap', _import='dedent') def valid_windows_sdk_dir(compiler, windows_sdk_dir, target_version, windows_sdk_dir_env): if windows_sdk_dir_env: windows_sdk_dir_env = windows_sdk_dir_env[0] @@ -160,16 +165,17 @@ add_old_configure_assignment( lambda x: '0x%04X0000' % x.version if x else None)) @imports(_from='mozbuild.shellutil', _import='quote') def valid_ucrt_sdk_dir_result(value): if value: return '%s in %s' % (value.version, quote(value.path)) + @depends(windows_sdk_dir, 'WINDOWSSDKDIR') @checking('for Universal CRT SDK', valid_ucrt_sdk_dir_result) @imports('os') @imports(_from='__builtin__', _import='sorted') @imports(_import='mozpack.path', _as='mozpath') def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env): if windows_sdk_dir_env: windows_sdk_dir_env = windows_sdk_dir_env[0] @@ -221,17 +227,17 @@ def valid_ucrt_sdk_dir(windows_sdk_dir, raise FatalCheckError('Cannot find the Universal CRT SDK. ' 'Please install it.') version, sdk = sdks[valid_sdks[0]] minimum_ucrt_version = Version('10.0.10586.0') if version < minimum_ucrt_version: raise FatalCheckError('Latest Universal CRT SDK version found %s' ' and minimum required is %s.' - % (version, minimum_ucrt_version)) + % (version, minimum_ucrt_version)) return namespace( path=sdk.path, include=sdk.include, lib=sdk.lib, version=version, ) @@ -262,17 +268,18 @@ def vc_path(c_compiler): @imports(_from='os.path', _import='isdir') def dia_sdk_dir(vc_path, c_compiler): if vc_path: if c_compiler.version < '19.10': path = os.path.join(os.path.dirname(vc_path), 'DIA SDK') else: # This would be easier if we had the installationPath that # get_vc_paths works with, since 'DIA SDK' is relative to that. - path = os.path.normpath(os.path.join(vc_path, r'..\..\..\..\DIA SDK')) + path = os.path.normpath(os.path.join( + vc_path, r'..\..\..\..\DIA SDK')) if isdir(path): return path @depends(vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir, dia_sdk_dir) @imports('os') def include_path(vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir): if not vc_path: @@ -301,16 +308,17 @@ def include_path(vc_path, windows_sdk_di )) if dia_sdk_dir: includes.append(os.path.join(dia_sdk_dir, 'include')) # Set in the environment for old-configure includes = os.pathsep.join(includes) os.environ['INCLUDE'] = includes return includes + set_config('INCLUDE', include_path) @depends(target, c_compiler, vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir, dia_sdk_dir) @imports('os') def lib_path(target, c_compiler, vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir): if not vc_path: return @@ -358,21 +366,23 @@ def lib_path(target, c_compiler, vc_path # For some reason the DIA SDK still uses the old-style targets # even in a newer MSVC. libs.append(os.path.join(dia_sdk_dir, 'lib', *old_target)) # Set in the environment for old-configure libs = os.pathsep.join(libs) os.environ['LIB'] = libs return libs + set_config('LIB', lib_path) option(env='MT', nargs=1, help='Path to the Microsoft Manifest Tool') + @depends(valid_windows_sdk_dir, valid_ucrt_sdk_dir) @imports(_from='os', _import='environ') @imports('platform') def sdk_bin_path(valid_windows_sdk_dir, valid_ucrt_sdk_dir): if not valid_windows_sdk_dir: return vc_host = { @@ -403,17 +413,17 @@ mt = check_prog('MT', ('mt.exe',), input @checking('whether MT is really Microsoft Manifest Tool', lambda x: bool(x)) @imports('subprocess') def valid_mt(path): try: out = subprocess.check_output([path]).splitlines() out = '\n'.join(l for l in out if 'Microsoft (R) Manifest Tool' in l) if out: - return path + return path except subprocess.CalledProcessError: pass raise FatalCheckError('%s is not Microsoft Manifest Tool') set_config('MSMANIFEST_TOOL', depends(valid_mt)(lambda x: bool(x))) @@ -428,12 +438,12 @@ add_old_configure_assignment('LINK', lin # valid_compiler(). @depends(sdk_bin_path) @imports('os') def alter_path(sdk_bin_path): path = os.pathsep.join(sdk_bin_path) os.environ['PATH'] = path return path + set_config('PATH', alter_path) check_prog('MAKECAB', ('makecab.exe',)) -
--- a/tools/lint/flake8.yml +++ b/tools/lint/flake8.yml @@ -1,12 +1,13 @@ --- flake8: description: Python linter include: + - build/moz.configure/*.configure - config/check_macroassembler_style.py - config/mozunit.py - layout/tools/reftest - python/mach - python/mach_commands.py - python/mozlint - python/mozversioncontrol - security/manager