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 159435 92ee006ec0a59d93557d8197ad020ed226faa65d
parent 159434 595ef28d3cf1d60ffe70d6f76f4effbbb7021504
child 159436 45097bc3a57898f22a4f3b74f8f8cf7511f5d0a4
push id407
push userlsblakk@mozilla.com
push dateTue, 03 Dec 2013 03:32:50 +0000
treeherdermozilla-release@babf8c9ebc52 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs912293
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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')