Bug 1428608: Allow explicitly specifying dirs from EXTERNAL_SOURCE_DIR to recurse into; r?Build
MozReview-Commit-ID: DuQpmyMOtpM
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -20,16 +20,17 @@ from mozpack.manifests import (
)
import mozpack.path as mozpath
from mozbuild.frontend.context import (
AbsolutePath,
Path,
RenamedSourcePath,
SourcePath,
+ ExternalSourcePath,
ObjDirPath,
)
from .common import CommonBackend
from ..frontend.data import (
AndroidAssetsDirs,
AndroidResDirs,
AndroidExtraResDirs,
AndroidExtraPackages,
@@ -962,16 +963,18 @@ class RecursiveMakeBackend(CommonBackend
return '$(srcdir)', path.full_path[len(backend_file.srcdir):]
if path.full_path.startswith(backend_file.topsrcdir):
return '$(topsrcdir)', path.full_path[len(backend_file.topsrcdir):]
elif isinstance(path, ObjDirPath):
if path.full_path.startswith(backend_file.objdir):
return '', path.full_path[len(backend_file.objdir) + 1:]
if path.full_path.startswith(self.environment.topobjdir):
return '$(DEPTH)', path.full_path[len(self.environment.topobjdir):]
+ elif isinstance(path, ExternalSourcePath):
+ return '$(EXTERNAL_SOURCE_DIR)', path.full_path[len(self.environment.external_source_dir):]
return '', path.full_path
def _pretty_path(self, path, backend_file):
return ''.join(self._pretty_path_parts(path, backend_file))
def _process_unified_sources(self, obj):
backend_file = self._get_backend_file_for(obj)
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -677,16 +677,48 @@ class SourcePath(Path):
Ideally, we wouldn't need this function, but the fact that both source
path under topsrcdir and the external source dir end up mixed in the
objdir (aka pseudo-rework), this is needed.
"""
return ObjDirPath(self.context, '!%s' % self).full_path
+class ExternalSourcePath(SourcePath):
+ """Like Path, but limited to paths in the source directory."""
+ def __init__(self, context, value):
+ if not os.path.isabs(value):
+ raise ValueError('Path \'%s\' is not absolute' % value)
+ # We explicitly skip calling SourcePath's __init__ here
+ super(SourcePath, self).__init__(context, value)
+
+ if context.config.external_source_dir:
+ path = mozpath.join(context.config.external_source_dir,
+ value[1:])
+ else:
+ raise ValueError('External source directory requested but none specified')
+ self.full_path = mozpath.normpath(path)
+
+ def join(self, *p):
+ """ContextDerived equivalent of mozpath.join(self, *p), returning a
+ new ExternalSourcePath instance.
+ """
+ return ExternalSourcePath(self.context, mozpath.join(self, *p))
+
+ @memoized_property
+ def translated(self):
+ """Returns the corresponding path in the objdir.
+
+ Ideally, we wouldn't need this function, but the fact that both source
+ path under topsrcdir and the external source dir end up mixed in the
+ objdir (aka pseudo-rework), this is needed.
+ """
+ return ObjDirPath(self.context, '!%s' % self).full_path
+
+
class RenamedSourcePath(SourcePath):
"""Like SourcePath, but with a different base name when installed.
The constructor takes a tuple of (source, target_basename).
This class is not meant to be exposed to moz.build sandboxes as of now,
and is not supported by the RecursiveMake backend.
"""
@@ -1386,16 +1418,20 @@ VARIABLES = {
and read the frontend file there. If there is no frontend file, an error
is raised.
Values are relative paths. They can be multiple directory levels
above or below. Use ``..`` for parent directories and ``/`` for path
delimiters.
"""),
+ 'EXTERNAL_SOURCE_DIRS': (ContextDerivedTypedList(ExternalSourcePath), list,
+ """Directories relative to EXTERNAL_SOURCE_DIR.
+ """),
+
'HAS_MISC_RULE': (bool, bool,
"""Whether this directory should be traversed in the ``misc`` tier.
Many ``libs`` rules still exist in Makefile.in files. We highly prefer
that these rules exist in the ``misc`` tier/target so that they can be
executed concurrently during tier traversal (the ``misc`` tier is
fully concurrent).
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -1591,15 +1591,16 @@ class TreeMetadataEmitter(LoggingMixin):
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', [])
+ o.dirs += context.get('EXTERNAL_SOURCE_DIRS', [])
# Some paths have a subconfigure, yet also have a moz.build. Those
# shouldn't end up in self._external_paths.
if o.objdir:
self._external_paths -= { o.relobjdir }
yield o
--- a/python/mozbuild/mozbuild/frontend/reader.py
+++ b/python/mozbuild/mozbuild/frontend/reader.py
@@ -1123,16 +1123,17 @@ class BuildReader(object):
# Yield main context before doing any processing. This gives immediate
# consumers an opportunity to change state before our remaining
# processing is performed.
yield context
# We need the list of directories pre-gyp processing for later.
dirs = list(context.get('DIRS', []))
+ dirs += list(context.get('EXTERNAL_SOURCE_DIRS', []))
curdir = mozpath.dirname(path)
for target_dir in context.get('GYP_DIRS', []):
gyp_dir = context['GYP_DIRS'][target_dir]
for v in ('input', 'variables'):
if not getattr(gyp_dir, v):
raise SandboxValidationError('Missing value for '
@@ -1302,17 +1303,17 @@ class BuildReader(object):
contexts = defaultdict(list)
all_contexts = []
for context in self.read_mozbuild(mozpath.join(topsrcdir, 'moz.build'),
self.config, metadata=metadata):
# Explicitly set directory traversal variables to override default
# traversal rules.
if not isinstance(context, SubContext):
- for v in ('DIRS', 'GYP_DIRS'):
+ for v in ('DIRS', 'GYP_DIRS', 'EXTERNAL_SOURCE_DIRS'):
context[v][:] = []
context['DIRS'] = sorted(dirs[context.main_path])
contexts[context.main_path].append(context)
all_contexts.append(context)
result = {}