Bug 1231315 - Build CONFIGURE_DEFINE_FILES at build time instead of during configure. r=gps

This commit is contained in:
Mike Hommey 2015-12-08 20:21:09 +09:00
parent 3c29698cac
commit 6874992719
7 changed files with 99 additions and 102 deletions

View File

@ -0,0 +1,94 @@
# 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/.
from __future__ import absolute_import, print_function, unicode_literals
import argparse
import os
import re
import sys
from buildconfig import topobjdir
from mozbuild.backend.configenvironment import ConfigEnvironment
from mozbuild.util import FileAvoidWrite
import mozpack.path as mozpath
def process_define_file(output, input):
'''Creates the given config header. A config header is generated by
taking the corresponding source file and replacing some #define/#undef
occurences:
"#undef NAME" is turned into "#define NAME VALUE"
"#define NAME" is unchanged
"#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE"
"#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
Whitespaces are preserved.
As a special rule, "#undef ALLDEFINES" is turned into "#define NAME
VALUE" for all the defined variables.
'''
path = os.path.abspath(input)
config = ConfigEnvironment.from_config_status(
mozpath.join(topobjdir, 'config.status'))
if mozpath.basedir(path,
[mozpath.join(config.topsrcdir, 'js/src')]) and \
not config.substs.get('JS_STANDALONE'):
config = ConfigEnvironment.from_config_status(
mozpath.join(topobjdir, 'js', 'src', 'config.status'))
with open(path, 'rU') as input:
r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
for l in input:
m = r.match(l)
if m:
cmd = m.group('cmd')
name = m.group('name')
value = m.group('value')
if name:
if name == 'ALLDEFINES':
if cmd == 'define':
raise Exception(
'`#define ALLDEFINES` is not allowed in a '
'CONFIGURE_DEFINE_FILE')
defines = '\n'.join(sorted(
'#define %s %s' % (name, val)
for name, val in config.defines.iteritems()
if name not in config.non_global_defines))
l = l[:m.start('cmd') - 1] \
+ defines + l[m.end('name'):]
elif name in config.defines:
if cmd == 'define' and value:
l = l[:m.start('value')] \
+ str(config.defines[name]) \
+ l[m.end('value'):]
elif cmd == 'undef':
l = l[:m.start('cmd')] \
+ 'define' \
+ l[m.end('cmd'):m.end('name')] \
+ ' ' \
+ str(config.defines[name]) \
+ l[m.end('name'):]
elif cmd == 'undef':
l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
output.write(l)
return {config.source}
def main(argv):
parser = argparse.ArgumentParser(
description='Process define files.')
parser.add_argument('input', help='Input define file.')
args = parser.parse_args(argv)
return process_define_file(sys.stdout, args.input)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

View File

