mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
align changes from rmottola/Arctic-Fox (rev e67e868c) to our tree Part 2: mozbuild changes
This commit is contained in:
@@ -20,6 +20,8 @@ def main(argv):
|
||||
add_help=False)
|
||||
parser.add_argument('python_script', metavar='python-script', type=str,
|
||||
help='The Python script to run')
|
||||
parser.add_argument('method_name', metavar='method-name', type=str,
|
||||
help='The method of the script to invoke')
|
||||
parser.add_argument('output_file', metavar='output-file', type=str,
|
||||
help='The file to generate')
|
||||
parser.add_argument('additional_arguments', metavar='arg', nargs='*',
|
||||
@@ -31,15 +33,16 @@ def main(argv):
|
||||
with open(script, 'r') as fh:
|
||||
module = imp.load_module('script', fh, script,
|
||||
('.py', 'r', imp.PY_SOURCE))
|
||||
if not hasattr(module, 'main'):
|
||||
print('Error: script "{0}" is missing a main method'.format(script),
|
||||
method = args.method_name
|
||||
if not hasattr(module, method):
|
||||
print('Error: script "{0}" is missing a {1} method'.format(script, method),
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
|
||||
ret = 1
|
||||
try:
|
||||
with FileAvoidWrite(args.output_file) as output:
|
||||
ret = module.main(output, *args.additional_arguments)
|
||||
ret = module.__dict__[method](output, *args.additional_arguments)
|
||||
except IOError as e:
|
||||
print('Error opening file "{0}"'.format(e.filename), file=sys.stderr)
|
||||
traceback.print_exc()
|
||||
|
||||
@@ -69,6 +69,77 @@ from ..util import (
|
||||
)
|
||||
from ..makeutil import Makefile
|
||||
|
||||
MOZBUILD_VARIABLES = [
|
||||
'ANDROID_GENERATED_RESFILES',
|
||||
'ANDROID_RES_DIRS',
|
||||
'ASFLAGS',
|
||||
'CMSRCS',
|
||||
'CMMSRCS',
|
||||
'CPP_UNIT_TESTS',
|
||||
'DIRS',
|
||||
'DIST_INSTALL',
|
||||
'EXTRA_DSO_LDOPTS',
|
||||
'EXTRA_JS_MODULES',
|
||||
'EXTRA_PP_COMPONENTS',
|
||||
'EXTRA_PP_JS_MODULES',
|
||||
'FORCE_SHARED_LIB',
|
||||
'FORCE_STATIC_LIB',
|
||||
'FINAL_LIBRARY',
|
||||
'HOST_CSRCS',
|
||||
'HOST_CMMSRCS',
|
||||
'HOST_EXTRA_LIBS',
|
||||
'HOST_LIBRARY_NAME',
|
||||
'HOST_PROGRAM',
|
||||
'HOST_SIMPLE_PROGRAMS',
|
||||
'IS_COMPONENT',
|
||||
'JAR_MANIFEST',
|
||||
'JAVA_JAR_TARGETS',
|
||||
'LD_VERSION_SCRIPT',
|
||||
'LIBRARY_NAME',
|
||||
'LIBS',
|
||||
'MAKE_FRAMEWORK',
|
||||
'MODULE',
|
||||
'MSVC_ENABLE_PGO',
|
||||
'NO_DIST_INSTALL',
|
||||
'NO_EXPAND_LIBS',
|
||||
'OS_LIBS',
|
||||
'PARALLEL_DIRS',
|
||||
'PREF_JS_EXPORTS',
|
||||
'PROGRAM',
|
||||
'PYTHON_UNIT_TESTS',
|
||||
'RESOURCE_FILES',
|
||||
'SDK_HEADERS',
|
||||
'SDK_LIBRARY',
|
||||
'SHARED_LIBRARY_LIBS',
|
||||
'SHARED_LIBRARY_NAME',
|
||||
'SIMPLE_PROGRAMS',
|
||||
'SONAME',
|
||||
'STATIC_LIBRARY_NAME',
|
||||
'TEST_DIRS',
|
||||
'TOOL_DIRS',
|
||||
'XPCSHELL_TESTS',
|
||||
'XPIDL_MODULE',
|
||||
]
|
||||
|
||||
DEPRECATED_VARIABLES = [
|
||||
'ANDROID_RESFILES',
|
||||
'EXPORT_LIBRARY',
|
||||
'EXTRA_LIBS',
|
||||
'HOST_LIBS',
|
||||
'LIBXUL_LIBRARY',
|
||||
'MOCHITEST_A11Y_FILES',
|
||||
'MOCHITEST_BROWSER_FILES',
|
||||
'MOCHITEST_BROWSER_FILES_PARTS',
|
||||
'MOCHITEST_CHROME_FILES',
|
||||
'MOCHITEST_FILES',
|
||||
'MOCHITEST_FILES_PARTS',
|
||||
'MOCHITEST_METRO_FILES',
|
||||
'MOCHITEST_ROBOCOP_FILES',
|
||||
'SHORT_LIBNAME',
|
||||
'TESTING_JS_MODULES',
|
||||
'TESTING_JS_MODULE_DIR',
|
||||
]
|
||||
|
||||
class BackendMakeFile(object):
|
||||
"""Represents a generated backend.mk file.
|
||||
|
||||
@@ -411,11 +482,12 @@ class RecursiveMakeBackend(CommonBackend):
|
||||
backend_file.write('GENERATED_FILES += %s\n' % obj.output)
|
||||
if obj.script:
|
||||
backend_file.write("""{output}: {script}{inputs}
|
||||
\t$(call py_action,file_generate,{script} {output}{inputs})
|
||||
\t$(call py_action,file_generate,{script} {method} {output}{inputs})
|
||||
|
||||
""".format(output=obj.output,
|
||||
inputs=' ' + ' '.join(obj.inputs) if obj.inputs else '',
|
||||
script=obj.script))
|
||||
script=obj.script,
|
||||
method=obj.method))
|
||||
|
||||
elif isinstance(obj, TestHarnessFiles):
|
||||
self._process_test_harness_files(obj, backend_file)
|
||||
@@ -627,6 +699,18 @@ class RecursiveMakeBackend(CommonBackend):
|
||||
rule = makefile.create_rule(['$(all_absolute_unified_files)'])
|
||||
rule.add_dependencies(['$(CURDIR)/%: %'])
|
||||
|
||||
def _check_blacklisted_variables(self, makefile_in, makefile_content):
|
||||
for x in MOZBUILD_VARIABLES:
|
||||
if re.search(r'[^#]\b%s\s*[:?+]?=' % x, makefile_content, re.M):
|
||||
raise Exception('Variable %s is defined in %s. It should '
|
||||
'only be defined in moz.build files.' % (x, makefile_in))
|
||||
|
||||
for x in DEPRECATED_VARIABLES:
|
||||
if re.search(r'[^#]\b%s\s*[:?+]?=' % x, makefile_content, re.M):
|
||||
raise Exception('Variable %s is defined in %s. This variable '
|
||||
'has been deprecated. It does nothing. It must be removed '
|
||||
'in order to build.' % (x, makefile_in))
|
||||
|
||||
def consume_finished(self):
|
||||
CommonBackend.consume_finished(self)
|
||||
|
||||
@@ -674,6 +758,10 @@ class RecursiveMakeBackend(CommonBackend):
|
||||
self._no_skip['tools'].add(mozpath.relpath(objdir,
|
||||
self.environment.topobjdir))
|
||||
|
||||
# Detect any Makefile.ins that contain variables on the
|
||||
# moz.build-only list
|
||||
self._check_blacklisted_variables(makefile_in, content)
|
||||
|
||||
self._fill_root_mk()
|
||||
|
||||
# Write out a dependency file used to determine whether a config.status
|
||||
@@ -1114,6 +1202,8 @@ INSTALL_TARGETS += %(prefix)s
|
||||
backend_file.write('REAL_LIBRARY := %s\n' % libdef.lib_name)
|
||||
if libdef.is_sdk:
|
||||
backend_file.write('SDK_LIBRARY := %s\n' % libdef.import_name)
|
||||
if libdef.no_expand_lib:
|
||||
backend_file.write('NO_EXPAND_LIBS := 1\n')
|
||||
|
||||
def _process_host_library(self, libdef, backend_file):
|
||||
backend_file.write('HOST_LIBRARY_NAME = %s\n' % libdef.basename)
|
||||
|
||||
@@ -268,6 +268,10 @@ class Context(KeyedDefaultDict):
|
||||
|
||||
|
||||
class TemplateContext(Context):
|
||||
def __init__(self, template=None, allowed_variables={}, config=None):
|
||||
self.template = template
|
||||
super(TemplateContext, self).__init__(allowed_variables, config)
|
||||
|
||||
def _validate(self, key, value):
|
||||
return Context._validate(self, key, value, True)
|
||||
|
||||
@@ -314,6 +318,21 @@ class FinalTargetValue(ContextDerivedValue, unicode):
|
||||
return unicode.__new__(cls, value)
|
||||
|
||||
|
||||
def Enum(*values):
|
||||
assert len(values)
|
||||
default = values[0]
|
||||
|
||||
class EnumClass(object):
|
||||
def __new__(cls, value=None):
|
||||
if value is None:
|
||||
return default
|
||||
if value in values:
|
||||
return value
|
||||
raise ValueError('Invalid value. Allowed values are: %s'
|
||||
% ', '.join(repr(v) for v in values))
|
||||
return EnumClass
|
||||
|
||||
|
||||
class SourcePath(ContextDerivedValue, UserString):
|
||||
"""Stores and resolves a source path relative to a given context
|
||||
|
||||
@@ -628,6 +647,14 @@ VARIABLES = {
|
||||
supported for passing to scripts, and that all arguments provided
|
||||
to the script should be filenames relative to the directory in which
|
||||
the moz.build file is located.
|
||||
|
||||
To enable using the same script for generating multiple files with
|
||||
slightly different non-filename parameters, alternative entry points
|
||||
into ``script`` can be specified::
|
||||
|
||||
GENERATED_FILES += ['bar.c']
|
||||
bar = GENERATED_FILES['bar.c']
|
||||
bar.script = 'generate.py:make_bar'
|
||||
""", 'export'),
|
||||
|
||||
'DEFINES': (OrderedDict, dict,
|
||||
@@ -1073,11 +1100,17 @@ VARIABLES = {
|
||||
ends with ``HOST_BIN_SUFFIX``, ``HOST_PROGRAM`` will remain unchanged.
|
||||
""", None),
|
||||
|
||||
'NO_DIST_INSTALL': (bool, bool,
|
||||
"""Disable installing certain files into the distribution directory.
|
||||
'DIST_INSTALL': (Enum(None, False, True), bool,
|
||||
"""Whether to install certain files into the dist directory.
|
||||
|
||||
If present, some files defined by other variables won't be
|
||||
distributed/shipped with the produced build.
|
||||
By default, some files types are installed in the dist directory, and
|
||||
some aren't. Set this variable to True to force the installation of
|
||||
some files that wouldn't be installed by default. Set this variable to
|
||||
False to force to not install some files that would be installed by
|
||||
default.
|
||||
|
||||
This is confusing for historical reasons, but eventually, the behavior
|
||||
will be made explicit.
|
||||
""", None),
|
||||
|
||||
'JAR_MANIFESTS': (StrictOrderingOnAppendList, list,
|
||||
@@ -1318,6 +1351,15 @@ VARIABLES = {
|
||||
appear in the moz.build file.
|
||||
""", None),
|
||||
|
||||
'ASFLAGS': (List, list,
|
||||
"""Flags passed to the assembler for all of the assembly source files
|
||||
declared in this directory.
|
||||
|
||||
Note that the ordering of flags matters here; these flags will be
|
||||
added to the assembler's command line in the same order as they
|
||||
appear in the moz.build file.
|
||||
""", None),
|
||||
|
||||
'LDFLAGS': (List, list,
|
||||
"""Flags passed to the linker when linking all of the libraries and
|
||||
executables declared in this directory.
|
||||
@@ -1360,6 +1402,11 @@ VARIABLES = {
|
||||
the path(s) with a '/' character and a '!' character, respectively::
|
||||
TEST_HARNESS_FILES.path += ['/build/bar.py', '!quux.py']
|
||||
""", 'libs'),
|
||||
|
||||
'NO_EXPAND_LIBS': (bool, bool,
|
||||
"""Forces to build a real static library, and no corresponding fake
|
||||
library.
|
||||
""", None),
|
||||
}
|
||||
|
||||
# Sanity check: we don't want any variable above to have a list as storage type.
|
||||
@@ -1728,6 +1775,16 @@ DEPRECATION_HINTS = {
|
||||
'TEST_TOOL_DIRS': 'Please use the TEST_DIRS variable instead.',
|
||||
|
||||
'PARALLEL_DIRS': 'Please use the DIRS variable instead.',
|
||||
|
||||
'NO_DIST_INSTALL': '''
|
||||
Please use
|
||||
|
||||
DIST_INSTALL = False
|
||||
|
||||
instead of
|
||||
|
||||
NO_DIST_INSTALL = True
|
||||
''',
|
||||
}
|
||||
|
||||
# Make sure that all template variables have a deprecation hint.
|
||||
|
||||
@@ -502,12 +502,14 @@ class StaticLibrary(Library):
|
||||
"""Context derived container object for a static library"""
|
||||
__slots__ = (
|
||||
'link_into',
|
||||
'no_expand_lib',
|
||||
)
|
||||
|
||||
def __init__(self, context, basename, real_name=None, is_sdk=False,
|
||||
link_into=None):
|
||||
link_into=None, no_expand_lib=False):
|
||||
Library.__init__(self, context, basename, real_name, is_sdk)
|
||||
self.link_into = link_into
|
||||
self.no_expand_lib = no_expand_lib
|
||||
|
||||
|
||||
class SharedLibrary(Library):
|
||||
@@ -840,7 +842,7 @@ class InstallationTarget(ContextDerived):
|
||||
self.xpiname = context.get('XPI_NAME', '')
|
||||
self.subdir = context.get('DIST_SUBDIR', '')
|
||||
self.target = context['FINAL_TARGET']
|
||||
self.enabled = not context.get('NO_DIST_INSTALL', False)
|
||||
self.enabled = context['DIST_INSTALL'] is not False
|
||||
|
||||
def is_custom(self):
|
||||
"""Returns whether or not the target is not derived from the default
|
||||
@@ -872,13 +874,15 @@ class GeneratedFile(ContextDerived):
|
||||
|
||||
__slots__ = (
|
||||
'script',
|
||||
'method',
|
||||
'output',
|
||||
'inputs',
|
||||
)
|
||||
|
||||
def __init__(self, context, script, output, inputs):
|
||||
def __init__(self, context, script, method, output, inputs):
|
||||
ContextDerived.__init__(self, context)
|
||||
self.script = script
|
||||
self.method = method
|
||||
self.output = output
|
||||
self.inputs = inputs
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ from .reader import SandboxValidationError
|
||||
from .context import (
|
||||
Context,
|
||||
SubContext,
|
||||
TemplateContext,
|
||||
)
|
||||
|
||||
|
||||
@@ -354,334 +355,7 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
else:
|
||||
return ExternalSharedLibrary(context, name)
|
||||
|
||||
def emit_from_context(self, context):
|
||||
"""Convert a Context to tree metadata objects.
|
||||
|
||||
This is a generator of mozbuild.frontend.data.ContextDerived instances.
|
||||
"""
|
||||
|
||||
# We only want to emit an InstallationTarget if one of the consulted
|
||||
# variables is defined. Later on, we look up FINAL_TARGET, which has
|
||||
# the side-effect of populating it. So, we need to do this lookup
|
||||
# early.
|
||||
if any(k in context for k in ('FINAL_TARGET', 'XPI_NAME', 'DIST_SUBDIR')):
|
||||
yield InstallationTarget(context)
|
||||
|
||||
# We always emit a directory traversal descriptor. This is needed by
|
||||
# the recursive make backend.
|
||||
for o in self._emit_directory_traversal_from_context(context): yield o
|
||||
|
||||
for path in context['CONFIGURE_SUBST_FILES']:
|
||||
yield self._create_substitution(ConfigFileSubstitution, context,
|
||||
path)
|
||||
|
||||
for path in context['CONFIGURE_DEFINE_FILES']:
|
||||
yield self._create_substitution(HeaderFileSubstitution, context,
|
||||
path)
|
||||
|
||||
# XPIDL source files get processed and turned into .h and .xpt files.
|
||||
# If there are multiple XPIDL files in a directory, they get linked
|
||||
# together into a final .xpt, which has the name defined by
|
||||
# XPIDL_MODULE.
|
||||
xpidl_module = context['XPIDL_MODULE']
|
||||
|
||||
if context['XPIDL_SOURCES'] and not xpidl_module:
|
||||
raise SandboxValidationError('XPIDL_MODULE must be defined if '
|
||||
'XPIDL_SOURCES is defined.', context)
|
||||
|
||||
if xpidl_module and not context['XPIDL_SOURCES']:
|
||||
raise SandboxValidationError('XPIDL_MODULE cannot be defined '
|
||||
'unless there are XPIDL_SOURCES', context)
|
||||
|
||||
if context['XPIDL_SOURCES'] and context['NO_DIST_INSTALL']:
|
||||
self.log(logging.WARN, 'mozbuild_warning', dict(
|
||||
path=context.main_path),
|
||||
'{path}: NO_DIST_INSTALL has no effect on XPIDL_SOURCES.')
|
||||
|
||||
for idl in context['XPIDL_SOURCES']:
|
||||
yield XPIDLFile(context, mozpath.join(context.srcdir, idl),
|
||||
xpidl_module)
|
||||
|
||||
for symbol in ('SOURCES', 'HOST_SOURCES', 'UNIFIED_SOURCES'):
|
||||
for src in (context[symbol] or []):
|
||||
if not os.path.exists(mozpath.join(context.srcdir, src)):
|
||||
raise SandboxValidationError('File listed in %s does not '
|
||||
'exist: \'%s\'' % (symbol, src), context)
|
||||
|
||||
# Proxy some variables as-is until we have richer classes to represent
|
||||
# them. We should aim to keep this set small because it violates the
|
||||
# desired abstraction of the build definition away from makefiles.
|
||||
passthru = VariablePassthru(context)
|
||||
varlist = [
|
||||
'ANDROID_GENERATED_RESFILES',
|
||||
'ANDROID_RES_DIRS',
|
||||
'DISABLE_STL_WRAPPING',
|
||||
'EXTRA_ASSEMBLER_FLAGS',
|
||||
'EXTRA_COMPILE_FLAGS',
|
||||
'EXTRA_COMPONENTS',
|
||||
'EXTRA_DSO_LDOPTS',
|
||||
'EXTRA_PP_COMPONENTS',
|
||||
'FAIL_ON_WARNINGS',
|
||||
'USE_STATIC_LIBS',
|
||||
'IS_GYP_DIR',
|
||||
'MSVC_ENABLE_PGO',
|
||||
'NO_DIST_INSTALL',
|
||||
'PYTHON_UNIT_TESTS',
|
||||
'RCFILE',
|
||||
'RESFILE',
|
||||
'RCINCLUDE',
|
||||
'DEFFILE',
|
||||
'WIN32_EXE_LDFLAGS',
|
||||
'LD_VERSION_SCRIPT',
|
||||
]
|
||||
for v in varlist:
|
||||
if v in context and context[v]:
|
||||
passthru.variables[v] = context[v]
|
||||
|
||||
if context.config.substs.get('OS_TARGET') == 'WINNT' and \
|
||||
context['DELAYLOAD_DLLS']:
|
||||
context['LDFLAGS'].extend([('-DELAYLOAD:%s' % dll)
|
||||
for dll in context['DELAYLOAD_DLLS']])
|
||||
context['OS_LIBS'].append('delayimp')
|
||||
|
||||
for v in ['CFLAGS', 'CXXFLAGS', 'CMFLAGS', 'CMMFLAGS', 'LDFLAGS']:
|
||||
if v in context and context[v]:
|
||||
passthru.variables['MOZBUILD_' + v] = context[v]
|
||||
|
||||
# NO_VISIBILITY_FLAGS is slightly different
|
||||
if context['NO_VISIBILITY_FLAGS']:
|
||||
passthru.variables['VISIBILITY_FLAGS'] = ''
|
||||
|
||||
no_pgo = context.get('NO_PGO')
|
||||
sources = context.get('SOURCES', [])
|
||||
no_pgo_sources = [f for f in sources if sources[f].no_pgo]
|
||||
if no_pgo:
|
||||
if no_pgo_sources:
|
||||
raise SandboxValidationError('NO_PGO and SOURCES[...].no_pgo '
|
||||
'cannot be set at the same time', context)
|
||||
passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo
|
||||
if no_pgo_sources:
|
||||
passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo_sources
|
||||
|
||||
# A map from "canonical suffixes" for a particular source file
|
||||
# language to the range of suffixes associated with that language.
|
||||
#
|
||||
# We deliberately don't list the canonical suffix in the suffix list
|
||||
# in the definition; we'll add it in programmatically after defining
|
||||
# things.
|
||||
suffix_map = {
|
||||
'.s': set(['.asm']),
|
||||
'.c': set(),
|
||||
'.m': set(),
|
||||
'.mm': set(),
|
||||
'.cpp': set(['.cc', '.cxx']),
|
||||
'.S': set(),
|
||||
}
|
||||
|
||||
# The inverse of the above, mapping suffixes to their canonical suffix.
|
||||
canonicalized_suffix_map = {}
|
||||
for suffix, alternatives in suffix_map.iteritems():
|
||||
alternatives.add(suffix)
|
||||
for a in alternatives:
|
||||
canonicalized_suffix_map[a] = suffix
|
||||
|
||||
def canonical_suffix_for_file(f):
|
||||
return canonicalized_suffix_map[mozpath.splitext(f)[1]]
|
||||
|
||||
# A map from moz.build variables to the canonical suffixes of file
|
||||
# kinds that can be listed therein.
|
||||
all_suffixes = list(suffix_map.keys())
|
||||
varmap = dict(
|
||||
SOURCES=(Sources, all_suffixes),
|
||||
HOST_SOURCES=(HostSources, ['.c', '.mm', '.cpp']),
|
||||
UNIFIED_SOURCES=(UnifiedSources, ['.c', '.mm', '.cpp']),
|
||||
GENERATED_SOURCES=(GeneratedSources, all_suffixes),
|
||||
)
|
||||
|
||||
for variable, (klass, suffixes) in varmap.items():
|
||||
allowed_suffixes = set().union(*[suffix_map[s] for s in suffixes])
|
||||
|
||||
# First ensure that we haven't been given filetypes that we don't
|
||||
# recognize.
|
||||
for f in context[variable]:
|
||||
ext = mozpath.splitext(f)[1]
|
||||
if ext not in allowed_suffixes:
|
||||
raise SandboxValidationError(
|
||||
'%s has an unknown file type.' % f, context)
|
||||
if variable.startswith('GENERATED_'):
|
||||
l = passthru.variables.setdefault('GARBAGE', [])
|
||||
l.append(f)
|
||||
|
||||
# Now sort the files to let groupby work.
|
||||
sorted_files = sorted(context[variable], key=canonical_suffix_for_file)
|
||||
for canonical_suffix, files in itertools.groupby(sorted_files, canonical_suffix_for_file):
|
||||
arglist = [context, list(files), canonical_suffix]
|
||||
if variable.startswith('UNIFIED_') and 'FILES_PER_UNIFIED_FILE' in context:
|
||||
arglist.append(context['FILES_PER_UNIFIED_FILE'])
|
||||
yield klass(*arglist)
|
||||
|
||||
sources_with_flags = [f for f in sources if sources[f].flags]
|
||||
for f in sources_with_flags:
|
||||
ext = mozpath.splitext(f)[1]
|
||||
yield PerSourceFlag(context, f, sources[f].flags)
|
||||
|
||||
exports = context.get('EXPORTS')
|
||||
if exports:
|
||||
yield Exports(context, exports,
|
||||
dist_install=not context.get('NO_DIST_INSTALL', False))
|
||||
|
||||
generated_files = context.get('GENERATED_FILES')
|
||||
if generated_files:
|
||||
for f in generated_files:
|
||||
flags = generated_files[f]
|
||||
output = f
|
||||
if flags.script:
|
||||
script = mozpath.join(context.srcdir, flags.script)
|
||||
inputs = [mozpath.join(context.srcdir, i) for i in flags.inputs]
|
||||
|
||||
if not os.path.exists(script):
|
||||
raise SandboxValidationError(
|
||||
'Script for generating %s does not exist: %s'
|
||||
% (f, script), context)
|
||||
if os.path.splitext(script)[1] != '.py':
|
||||
raise SandboxValidationError(
|
||||
'Script for generating %s does not end in .py: %s'
|
||||
% (f, script), context)
|
||||
for i in inputs:
|
||||
if not os.path.exists(i):
|
||||
raise SandboxValidationError(
|
||||
'Input for generating %s does not exist: %s'
|
||||
% (f, i), context)
|
||||
else:
|
||||
script = None
|
||||
inputs = []
|
||||
yield GeneratedFile(context, script, output, inputs)
|
||||
|
||||
test_harness_files = context.get('TEST_HARNESS_FILES')
|
||||
if test_harness_files:
|
||||
srcdir_files = defaultdict(list)
|
||||
srcdir_pattern_files = defaultdict(list)
|
||||
objdir_files = defaultdict(list)
|
||||
|
||||
for path, strings in test_harness_files.walk():
|
||||
if not path and strings:
|
||||
raise SandboxValidationError(
|
||||
'Cannot install files to the root of TEST_HARNESS_FILES', context)
|
||||
|
||||
for s in strings:
|
||||
if context.is_objdir_path(s):
|
||||
if s.startswith('!/'):
|
||||
objdir_files[path].append('$(DEPTH)/%s' % s[2:])
|
||||
else:
|
||||
objdir_files[path].append(s[1:])
|
||||
else:
|
||||
resolved = context.resolve_path(s)
|
||||
if '*' in s:
|
||||
if s[0] == '/':
|
||||
pattern_start = resolved.index('*')
|
||||
base_path = mozpath.dirname(resolved[:pattern_start])
|
||||
pattern = resolved[len(base_path)+1:]
|
||||
else:
|
||||
base_path = context.srcdir
|
||||
pattern = s
|
||||
srcdir_pattern_files[path].append((base_path, pattern));
|
||||
elif not os.path.exists(resolved):
|
||||
raise SandboxValidationError(
|
||||
'File listed in TEST_HARNESS_FILES does not exist: %s' % s, context)
|
||||
else:
|
||||
srcdir_files[path].append(resolved)
|
||||
|
||||
yield TestHarnessFiles(context, srcdir_files,
|
||||
srcdir_pattern_files, objdir_files)
|
||||
|
||||
defines = context.get('DEFINES')
|
||||
if defines:
|
||||
yield Defines(context, defines)
|
||||
|
||||
resources = context.get('RESOURCE_FILES')
|
||||
if resources:
|
||||
yield Resources(context, resources, defines)
|
||||
|
||||
for pref in sorted(context['JS_PREFERENCE_FILES']):
|
||||
yield JsPreferenceFile(context, pref)
|
||||
|
||||
for kind, cls in [('PROGRAM', Program), ('HOST_PROGRAM', HostProgram)]:
|
||||
program = context.get(kind)
|
||||
if program:
|
||||
if program in self._binaries:
|
||||
raise SandboxValidationError(
|
||||
'Cannot use "%s" as %s name, '
|
||||
'because it is already used in %s' % (program, kind,
|
||||
self._binaries[program].relativedir), context)
|
||||
self._binaries[program] = cls(context, program)
|
||||
self._linkage.append((context, self._binaries[program],
|
||||
kind.replace('PROGRAM', 'USE_LIBS')))
|
||||
|
||||
for kind, cls in [
|
||||
('SIMPLE_PROGRAMS', SimpleProgram),
|
||||
('CPP_UNIT_TESTS', SimpleProgram),
|
||||
('HOST_SIMPLE_PROGRAMS', HostSimpleProgram)]:
|
||||
for program in context[kind]:
|
||||
if program in self._binaries:
|
||||
raise SandboxValidationError(
|
||||
'Cannot use "%s" in %s, '
|
||||
'because it is already used in %s' % (program, kind,
|
||||
self._binaries[program].relativedir), context)
|
||||
self._binaries[program] = cls(context, program,
|
||||
is_unit_test=kind == 'CPP_UNIT_TESTS')
|
||||
self._linkage.append((context, self._binaries[program],
|
||||
'HOST_USE_LIBS' if kind == 'HOST_SIMPLE_PROGRAMS'
|
||||
else 'USE_LIBS'))
|
||||
|
||||
extra_js_modules = context.get('EXTRA_JS_MODULES')
|
||||
if extra_js_modules:
|
||||
yield JavaScriptModules(context, extra_js_modules, 'extra')
|
||||
|
||||
extra_pp_js_modules = context.get('EXTRA_PP_JS_MODULES')
|
||||
if extra_pp_js_modules:
|
||||
yield JavaScriptModules(context, extra_pp_js_modules, 'extra_pp')
|
||||
|
||||
test_js_modules = context.get('TESTING_JS_MODULES')
|
||||
if test_js_modules:
|
||||
yield JavaScriptModules(context, test_js_modules, 'testing')
|
||||
|
||||
simple_lists = [
|
||||
('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile),
|
||||
('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
|
||||
('IPDL_SOURCES', IPDLFile),
|
||||
('GENERATED_INCLUDES', GeneratedInclude),
|
||||
('PREPROCESSED_TEST_WEBIDL_FILES', PreprocessedTestWebIDLFile),
|
||||
('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile),
|
||||
('TEST_WEBIDL_FILES', TestWebIDLFile),
|
||||
('WEBIDL_FILES', WebIDLFile),
|
||||
('WEBIDL_EXAMPLE_INTERFACES', ExampleWebIDLInterface),
|
||||
]
|
||||
for context_var, klass in simple_lists:
|
||||
for name in context.get(context_var, []):
|
||||
yield klass(context, name)
|
||||
|
||||
for local_include in context.get('LOCAL_INCLUDES', []):
|
||||
if local_include.startswith('/'):
|
||||
path = context.config.topsrcdir
|
||||
relative_include = local_include[1:]
|
||||
else:
|
||||
path = context.srcdir
|
||||
relative_include = local_include
|
||||
|
||||
actual_include = os.path.join(path, relative_include)
|
||||
if not os.path.exists(actual_include):
|
||||
raise SandboxValidationError('Path specified in LOCAL_INCLUDES '
|
||||
'does not exist: %s (resolved to %s)' % (local_include, actual_include), context)
|
||||
yield LocalInclude(context, local_include)
|
||||
|
||||
final_target_files = context.get('FINAL_TARGET_FILES')
|
||||
if final_target_files:
|
||||
yield FinalTargetFiles(context, final_target_files, context['FINAL_TARGET'])
|
||||
|
||||
branding_files = context.get('BRANDING_FILES')
|
||||
if branding_files:
|
||||
yield BrandingFiles(context, branding_files)
|
||||
|
||||
def _handle_libraries(self, context):
|
||||
host_libname = context.get('HOST_LIBRARY_NAME')
|
||||
libname = context.get('LIBRARY_NAME')
|
||||
|
||||
@@ -782,6 +456,13 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
elif static_lib:
|
||||
static_args['is_sdk'] = True
|
||||
|
||||
if context.get('NO_EXPAND_LIBS'):
|
||||
if not static_lib:
|
||||
raise SandboxValidationError(
|
||||
'NO_EXPAND_LIBS can only be set for static libraries.',
|
||||
context)
|
||||
static_args['no_expand_lib'] = True
|
||||
|
||||
if shared_lib and static_lib:
|
||||
if not static_name and not shared_name:
|
||||
raise SandboxValidationError(
|
||||
@@ -825,6 +506,401 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
'LIBRARY_NAME to take effect', context)
|
||||
lib.defines.update(lib_defines)
|
||||
|
||||
def emit_from_context(self, context):
|
||||
"""Convert a Context to tree metadata objects.
|
||||
|
||||
This is a generator of mozbuild.frontend.data.ContextDerived instances.
|
||||
"""
|
||||
|
||||
# We only want to emit an InstallationTarget if one of the consulted
|
||||
# variables is defined. Later on, we look up FINAL_TARGET, which has
|
||||
# the side-effect of populating it. So, we need to do this lookup
|
||||
# early.
|
||||
if any(k in context for k in ('FINAL_TARGET', 'XPI_NAME', 'DIST_SUBDIR')):
|
||||
yield InstallationTarget(context)
|
||||
|
||||
# We always emit a directory traversal descriptor. This is needed by
|
||||
# the recursive make backend.
|
||||
for o in self._emit_directory_traversal_from_context(context): yield o
|
||||
|
||||
for path in context['CONFIGURE_SUBST_FILES']:
|
||||
yield self._create_substitution(ConfigFileSubstitution, context,
|
||||
path)
|
||||
|
||||
for path in context['CONFIGURE_DEFINE_FILES']:
|
||||
yield self._create_substitution(HeaderFileSubstitution, context,
|
||||
path)
|
||||
|
||||
for obj in self._process_xpidl(context):
|
||||
yield obj
|
||||
|
||||
# Proxy some variables as-is until we have richer classes to represent
|
||||
# them. We should aim to keep this set small because it violates the
|
||||
# desired abstraction of the build definition away from makefiles.
|
||||
passthru = VariablePassthru(context)
|
||||
varlist = [
|
||||
'ANDROID_GENERATED_RESFILES',
|
||||
'ANDROID_RES_DIRS',
|
||||
'DISABLE_STL_WRAPPING',
|
||||
'EXTRA_ASSEMBLER_FLAGS',
|
||||
'EXTRA_COMPILE_FLAGS',
|
||||
'EXTRA_COMPONENTS',
|
||||
'EXTRA_DSO_LDOPTS',
|
||||
'EXTRA_PP_COMPONENTS',
|
||||
'FAIL_ON_WARNINGS',
|
||||
'USE_STATIC_LIBS',
|
||||
'MSVC_ENABLE_PGO',
|
||||
'PYTHON_UNIT_TESTS',
|
||||
'RCFILE',
|
||||
'RESFILE',
|
||||
'RCINCLUDE',
|
||||
'DEFFILE',
|
||||
'WIN32_EXE_LDFLAGS',
|
||||
'LD_VERSION_SCRIPT',
|
||||
]
|
||||
for v in varlist:
|
||||
if v in context and context[v]:
|
||||
passthru.variables[v] = context[v]
|
||||
|
||||
if context.config.substs.get('OS_TARGET') == 'WINNT' and \
|
||||
context['DELAYLOAD_DLLS']:
|
||||
context['LDFLAGS'].extend([('-DELAYLOAD:%s' % dll)
|
||||
for dll in context['DELAYLOAD_DLLS']])
|
||||
context['OS_LIBS'].append('delayimp')
|
||||
|
||||
for v in ['CFLAGS', 'CXXFLAGS', 'CMFLAGS', 'CMMFLAGS', 'ASFLAGS',
|
||||
'LDFLAGS']:
|
||||
if v in context and context[v]:
|
||||
passthru.variables['MOZBUILD_' + v] = context[v]
|
||||
|
||||
# NO_VISIBILITY_FLAGS is slightly different
|
||||
if context['NO_VISIBILITY_FLAGS']:
|
||||
passthru.variables['VISIBILITY_FLAGS'] = ''
|
||||
|
||||
if isinstance(context, TemplateContext) and context.template == 'Gyp':
|
||||
passthru.variables['IS_GYP_DIR'] = True
|
||||
|
||||
dist_install = context['DIST_INSTALL']
|
||||
if dist_install is True:
|
||||
passthru.variables['DIST_INSTALL'] = True
|
||||
elif dist_install is False:
|
||||
passthru.variables['NO_DIST_INSTALL'] = True
|
||||
|
||||
for obj in self._process_sources(context, passthru):
|
||||
yield obj
|
||||
|
||||
exports = context.get('EXPORTS')
|
||||
if exports:
|
||||
yield Exports(context, exports,
|
||||
dist_install=dist_install is not False)
|
||||
|
||||
for obj in self._process_generated_files(context):
|
||||
yield obj
|
||||
|
||||
for obj in self._process_test_harness_files(context):
|
||||
yield obj
|
||||
|
||||
defines = context.get('DEFINES')
|
||||
if defines:
|
||||
yield Defines(context, defines)
|
||||
|
||||
resources = context.get('RESOURCE_FILES')
|
||||
if resources:
|
||||
yield Resources(context, resources, defines)
|
||||
|
||||
for pref in sorted(context['JS_PREFERENCE_FILES']):
|
||||
yield JsPreferenceFile(context, pref)
|
||||
|
||||
self._handle_programs(context)
|
||||
|
||||
extra_js_modules = context.get('EXTRA_JS_MODULES')
|
||||
if extra_js_modules:
|
||||
yield JavaScriptModules(context, extra_js_modules, 'extra')
|
||||
|
||||
extra_pp_js_modules = context.get('EXTRA_PP_JS_MODULES')
|
||||
if extra_pp_js_modules:
|
||||
yield JavaScriptModules(context, extra_pp_js_modules, 'extra_pp')
|
||||
|
||||
test_js_modules = context.get('TESTING_JS_MODULES')
|
||||
if test_js_modules:
|
||||
yield JavaScriptModules(context, test_js_modules, 'testing')
|
||||
|
||||
simple_lists = [
|
||||
('GENERATED_EVENTS_WEBIDL_FILES', GeneratedEventWebIDLFile),
|
||||
('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
|
||||
('IPDL_SOURCES', IPDLFile),
|
||||
('GENERATED_INCLUDES', GeneratedInclude),
|
||||
('PREPROCESSED_TEST_WEBIDL_FILES', PreprocessedTestWebIDLFile),
|
||||
('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile),
|
||||
('TEST_WEBIDL_FILES', TestWebIDLFile),
|
||||
('WEBIDL_FILES', WebIDLFile),
|
||||
('WEBIDL_EXAMPLE_INTERFACES', ExampleWebIDLInterface),
|
||||
]
|
||||
for context_var, klass in simple_lists:
|
||||
for name in context.get(context_var, []):
|
||||
yield klass(context, name)
|
||||
|
||||
for local_include in context.get('LOCAL_INCLUDES', []):
|
||||
if local_include.startswith('/'):
|
||||
path = context.config.topsrcdir
|
||||
relative_include = local_include[1:]
|
||||
else:
|
||||
path = context.srcdir
|
||||
relative_include = local_include
|
||||
|
||||
actual_include = os.path.join(path, relative_include)
|
||||
if not os.path.exists(actual_include):
|
||||
raise SandboxValidationError('Path specified in LOCAL_INCLUDES '
|
||||
'does not exist: %s (resolved to %s)' % (local_include, actual_include), context)
|
||||
yield LocalInclude(context, local_include)
|
||||
|
||||
final_target_files = context.get('FINAL_TARGET_FILES')
|
||||
if final_target_files:
|
||||
yield FinalTargetFiles(context, final_target_files, context['FINAL_TARGET'])
|
||||
|
||||
branding_files = context.get('BRANDING_FILES')
|
||||
if branding_files:
|
||||
yield BrandingFiles(context, branding_files)
|
||||
|
||||
self._handle_libraries(context)
|
||||
|
||||
for obj in self._process_test_manifests(context):
|
||||
yield obj
|
||||
|
||||
for obj in self._process_jar_manifests(context):
|
||||
yield obj
|
||||
|
||||
for name, jar in context.get('JAVA_JAR_TARGETS', {}).items():
|
||||
yield ContextWrapped(context, jar)
|
||||
|
||||
for name, data in context.get('ANDROID_ECLIPSE_PROJECT_TARGETS', {}).items():
|
||||
yield ContextWrapped(context, data)
|
||||
|
||||
if passthru.variables:
|
||||
yield passthru
|
||||
|
||||
def _create_substitution(self, cls, context, path):
|
||||
if os.path.isabs(path):
|
||||
path = path[1:]
|
||||
|
||||
sub = cls(context)
|
||||
sub.input_path = mozpath.join(context.srcdir, '%s.in' % path)
|
||||
sub.output_path = mozpath.join(context.objdir, path)
|
||||
sub.relpath = path
|
||||
|
||||
return sub
|
||||
|
||||
def _process_sources(self, context, passthru):
|
||||
for symbol in ('SOURCES', 'HOST_SOURCES', 'UNIFIED_SOURCES'):
|
||||
for src in (context[symbol] or []):
|
||||
if not os.path.exists(mozpath.join(context.srcdir, src)):
|
||||
raise SandboxValidationError('File listed in %s does not '
|
||||
'exist: \'%s\'' % (symbol, src), context)
|
||||
|
||||
no_pgo = context.get('NO_PGO')
|
||||
sources = context.get('SOURCES', [])
|
||||
no_pgo_sources = [f for f in sources if sources[f].no_pgo]
|
||||
if no_pgo:
|
||||
if no_pgo_sources:
|
||||
raise SandboxValidationError('NO_PGO and SOURCES[...].no_pgo '
|
||||
'cannot be set at the same time', context)
|
||||
passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo
|
||||
if no_pgo_sources:
|
||||
passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo_sources
|
||||
|
||||
# A map from "canonical suffixes" for a particular source file
|
||||
# language to the range of suffixes associated with that language.
|
||||
#
|
||||
# We deliberately don't list the canonical suffix in the suffix list
|
||||
# in the definition; we'll add it in programmatically after defining
|
||||
# things.
|
||||
suffix_map = {
|
||||
'.s': set(['.asm']),
|
||||
'.c': set(),
|
||||
'.m': set(),
|
||||
'.mm': set(),
|
||||
'.cpp': set(['.cc', '.cxx']),
|
||||
'.S': set(),
|
||||
}
|
||||
|
||||
# The inverse of the above, mapping suffixes to their canonical suffix.
|
||||
canonicalized_suffix_map = {}
|
||||
for suffix, alternatives in suffix_map.iteritems():
|
||||
alternatives.add(suffix)
|
||||
for a in alternatives:
|
||||
canonicalized_suffix_map[a] = suffix
|
||||
|
||||
def canonical_suffix_for_file(f):
|
||||
return canonicalized_suffix_map[mozpath.splitext(f)[1]]
|
||||
|
||||
# A map from moz.build variables to the canonical suffixes of file
|
||||
# kinds that can be listed therein.
|
||||
all_suffixes = list(suffix_map.keys())
|
||||
varmap = dict(
|
||||
SOURCES=(Sources, all_suffixes),
|
||||
HOST_SOURCES=(HostSources, ['.c', '.mm', '.cpp']),
|
||||
UNIFIED_SOURCES=(UnifiedSources, ['.c', '.mm', '.cpp']),
|
||||
GENERATED_SOURCES=(GeneratedSources, all_suffixes),
|
||||
)
|
||||
|
||||
for variable, (klass, suffixes) in varmap.items():
|
||||
allowed_suffixes = set().union(*[suffix_map[s] for s in suffixes])
|
||||
|
||||
# First ensure that we haven't been given filetypes that we don't
|
||||
# recognize.
|
||||
for f in context[variable]:
|
||||
ext = mozpath.splitext(f)[1]
|
||||
if ext not in allowed_suffixes:
|
||||
raise SandboxValidationError(
|
||||
'%s has an unknown file type.' % f, context)
|
||||
if variable.startswith('GENERATED_'):
|
||||
l = passthru.variables.setdefault('GARBAGE', [])
|
||||
l.append(f)
|
||||
|
||||
# Now sort the files to let groupby work.
|
||||
sorted_files = sorted(context[variable], key=canonical_suffix_for_file)
|
||||
for canonical_suffix, files in itertools.groupby(sorted_files, canonical_suffix_for_file):
|
||||
arglist = [context, list(files), canonical_suffix]
|
||||
if variable.startswith('UNIFIED_') and 'FILES_PER_UNIFIED_FILE' in context:
|
||||
arglist.append(context['FILES_PER_UNIFIED_FILE'])
|
||||
yield klass(*arglist)
|
||||
|
||||
sources_with_flags = [f for f in sources if sources[f].flags]
|
||||
for f in sources_with_flags:
|
||||
ext = mozpath.splitext(f)[1]
|
||||
yield PerSourceFlag(context, f, sources[f].flags)
|
||||
|
||||
def _process_xpidl(self, context):
|
||||
# XPIDL source files get processed and turned into .h and .xpt files.
|
||||
# If there are multiple XPIDL files in a directory, they get linked
|
||||
# together into a final .xpt, which has the name defined by
|
||||
# XPIDL_MODULE.
|
||||
xpidl_module = context['XPIDL_MODULE']
|
||||
|
||||
if context['XPIDL_SOURCES'] and not xpidl_module:
|
||||
raise SandboxValidationError('XPIDL_MODULE must be defined if '
|
||||
'XPIDL_SOURCES is defined.', context)
|
||||
|
||||
if xpidl_module and not context['XPIDL_SOURCES']:
|
||||
raise SandboxValidationError('XPIDL_MODULE cannot be defined '
|
||||
'unless there are XPIDL_SOURCES', context)
|
||||
|
||||
if context['XPIDL_SOURCES'] and context['DIST_INSTALL'] is False:
|
||||
self.log(logging.WARN, 'mozbuild_warning', dict(
|
||||
path=context.main_path),
|
||||
'{path}: DIST_INSTALL = False has no effect on XPIDL_SOURCES.')
|
||||
|
||||
for idl in context['XPIDL_SOURCES']:
|
||||
yield XPIDLFile(context, mozpath.join(context.srcdir, idl),
|
||||
xpidl_module)
|
||||
|
||||
def _process_generated_files(self, context):
|
||||
generated_files = context.get('GENERATED_FILES')
|
||||
if not generated_files:
|
||||
return
|
||||
|
||||
for f in generated_files:
|
||||
flags = generated_files[f]
|
||||
output = f
|
||||
if flags.script:
|
||||
method = "main"
|
||||
# Deal with cases like "C:\\path\\to\\script.py:function".
|
||||
if not flags.script.endswith('.py') and ':' in flags.script:
|
||||
script, method = flags.script.rsplit(':', 1)
|
||||
else:
|
||||
script = flags.script
|
||||
script = mozpath.join(context.srcdir, script)
|
||||
inputs = [mozpath.join(context.srcdir, i) for i in flags.inputs]
|
||||
|
||||
if not os.path.exists(script):
|
||||
raise SandboxValidationError(
|
||||
'Script for generating %s does not exist: %s'
|
||||
% (f, script), context)
|
||||
if os.path.splitext(script)[1] != '.py':
|
||||
raise SandboxValidationError(
|
||||
'Script for generating %s does not end in .py: %s'
|
||||
% (f, script), context)
|
||||
for i in inputs:
|
||||
if not os.path.exists(i):
|
||||
raise SandboxValidationError(
|
||||
'Input for generating %s does not exist: %s'
|
||||
% (f, i), context)
|
||||
else:
|
||||
script = None
|
||||
method = None
|
||||
inputs = []
|
||||
yield GeneratedFile(context, script, method, output, inputs)
|
||||
|
||||
def _process_test_harness_files(self, context):
|
||||
test_harness_files = context.get('TEST_HARNESS_FILES')
|
||||
if not test_harness_files:
|
||||
return
|
||||
|
||||
srcdir_files = defaultdict(list)
|
||||
srcdir_pattern_files = defaultdict(list)
|
||||
objdir_files = defaultdict(list)
|
||||
|
||||
for path, strings in test_harness_files.walk():
|
||||
if not path and strings:
|
||||
raise SandboxValidationError(
|
||||
'Cannot install files to the root of TEST_HARNESS_FILES', context)
|
||||
|
||||
for s in strings:
|
||||
if context.is_objdir_path(s):
|
||||
if s.startswith('!/'):
|
||||
objdir_files[path].append('$(DEPTH)/%s' % s[2:])
|
||||
else:
|
||||
objdir_files[path].append(s[1:])
|
||||
else:
|
||||
resolved = context.resolve_path(s)
|
||||
if '*' in s:
|
||||
if s[0] == '/':
|
||||
pattern_start = resolved.index('*')
|
||||
base_path = mozpath.dirname(resolved[:pattern_start])
|
||||
pattern = resolved[len(base_path)+1:]
|
||||
else:
|
||||
base_path = context.srcdir
|
||||
pattern = s
|
||||
srcdir_pattern_files[path].append((base_path, pattern));
|
||||
elif not os.path.exists(resolved):
|
||||
raise SandboxValidationError(
|
||||
'File listed in TEST_HARNESS_FILES does not exist: %s' % s, context)
|
||||
else:
|
||||
srcdir_files[path].append(resolved)
|
||||
|
||||
yield TestHarnessFiles(context, srcdir_files,
|
||||
srcdir_pattern_files, objdir_files)
|
||||
|
||||
def _handle_programs(self, context):
|
||||
for kind, cls in [('PROGRAM', Program), ('HOST_PROGRAM', HostProgram)]:
|
||||
program = context.get(kind)
|
||||
if program:
|
||||
if program in self._binaries:
|
||||
raise SandboxValidationError(
|
||||
'Cannot use "%s" as %s name, '
|
||||
'because it is already used in %s' % (program, kind,
|
||||
self._binaries[program].relativedir), context)
|
||||
self._binaries[program] = cls(context, program)
|
||||
self._linkage.append((context, self._binaries[program],
|
||||
kind.replace('PROGRAM', 'USE_LIBS')))
|
||||
|
||||
for kind, cls in [
|
||||
('SIMPLE_PROGRAMS', SimpleProgram),
|
||||
('CPP_UNIT_TESTS', SimpleProgram),
|
||||
('HOST_SIMPLE_PROGRAMS', HostSimpleProgram)]:
|
||||
for program in context[kind]:
|
||||
if program in self._binaries:
|
||||
raise SandboxValidationError(
|
||||
'Cannot use "%s" in %s, '
|
||||
'because it is already used in %s' % (program, kind,
|
||||
self._binaries[program].relativedir), context)
|
||||
self._binaries[program] = cls(context, program,
|
||||
is_unit_test=kind == 'CPP_UNIT_TESTS')
|
||||
self._linkage.append((context, self._binaries[program],
|
||||
'HOST_USE_LIBS' if kind == 'HOST_SIMPLE_PROGRAMS'
|
||||
else 'USE_LIBS'))
|
||||
|
||||
def _process_test_manifests(self, context):
|
||||
# While there are multiple test manifests, the behavior is very similar
|
||||
# across them. We enforce this by having common handling of all
|
||||
# manifests and outputting a single class type with the differences
|
||||
@@ -865,44 +941,6 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
for obj in self._process_reftest_manifest(context, flavor, path):
|
||||
yield obj
|
||||
|
||||
jar_manifests = context.get('JAR_MANIFESTS', [])
|
||||
if len(jar_manifests) > 1:
|
||||
raise SandboxValidationError('While JAR_MANIFESTS is a list, '
|
||||
'it is currently limited to one value.', context)
|
||||
|
||||
for path in jar_manifests:
|
||||
yield JARManifest(context, mozpath.join(context.srcdir, path))
|
||||
|
||||
# Temporary test to look for jar.mn files that creep in without using
|
||||
# the new declaration. Before, we didn't require jar.mn files to
|
||||
# declared anywhere (they were discovered). This will detect people
|
||||
# relying on the old behavior.
|
||||
if os.path.exists(os.path.join(context.srcdir, 'jar.mn')):
|
||||
if 'jar.mn' not in jar_manifests:
|
||||
raise SandboxValidationError('A jar.mn exists but it '
|
||||
'is not referenced in the moz.build file. '
|
||||
'Please define JAR_MANIFESTS.', context)
|
||||
|
||||
for name, jar in context.get('JAVA_JAR_TARGETS', {}).items():
|
||||
yield ContextWrapped(context, jar)
|
||||
|
||||
for name, data in context.get('ANDROID_ECLIPSE_PROJECT_TARGETS', {}).items():
|
||||
yield ContextWrapped(context, data)
|
||||
|
||||
if passthru.variables:
|
||||
yield passthru
|
||||
|
||||
def _create_substitution(self, cls, context, path):
|
||||
if os.path.isabs(path):
|
||||
path = path[1:]
|
||||
|
||||
sub = cls(context)
|
||||
sub.input_path = mozpath.join(context.srcdir, '%s.in' % path)
|
||||
sub.output_path = mozpath.join(context.objdir, path)
|
||||
sub.relpath = path
|
||||
|
||||
return sub
|
||||
|
||||
def _process_test_manifest(self, context, info, manifest_path):
|
||||
flavor, install_root, install_subdir, package_tests = info
|
||||
|
||||
@@ -914,7 +952,8 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
install_prefix = mozpath.join(install_root, install_subdir)
|
||||
|
||||
try:
|
||||
m = manifestparser.TestManifest(manifests=[path], strict=True)
|
||||
m = manifestparser.TestManifest(manifests=[path], strict=True,
|
||||
rootdir=context.config.topsrcdir)
|
||||
defaults = m.manifest_defaults[os.path.normpath(path)]
|
||||
if not m.tests and not 'support-files' in defaults:
|
||||
raise SandboxValidationError('Empty test manifest: %s'
|
||||
@@ -1008,8 +1047,10 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
# Some test files are compiled and should not be copied into the
|
||||
# test package. They function as identifiers rather than files.
|
||||
if package_tests:
|
||||
manifest_relpath = mozpath.relpath(test['path'],
|
||||
mozpath.dirname(test['manifest']))
|
||||
obj.installs[mozpath.normpath(test['path'])] = \
|
||||
(mozpath.join(out_dir, test['relpath']), True)
|
||||
((mozpath.join(out_dir, manifest_relpath)), True)
|
||||
|
||||
process_support_files(test)
|
||||
|
||||
@@ -1079,6 +1120,25 @@ class TreeMetadataEmitter(LoggingMixin):
|
||||
|
||||
yield obj
|
||||
|
||||
def _process_jar_manifests(self, context):
|
||||
jar_manifests = context.get('JAR_MANIFESTS', [])
|
||||
if len(jar_manifests) > 1:
|
||||
raise SandboxValidationError('While JAR_MANIFESTS is a list, '
|
||||
'it is currently limited to one value.', context)
|
||||
|
||||
for path in jar_manifests:
|
||||
yield JARManifest(context, mozpath.join(context.srcdir, path))
|
||||
|
||||
# Temporary test to look for jar.mn files that creep in without using
|
||||
# the new declaration. Before, we didn't require jar.mn files to
|
||||
# declared anywhere (they were discovered). This will detect people
|
||||
# relying on the old behavior.
|
||||
if os.path.exists(os.path.join(context.srcdir, 'jar.mn')):
|
||||
if 'jar.mn' not in jar_manifests:
|
||||
raise SandboxValidationError('A jar.mn exists but it '
|
||||
'is not referenced in the moz.build file. '
|
||||
'Please define JAR_MANIFESTS.', context)
|
||||
|
||||
def _emit_directory_traversal_from_context(self, context):
|
||||
o = DirectoryTraversal(context)
|
||||
o.dirs = context.get('DIRS', [])
|
||||
|
||||
@@ -61,8 +61,8 @@ class GypContext(TemplateContext):
|
||||
"""
|
||||
def __init__(self, config, relobjdir):
|
||||
self._relobjdir = relobjdir
|
||||
TemplateContext.__init__(self, allowed_variables=self.VARIABLES(),
|
||||
config=config)
|
||||
TemplateContext.__init__(self, template='Gyp',
|
||||
allowed_variables=self.VARIABLES(), config=config)
|
||||
|
||||
@classmethod
|
||||
@memoize
|
||||
@@ -71,7 +71,6 @@ class GypContext(TemplateContext):
|
||||
# Using a class method instead of a class variable to hide the content
|
||||
# from sphinx.
|
||||
return dict(VARIABLES,
|
||||
IS_GYP_DIR=(bool, bool, '', None),
|
||||
EXTRA_ASSEMBLER_FLAGS=(List, list, '', None),
|
||||
EXTRA_COMPILE_FLAGS=(List, list, '', None),
|
||||
)
|
||||
@@ -148,8 +147,6 @@ def read_from_gyp(config, path, output, vars, non_unified_sources = set()):
|
||||
context.add_source(mozpath.abspath(mozpath.join(
|
||||
mozpath.dirname(build_file), f)))
|
||||
|
||||
context['IS_GYP_DIR'] = True
|
||||
|
||||
spec = targets[target]
|
||||
|
||||
# Derive which gyp configuration to use based on MOZ_DEBUG.
|
||||
|
||||
@@ -411,8 +411,10 @@ class MozbuildSandbox(Sandbox):
|
||||
func, code, path = template
|
||||
|
||||
def template_function(*args, **kwargs):
|
||||
context = TemplateContext(self._context._allowed_variables,
|
||||
self._context.config)
|
||||
context = TemplateContext(
|
||||
template=func.func_name,
|
||||
allowed_variables=self._context._allowed_variables,
|
||||
config=self._context.config)
|
||||
context.add_source(self._context.current_path)
|
||||
for p in self._context.all_paths:
|
||||
context.add_source(p)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
GENERATED_FILES += [ 'bar.c', 'foo.c', 'quux.c' ]
|
||||
|
||||
bar = GENERATED_FILES['bar.c']
|
||||
bar.script = 'generate-bar.py'
|
||||
bar.script = 'generate-bar.py:baz'
|
||||
|
||||
foo = GENERATED_FILES['foo.c']
|
||||
foo.script = 'generate-foo.py'
|
||||
|
||||
@@ -379,11 +379,11 @@ class TestRecursiveMakeBackend(BackendTester):
|
||||
expected = [
|
||||
'GENERATED_FILES += bar.c',
|
||||
'bar.c: %s/generate-bar.py' % env.topsrcdir,
|
||||
'$(call py_action,file_generate,%s/generate-bar.py bar.c)' % env.topsrcdir,
|
||||
'$(call py_action,file_generate,%s/generate-bar.py baz bar.c)' % env.topsrcdir,
|
||||
'',
|
||||
'GENERATED_FILES += foo.c',
|
||||
'foo.c: %s/generate-foo.py %s/foo-data' % (env.topsrcdir, env.topsrcdir),
|
||||
'$(call py_action,file_generate,%s/generate-foo.py foo.c %s/foo-data)' % (env.topsrcdir, env.topsrcdir),
|
||||
'$(call py_action,file_generate,%s/generate-foo.py main foo.c %s/foo-data)' % (env.topsrcdir, env.topsrcdir),
|
||||
'',
|
||||
'GENERATED_FILES += quux.c',
|
||||
]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
GENERATED_FILES += ['bar.c']
|
||||
|
||||
bar = GENERATED_FILES['bar.c']
|
||||
bar.script = TOPSRCDIR + '/script.py:make_bar'
|
||||
bar.inputs = []
|
||||
@@ -0,0 +1,13 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
GENERATED_FILES += [ 'bar.c', 'foo.c' ]
|
||||
|
||||
bar = GENERATED_FILES['bar.c']
|
||||
bar.script = 'script.py:make_bar'
|
||||
bar.inputs = []
|
||||
|
||||
foo = GENERATED_FILES['foo.c']
|
||||
foo.script = 'script.py'
|
||||
foo.inputs = []
|
||||
@@ -8,7 +8,7 @@ EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js']
|
||||
FAIL_ON_WARNINGS = True
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
||||
NO_DIST_INSTALL = True
|
||||
DIST_INSTALL = False
|
||||
|
||||
NO_VISIBILITY_FLAGS = True
|
||||
|
||||
|
||||
@@ -194,6 +194,37 @@ class TestEmitterBasic(unittest.TestCase):
|
||||
expected = ['bar.c', 'foo.c']
|
||||
for o, expected_filename in zip(objs, expected):
|
||||
self.assertEqual(o.output, expected_filename)
|
||||
self.assertEqual(o.script, None)
|
||||
self.assertEqual(o.method, None)
|
||||
self.assertEqual(o.inputs, [])
|
||||
|
||||
def test_generated_files_method_names(self):
|
||||
reader = self.reader('generated-files-method-names')
|
||||
objs = self.read_topsrcdir(reader)
|
||||
|
||||
self.assertEqual(len(objs), 2)
|
||||
for o in objs:
|
||||
self.assertIsInstance(o, GeneratedFile)
|
||||
|
||||
expected = ['bar.c', 'foo.c']
|
||||
expected_method_names = ['make_bar', 'main']
|
||||
for o, expected_filename, expected_method in zip(objs, expected, expected_method_names):
|
||||
self.assertEqual(o.output, expected_filename)
|
||||
self.assertEqual(o.method, expected_method)
|
||||
self.assertEqual(o.inputs, [])
|
||||
|
||||
def test_generated_files_absolute_script(self):
|
||||
reader = self.reader('generated-files-absolute-script')
|
||||
objs = self.read_topsrcdir(reader)
|
||||
|
||||
self.assertEqual(len(objs), 1)
|
||||
|
||||
o = objs[0]
|
||||
self.assertIsInstance(o, GeneratedFile)
|
||||
self.assertEqual(o.output, 'bar.c')
|
||||
self.assertRegexpMatches(o.script, 'script.py$')
|
||||
self.assertEqual(o.method, 'make_bar')
|
||||
self.assertEqual(o.inputs, [])
|
||||
|
||||
def test_generated_files_no_script(self):
|
||||
reader = self.reader('generated-files-no-script')
|
||||
|
||||
@@ -29,8 +29,10 @@ def rewrite_test_base(test, new_base, honor_install_to_subdir=False):
|
||||
test['here'] = mozpath.join(new_base, test['dir_relpath'])
|
||||
|
||||
if honor_install_to_subdir and test.get('install-to-subdir'):
|
||||
manifest_relpath = mozpath.relpath(test['path'],
|
||||
mozpath.dirname(test['manifest']))
|
||||
test['path'] = mozpath.join(new_base, test['dir_relpath'],
|
||||
test['install-to-subdir'], test['relpath'])
|
||||
test['install-to-subdir'], manifest_relpath)
|
||||
else:
|
||||
test['path'] = mozpath.join(new_base, test['file_relpath'])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user