Bug 912293 - Add a generic header and footer to generated Makefiles. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 05 Sep 2013 09:01:45 +0900
changeset 145614 92ee006ec0a59d93557d8197ad020ed226faa65d
parent 145613 595ef28d3cf1d60ffe70d6f76f4effbbb7021504
child 145615 45097bc3a57898f22a4f3b74f8f8cf7511f5d0a4
push id2502
push useremorley@mozilla.com
push dateThu, 05 Sep 2013 13:54:42 +0000
treeherderfx-team@efe592efe709 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs912293
milestone26.0a1
Bug 912293 - Add a generic header and footer to generated Makefiles. r=gps
config/autoconf.mk.in
config/baseconfig.mk
config/rules.mk
js/src/config/autoconf.mk.in
js/src/config/baseconfig.mk
js/src/config/rules.mk
js/src/configure.in
python/mozbuild/mozbuild/backend/configenvironment.py
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/test/backend/data/stub0/Makefile.in
python/mozbuild/mozbuild/test/backend/test_recursivemake.py
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -1,3 +1,6 @@
+ifndef INCLUDED_AUTOCONF_MK
+INCLUDED_AUTOCONF_MK = 1
 include $(DEPTH)/config/emptyvars.mk
 @ALLSUBSTS@
 include $(topsrcdir)/config/baseconfig.mk
+endif
--- a/config/baseconfig.mk
+++ b/config/baseconfig.mk
@@ -1,10 +1,8 @@
-INCLUDED_AUTOCONF_MK = 1
-
 includedir := $(includedir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
 idldir = $(datadir)/idl/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
 installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
 sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
 DIST = $(DEPTH)/dist
 
 # We do magic with OBJ_SUFFIX in config.mk, the following ensures we don't
 # manually use it before config.mk inclusion
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -5,16 +5,22 @@
 # 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/.
 #
 
 ifndef topsrcdir
 $(error topsrcdir was not set))
 endif
 
+# Define an include-at-most-once flag
+ifdef INCLUDED_RULES_MK
+$(error Do not include rules.mk twice!)
+endif
+INCLUDED_RULES_MK = 1
+
 # Integrate with mozbuild-generated make files. We first verify that no
 # variables provided by the automatically generated .mk files are
 # present. If they are, this is a violation of the separation of
 # responsibility between Makefile.in and mozbuild files.
 _MOZBUILD_EXTERNAL_VARIABLES := \
   CPP_UNIT_TESTS \
   DIRS \
   EXTRA_PP_COMPONENTS \
--- a/js/src/config/autoconf.mk.in
+++ b/js/src/config/autoconf.mk.in
@@ -1,3 +1,6 @@
+ifndef INCLUDED_AUTOCONF_MK
+INCLUDED_AUTOCONF_MK = 1
 include $(DEPTH)/config/emptyvars.mk
 @ALLSUBSTS@
 include $(topsrcdir)/config/baseconfig.mk
+endif
--- a/js/src/config/baseconfig.mk
+++ b/js/src/config/baseconfig.mk
@@ -1,10 +1,8 @@
-INCLUDED_AUTOCONF_MK = 1
-
 installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
 sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
 
 ifneq (,$(filter /%,$(TOP_DIST)))
 DIST = $(TOP_DIST)
 else
 DIST = $(DEPTH)/$(TOP_DIST)
 endif
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -5,16 +5,22 @@
 # 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/.
 #
 
 ifndef topsrcdir
 $(error topsrcdir was not set))
 endif
 
+# Define an include-at-most-once flag
+ifdef INCLUDED_RULES_MK
+$(error Do not include rules.mk twice!)
+endif
+INCLUDED_RULES_MK = 1
+
 # Integrate with mozbuild-generated make files. We first verify that no
 # variables provided by the automatically generated .mk files are
 # present. If they are, this is a violation of the separation of
 # responsibility between Makefile.in and mozbuild files.
 _MOZBUILD_EXTERNAL_VARIABLES := \
   CPP_UNIT_TESTS \
   DIRS \
   EXTRA_PP_COMPONENTS \
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4336,17 +4336,17 @@ AC_HAVE_FUNCS(localeconv)
 
 AC_SUBST(MOZILLA_VERSION)
 
 AC_SUBST(ac_configure_args)
 
 dnl Spit out some output
 dnl ========================================================
 
