diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py index fc3f505e280f..88a479edb53f 100644 --- a/python/mozbuild/mozbuild/backend/recursivemake.py +++ b/python/mozbuild/mozbuild/backend/recursivemake.py @@ -31,11 +31,13 @@ from ..frontend.data import ( GeneratedWebIDLFile, InstallationTarget, IPDLFile, + JavaJarData, LocalInclude, PreprocessedTestWebIDLFile, PreprocessedWebIDLFile, Program, SandboxDerived, + SandboxWrapped, TestWebIDLFile, VariablePassthru, XPIDLFile, @@ -417,6 +419,15 @@ class RecursiveMakeBackend(CommonBackend): elif isinstance(obj, InstallationTarget): self._process_installation_target(obj, backend_file) + elif isinstance(obj, SandboxWrapped): + # Process a rich build system object from the front-end + # as-is. Please follow precedent and handle CamelCaseData + # in a function named _process_camel_case_data. At some + # point in the future, this unwrapping process may be + # automated. + if isinstance(obj.wrapped, JavaJarData): + self._process_java_jar_data(obj.wrapped, backend_file) + self._backend_files[obj.srcdir] = backend_file def _fill_root_mk(self): @@ -1004,6 +1015,23 @@ class RecursiveMakeBackend(CommonBackend): path = '' backend_file.write('LOCAL_INCLUDES += -I%s%s\n' % (path, generated_include)) + def _process_java_jar_data(self, jar, backend_file): + target = jar.name + backend_file.write('JAVA_JAR_TARGETS += %s\n' % target) + backend_file.write('%s_DEST := %s.jar\n' % (target, jar.name)) + if jar.sources: + backend_file.write('%s_JAVAFILES := %s\n' % + (target, ' '.join(jar.sources))) + if jar.generated_sources: + backend_file.write('%s_PP_JAVAFILES := %s\n' % + (target, ' '.join(jar.generated_sources))) + if jar.extra_jars: + backend_file.write('%s_EXTRA_JARS := %s\n' % + (target, ' '.join(jar.extra_jars))) + if jar.javac_flags: + backend_file.write('%s_JAVAC_FLAGS := %s\n' % + (target, jar.javac_flags)) + def _write_manifests(self, dest, manifests): man_dir = os.path.join(self.environment.topobjdir, '_build_manifests', dest) diff --git a/python/mozbuild/mozbuild/frontend/data.py b/python/mozbuild/mozbuild/frontend/data.py index 8d525212e68a..7307fe10789b 100644 --- a/python/mozbuild/mozbuild/frontend/data.py +++ b/python/mozbuild/mozbuild/frontend/data.py @@ -371,6 +371,54 @@ class GeneratedInclude(SandboxDerived): self.path = path + +class SandboxWrapped(SandboxDerived): + """Generic sandbox container object for a wrapped rich object. + + Use this wrapper class to shuttle a rich build system object + completely defined in moz.build files through the tree metadata + emitter to the build backend for processing as-is. + """ + + __slots__ = ( + 'wrapped', + ) + + def __init__(self, sandbox, wrapped): + SandboxDerived.__init__(self, sandbox) + + self.wrapped = wrapped + + +class JavaJarData(object): + """Represents a Java JAR file. + + A Java JAR has the following members: + * sources - list of input java sources + * generated_sources - list of generated input java sources + * extra_jars - list of JAR file dependencies to include on the + javac compiler classpath + * javac_flags - string containing extra flags passed to the + javac compiler + """ + + __slots__ = ( + 'name', + 'sources', + 'generated_sources', + 'extra_jars', + 'javac_flags', + ) + + def __init__(self, name, sources=[], generated_sources=[], + extra_jars=[], javac_flags=None): + self.name = name + self.sources = list(sources) + self.generated_sources = list(generated_sources) + self.extra_jars = list(extra_jars) + self.javac_flags = javac_flags + + class InstallationTarget(SandboxDerived): """Describes the rules that affect where files get installed to.""" diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index 7102a464d45a..9302522efb24 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -32,6 +32,7 @@ from .data import ( PreprocessedWebIDLFile, Program, ReaderSummary, + SandboxWrapped, TestWebIDLFile, TestManifest, VariablePassthru, @@ -258,6 +259,9 @@ class TreeMetadataEmitter(LoggingMixin): for obj in self._process_test_manifest(sandbox, info, path): yield obj + for name, jar in sandbox.get('JAVA_JAR_TARGETS', {}).items(): + yield SandboxWrapped(sandbox, jar) + def _process_test_manifest(self, sandbox, info, manifest_path): flavor, install_prefix, filter_inactive = info diff --git a/python/mozbuild/mozbuild/frontend/reader.py b/python/mozbuild/mozbuild/frontend/reader.py index 45b7f440d8c9..979eaa2cec66 100644 --- a/python/mozbuild/mozbuild/frontend/reader.py +++ b/python/mozbuild/mozbuild/frontend/reader.py @@ -40,6 +40,10 @@ from mozbuild.util import ( from mozbuild.backend.configenvironment import ConfigEnvironment +from .data import ( + JavaJarData, +) + from .sandbox import ( SandboxError, SandboxExecutionError, @@ -222,6 +226,22 @@ class MozbuildSandbox(Sandbox): Sandbox.exec_file(self, path) + def _add_java_jar(self, name): + """Add a Java JAR build target.""" + if not name: + raise Exception('Java JAR cannot be registered without a name') + + if '/' in name or '\\' in name or '.jar' in name: + raise Exception('Java JAR names must not include slashes or' + ' .jar: %s' % name) + + if self['JAVA_JAR_TARGETS'].has_key(name): + raise Exception('Java JAR has already been registered: %s' % name) + + jar = JavaJarData(name) + self['JAVA_JAR_TARGETS'][name] = jar + return jar + def _add_tier_directory(self, tier, reldir, static=False, external=False): """Register a tier directory with the build.""" if isinstance(reldir, text_type): diff --git a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py index 425a4aa3254c..b85a1a40dcf6 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py +++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py @@ -209,6 +209,13 @@ VARIABLES = { """Name of target library generated when cross compiling. """, 'binaries'), + 'JAVA_JAR_TARGETS': (dict, dict, {}, + """Defines Java JAR targets to be built. + + This variable should not be populated directly. Instead, it should + populated by calling add_java_jar(). + """, 'binaries'), + 'JS_MODULES_PATH': (unicode, unicode, "", """Sub-directory of ``$(FINAL_TARGET)`` to install ``EXTRA_JS_MODULES``. @@ -535,6 +542,19 @@ FUNCTIONS = { include('/elsewhere/foo.build') """), + 'add_java_jar': ('_add_java_jar', (str,), + """Declare a Java JAR target to be built. + + This is the supported way to populate the JAVA_JAR_TARGETS + variable. + + The parameters are: + * dest - target name, without the trailing .jar. (required) + + This returns a rich Java JAR type, described at + :py:class:`mozbuild.frontend.data.JavaJarData`. + """), + 'add_tier_dir': ('_add_tier_directory', (str, [str, list], bool, bool), """Register a directory for tier traversal.