diff options
Diffstat (limited to 'python/mozbuild/mozbuild/backend/make.py')
-rw-r--r-- | python/mozbuild/mozbuild/backend/make.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/backend/make.py b/python/mozbuild/mozbuild/backend/make.py new file mode 100644 index 0000000000..90b37e6758 --- /dev/null +++ b/python/mozbuild/mozbuild/backend/make.py @@ -0,0 +1,139 @@ +# 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/. + +import mozpack.path as mozpath + +from mozbuild.frontend.data import GeneratedFile +from mozbuild.shellutil import quote as shell_quote + +from .common import CommonBackend + + +class MakeBackend(CommonBackend): + """Class encapsulating logic for backends that use Make.""" + + def _init(self): + CommonBackend._init(self) + + def _format_statements_for_generated_file(self, obj, tier, extra_dependencies=""): + """Return the list of statements to write to the Makefile for this + GeneratedFile. + + This function will invoke _format_generated_file_input_name and + _format_generated_file_output_name to munge the input/output filenames + before sending them to the output. + """ + assert isinstance(obj, GeneratedFile) + + # Localized generated files can use {AB_CD} and {AB_rCD} in their + # output paths. + if obj.localized: + substs = {"AB_CD": "$(AB_CD)", "AB_rCD": "$(AB_rCD)"} + else: + substs = {} + + outputs = [] + needs_AB_rCD = False + for o in obj.outputs: + needs_AB_rCD = needs_AB_rCD or ("AB_rCD" in o) + try: + outputs.append( + self._format_generated_file_output_name(o.format(**substs), obj) + ) + except KeyError as e: + raise ValueError( + "%s not in %s is not a valid substitution in %s" + % (e.args[0], ", ".join(sorted(substs.keys())), o) + ) + + first_output = outputs[0] + dep_file = mozpath.join( + mozpath.dirname(first_output), + "$(MDDEPDIR)", + "%s.pp" % mozpath.basename(first_output), + ) + # The stub target file needs to go in MDDEPDIR so that it doesn't + # get written into generated Android resource directories, breaking + # Gradle tooling and/or polluting the Android packages. + stub_file = mozpath.join( + mozpath.dirname(first_output), + "$(MDDEPDIR)", + "%s.stub" % mozpath.basename(first_output), + ) + + if obj.inputs: + inputs = [ + self._format_generated_file_input_name(f, obj) for f in obj.inputs + ] + else: + inputs = [] + + force = "" + if obj.force: + force = " FORCE" + elif obj.localized: + force = " $(if $(IS_LANGUAGE_REPACK),FORCE)" + + ret = [] + + if obj.script: + # If we are doing an artifact build, we don't run compiler, so + # we can skip generated files that are needed during compile, + # or let the rule run as the result of something depending on + # it. + if ( + not (obj.required_before_compile or obj.required_during_compile) + or not self.environment.is_artifact_build + ): + if tier and not needs_AB_rCD: + # Android localized resources have special Makefile + # handling. + + # Double-colon tiers via a variable that the backend adds as a dependency + # later. See https://bugzilla.mozilla.org/show_bug.cgi?id=1645986#c0 as + # to why. + if tier in ("export", "pre-compile", "libs", "misc"): + dep = "%s_TARGETS" % tier.replace("-", "_").upper() + ret.append("%s += %s" % (dep, stub_file)) + else: + ret.append("%s: %s" % (tier, stub_file)) + for output in outputs: + ret.append("%s: %s ;" % (output, stub_file)) + ret.append("EXTRA_MDDEPEND_FILES += %s" % dep_file) + + ret.append( + ( + """{stub}: {script}{inputs}{backend}{force} +\t$(REPORT_BUILD) +\t$(call py_action,file_generate,{locale}{script} """ # wrap for E501 + """{method} {output} {dep_file} {stub}{inputs}{flags}) +\t@$(TOUCH) $@ +""" + ).format( + stub=stub_file, + output=first_output, + dep_file=dep_file, + inputs=" " + " ".join(inputs) if inputs else "", + flags=" " + " ".join(shell_quote(f) for f in obj.flags) + if obj.flags + else "", + backend=" " + extra_dependencies if extra_dependencies else "", + # Locale repacks repack multiple locales from a single configured objdir, + # so standard mtime dependencies won't work properly when the build is re-run + # with a different locale as input. IS_LANGUAGE_REPACK will reliably be set + # in this situation, so simply force the generation to run in that case. + force=force, + locale="--locale=$(AB_CD) " if obj.localized else "", + script=obj.script, + method=obj.method, + ) + ) + + return ret + + def _format_generated_file_input_name(self, path, obj): + raise NotImplementedError("Subclass must implement") + + def _format_generated_file_output_name(self, path, obj): + raise NotImplementedError("Subclass must implement") |