-AC_OUTPUT([js-confdefs.h Makefile config/autoconf.mk config/emptyvars.mk])
+AC_OUTPUT([js-confdefs.h config/autoconf.mk config/emptyvars.mk])
 
 # Produce the js-config script at configure time; see the comments for
 # 'js*-config' in Makefile.in.
 AC_MSG_RESULT(invoking $MAKE to create $JS_CONFIG_NAME script)
 $MAKE $JS_CONFIG_NAME
 
 # Build jsctypes if it's enabled.
 if test "$JS_HAS_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then
--- a/python/mozbuild/mozbuild/backend/configenvironment.py
+++ b/python/mozbuild/mozbuild/backend/configenvironment.py
@@ -200,31 +200,65 @@ class ConfigEnvironment(object):
         taking the corresponding source file and replacing occurences of
         "@VAR@" by the value corresponding to "VAR" in the substs dict.
 
         Additional substs are defined according to the file being treated:
             "srcdir" for its the path to its source directory
             "relativesrcdir" for its source directory relative to the top
             "DEPTH" for the path to the top object directory
         '''
-        input = self.get_input(path)
+        if os.path.basename(path) == 'Makefile':
+            return self.create_makefile(path, extra=extra)
+        pp = self._get_preprocessor(path, extra)
+        pp.do_include(self.get_input(path))
+        return pp.out.close()
+
+    def create_makefile(self, path, stub=False, extra=None):
+        '''Creates the given makefile. Makefiles are treated the same as
+        config files, but some additional header and footer is added to the
+        output.
+
+        When the stub argument is True, no source file is used, and a stub
+        makefile with the default header and footer only is created.
+        '''
+        pp = self._get_preprocessor(path, extra)
+        pp.handleLine('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
+        pp.handleLine('DEPTH := @DEPTH@\n')
+        pp.handleLine('topsrcdir := @top_srcdir@\n')
+        pp.handleLine('srcdir := @srcdir@\n')
+        pp.handleLine('VPATH := @srcdir@\n')
+        pp.handleLine('relativesrcdir := @relativesrcdir@\n')
+        pp.handleLine('include $(DEPTH)/config/autoconf.mk\n')
+        if not stub:
+            pp.do_include(self.get_input(path))
+        # Empty line to avoid failures when last line in Makefile.in ends
+        # with a backslash.
+        pp.handleLine('\n')
+        pp.handleLine('ifndef INCLUDED_RULES_MK\n')
+        pp.handleLine('include $(topsrcdir)/config/rules.mk\n')
+        pp.handleLine('endif\n')
+        return pp.out.close()
+
+    def _get_preprocessor(self, path, extra):
+        '''Returns a preprocessor for use by create_config_file and
+        create_makefile.
+        '''
         pp = Preprocessor()
         pp.context.update(self.substs)
         pp.context.update(top_srcdir = self.get_top_srcdir(path))
         pp.context.update(srcdir = self.get_file_srcdir(path))
         pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
         pp.context.update(DEPTH = self.get_depth(path))
         if extra:
             pp.context.update(extra)
         pp.do_filter('attemptSubstitution')
         pp.setMarker(None)
 
         pp.out = FileAvoidWrite(path)
-        pp.do_include(input)
-        return pp.out.close()
+        return pp
 
     def create_config_header(self, path):
         '''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"
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -26,29 +26,16 @@ from ..frontend.data import (
     Exports,
     Program,
     XPIDLFile,
     XpcshellManifests,
 )
 from ..util import FileAvoidWrite
 
 