@ -17,7 +17,6 @@ from .base import BuildBackend
from ..frontend.data import (
ConfigFileSubstitution,
ExampleWebIDLInterface,
HeaderFileSubstitution,
IPDLFile,
GeneratedEventWebIDLFile,
GeneratedWebIDLFile,
@ -211,10 +210,6 @@ class CommonBackend(BuildBackend):
pp.do_include(obj.input_path)
self.backend_input_files.add(obj.input_path)
elif isinstance(obj, HeaderFileSubstitution):
self._create_config_header(obj)
self.backend_input_files.add(obj.input_path)
# We should consider aggregating WebIDL types in emitter.py.
elif isinstance(obj, WebIDLFile):
self._webidls.sources.add(mozpath.join(obj.srcdir, obj.basename))
@ -372,54 +367,3 @@ class CommonBackend(BuildBackend):
for unified_file, source_filenames in unified_source_mapping:
self._write_unified_file(unified_file, source_filenames,
output_directory, poison_windows_h)
def _create_config_header(self, obj):
'''Creates the given config header. A config header is generated by
taking the corresponding source file and replacing some #define/#undef
occurences:
"#undef NAME" is turned into "#define NAME VALUE"
"#define NAME" is unchanged
"#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE"
"#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
Whitespaces are preserved.
As a special rule, "#undef ALLDEFINES" is turned into "#define NAME
VALUE" for all the defined variables.
'''
with self._write_file(obj.output_path) as fh, \
open(obj.input_path, 'rU') as input:
r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
for l in input:
m = r.match(l)
if m:
cmd = m.group('cmd')
name = m.group('name')
value = m.group('value')
if name:
if name == 'ALLDEFINES':
if cmd == 'define':
raise Exception(
'`#define ALLDEFINES` is not allowed in a '
'CONFIGURE_DEFINE_FILE')
defines = '\n'.join(sorted(
'#define %s %s' % (name, val)
for name, val in obj.config.defines.iteritems()
if name not in obj.config.non_global_defines))
l = l[:m.start('cmd') - 1] \
+ defines + l[m.end('name'):]
elif name in obj.config.defines:
if cmd == 'define' and value:
l = l[:m.start('value')] \
+ str(obj.config.defines[name]) \
+ l[m.end('value'):]
elif cmd == 'undef':
l = l[:m.start('cmd')] \
+ 'define' \
+ l[m.end('cmd'):m.end('name')] \
+ ' ' \
+ str(obj.config.defines[name]) \
+ l[m.end('name'):]
elif cmd == 'undef':
l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
fh.write(l)

View File

@ -127,10 +127,6 @@ class ConfigFileSubstitution(BaseConfigSubstitution):
"""Describes a config file that will be generated using substitutions."""
class HeaderFileSubstitution(BaseConfigSubstitution):
"""Describes a header file that will be generated using substitutions."""
class VariablePassthru(ContextDerived):
"""A dict of variables to pass through to backend.mk unaltered.

View File

@ -44,7 +44,6 @@ from .data import (
ExampleWebIDLInterface,
ExternalStaticLibrary,
ExternalSharedLibrary,
HeaderFileSubstitution,
HostDefines,
HostLibrary,
HostProgram,
@ -549,8 +548,10 @@ class TreeMetadataEmitter(LoggingMixin):
path)
for path in context['CONFIGURE_DEFINE_FILES']:
yield self._create_substitution(HeaderFileSubstitution, context,
path)
script = mozpath.join(mozpath.dirname(mozpath.dirname(__file__)),
'action', 'process_define_files.py')
yield GeneratedFile(context, script, 'process_define_file', path,
[mozpath.join(context.srcdir, path + '.in')])
for obj in self._process_xpidl(context):
yield obj

View File

@ -1,15 +0,0 @@
/* Comment */
#define foo
#define foo 42
#undef foo
#define bar
#define bar 42
#undef bar
# undef baz
#ifdef foo
# undef foo
# define foo 42
# define foo 42
#endif

View File

@ -1,6 +1,3 @@
CONFIGURE_SUBST_FILES = [
'file',
]
CONFIGURE_DEFINE_FILES = [
'file.h',
]

View File

@ -698,8 +698,7 @@ class TestRecursiveMakeBackend(BackendTester):
self.assertEqual(found, expected)
def test_config(self):
"""Test that CONFIGURE_SUBST_FILES and CONFIGURE_DEFINE_FILES are
properly handled."""
"""Test that CONFIGURE_SUBST_FILES are properly handled."""
env = self._consume('test_config', RecursiveMakeBackend)
self.assertEqual(
@ -709,25 +708,6 @@ class TestRecursiveMakeBackend(BackendTester):
'@bar@\n',
])
self.assertEqual(
open(os.path.join(env.topobjdir, 'file.h'), 'r').readlines(), [
'/* Comment */\n',
'#define foo\n',
'#define foo baz qux\n',
'#define foo baz qux\n',
'#define bar\n',
'#define bar 42\n',
'/* #undef bar */\n',
'\n',
'# define baz 1\n',
'\n',
'#ifdef foo\n',
'# define foo baz qux\n',
'# define foo baz qux\n',
' # define foo baz qux \n',
'#endif\n',
])
def test_jar_manifests(self):
env = self._consume('jar-manifests', RecursiveMakeBackend)