-STUB_MAKEFILE = '''
-# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.
-
-DEPTH          := {depth}
-topsrcdir      := {topsrc}
-srcdir         := {src}
-VPATH          := {src}
-relativesrcdir := {relsrc}
-
-include {topsrc}/config/rules.mk
-'''.lstrip()
-
-
 class BackendMakeFile(object):
     """Represents a generated backend.mk file.
 
     This is both a wrapper around a file handle as well as a container that
     holds accumulated state.
 
     It's worth taking a moment to explain the make dependencies. The
     generated backend.mk as well as the Makefile.in (if it exists) are in the
@@ -232,45 +219,34 @@ class RecursiveMakeBackend(CommonBackend
                     if error.errno != errno.EEXIST:
                         raise
 
             makefile_in = os.path.join(srcdir, 'Makefile.in')
             makefile = os.path.join(bf.objdir, 'Makefile')
 
             # If Makefile.in exists, use it as a template. Otherwise, create a
             # stub.
-            if os.path.exists(makefile_in):
+            stub = not os.path.exists(makefile_in)
+            if not stub:
                 self.log(logging.DEBUG, 'substitute_makefile',
                     {'path': makefile}, 'Substituting makefile: {path}')
 
-                self._update_from_avoid_write(
-                    bf.environment.create_config_file(makefile))
-                self.summary.managed_count += 1
-
                 # Adding the Makefile.in here has the desired side-effect that
                 # if the Makefile.in disappears, this will force moz.build
                 # traversal. This means that when we remove empty Makefile.in
                 # files, the old file will get replaced with the autogenerated
                 # one automatically.
                 self.backend_input_files.add(makefile_in)
             else:
                 self.log(logging.DEBUG, 'stub_makefile',
                     {'path': makefile}, 'Creating stub Makefile: {path}')
 
-                params = {
-                    'topsrc': bf.environment.get_top_srcdir(makefile),
-                    'src': bf.environment.get_file_srcdir(makefile),
-                    'depth': bf.environment.get_depth(makefile),
-                    'relsrc': bf.environment.get_relative_srcdir(makefile),
-                }
-
-                aw = FileAvoidWrite(makefile)
-                aw.write(STUB_MAKEFILE.format(**params))
-                self._update_from_avoid_write(aw.close())
-                self.summary.managed_count += 1
+            self._update_from_avoid_write(
+                bf.environment.create_makefile(makefile, stub=stub))
+            self.summary.managed_count += 1
 
             self._update_from_avoid_write(bf.close())
             self.summary.managed_count += 1
 
 
         # Write out a master list of all IPDL source files.
         ipdls = FileAvoidWrite(os.path.join(self.environment.topobjdir,
             'ipc', 'ipdl', 'ipdlsrcs.mk'))
--- a/python/mozbuild/mozbuild/test/backend/data/stub0/Makefile.in
+++ b/python/mozbuild/mozbuild/test/backend/data/stub0/Makefile.in
@@ -1,11 +1,4 @@
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
-DEPTH := @DEPTH@
-topsrcdir := @top_srcdir@
-srcdir := @srcdir@
-VPATH = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-include $(topsrcdir)/config/rules.mk
+FOO := foo
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -42,37 +42,41 @@ class TestRecursiveMakeBackend(BackendTe
             self.assertTrue(os.path.exists(out_backend))
 
     def test_makefile_conversion(self):
         """Ensure Makefile.in is converted properly."""
         env = self._consume('stub0', RecursiveMakeBackend)
 
         p = os.path.join(env.topobjdir, 'Makefile')
 
-        lines = [l.strip() for l in open(p, 'rt').readlines()[3:]]
+        lines = [l.strip() for l in open(p, 'rt').readlines()[1:] if not l.startswith('#')]
         self.assertEqual(lines, [
             'DEPTH := .',
             'topsrcdir := %s' % env.topsrcdir,
             'srcdir := %s' % env.topsrcdir,
-            'VPATH = %s' % env.topsrcdir,
-            '',
+            'VPATH := %s' % env.topsrcdir,
+            'relativesrcdir := .',
             'include $(DEPTH)/config/autoconf.mk',
             '',
-            'include $(topsrcdir)/config/rules.mk'
+            'FOO := foo',
+            '',
+            'ifndef INCLUDED_RULES_MK',
+            'include $(topsrcdir)/config/rules.mk',
+            'endif',
         ])
 
     def test_missing_makefile_in(self):
         """Ensure missing Makefile.in results in Makefile creation."""
         env = self._consume('stub0', RecursiveMakeBackend)
 
         p = os.path.join(env.topobjdir, 'dir2', 'Makefile')
         self.assertTrue(os.path.exists(p))
 
         lines = [l.strip() for l in open(p, 'rt').readlines()]
-        self.assertEqual(len(lines), 9)
+        self.assertEqual(len(lines), 11)
 
         self.assertTrue(lines[0].startswith('# THIS FILE WAS AUTOMATICALLY'))
 
     def test_backend_mk(self):
         """Ensure backend.mk file is written out properly."""
         env = self._consume('stub0', RecursiveMakeBackend)
 
         p = os.path.join(env.topobjdir, 'backend.mk')