Bug 945042 - Add moz.build infrastructure to replace NO_PROFILE_GUIDED_OPTIMIZE from Makefile.in. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Mon, 09 Dec 2013 13:39:16 +0900
changeset 174168 473d459b4bba7cbd915bcc9693875d3f770a341f
parent 174167 c9d4612aef4c5e14a194d8cd815fee3a302ccfaf
child 174169 85196889c598679878fd65d6f36832623f1de7e9
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs945042
milestone28.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 945042 - Add moz.build infrastructure to replace NO_PROFILE_GUIDED_OPTIMIZE from Makefile.in. r=gps
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/frontend/sandbox_symbols.py
python/mozbuild/mozbuild/test/test_util.py
python/mozbuild/mozbuild/util.py
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -253,16 +253,26 @@ class TreeMetadataEmitter(LoggingMixin):
                 if ext not in mapping:
                     raise SandboxValidationError('%s has an unknown file type in %s' % (f, sandbox['RELATIVEDIR']))
                 l = passthru.variables.setdefault(mapping[ext], [])
                 l.append(f)
                 if variable.startswith('GENERATED_'):
                     l = passthru.variables.setdefault('GARBAGE', [])
                     l.append(f)
 
+        no_pgo = sandbox.get('NO_PGO')
+        sources = sandbox.get('SOURCES', [])
+        no_pgo_sources = [f for f in sources if sources[f].no_pgo]
+        if no_pgo:
+            if no_pgo_sources:
+                raise SandboxValidationError('NO_PGO and SOURCES[...].no_pgo cannot be set at the same time')
+            passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo
+        if no_pgo_sources:
+            passthru.variables['NO_PROFILE_GUIDED_OPTIMIZE'] = no_pgo_sources
+
         exports = sandbox.get('EXPORTS')
         if exports:
             yield Exports(sandbox, exports,
                 dist_install=not sandbox.get('NO_DIST_INSTALL', False))
 
         defines = sandbox.get('DEFINES')
         if defines:
             yield Defines(sandbox, defines)
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -16,16 +16,17 @@ the Sandbox consists of, you've come to 
 """
 
 from __future__ import unicode_literals
 
 from collections import OrderedDict
 from mozbuild.util import (
     HierarchicalStringList,
     StrictOrderingOnAppendList,
+    StrictOrderingOnAppendListWithFlagsFactory,
 )
 from .sandbox import SandboxDerivedValue
 from types import StringTypes
 
 
 class FinalTargetValue(SandboxDerivedValue, unicode):
     def __new__(cls, sandbox, value=""):
         if not value:
@@ -69,17 +70,17 @@ VARIABLES = {
 
     'ANDROID_RESFILES': (StrictOrderingOnAppendList, list,
         """Android resource files.
 
         This variable contains a list of files to package into a 'res'
         directory and merge into an APK file.
         """, 'export'),
 
-    'SOURCES': (StrictOrderingOnAppendList, list,
+    'SOURCES': (StrictOrderingOnAppendListWithFlagsFactory({'no_pgo': bool}), list,
         """Source code files.
 
         This variable contains a list of source code files to compile.
         Accepts assembler, C, C++, Objective C/C++.
         """, 'compile'),
 
     'GENERATED_SOURCES': (StrictOrderingOnAppendList, list,
         """Generated source code files.
@@ -291,17 +292,21 @@ VARIABLES = {
         Implies ``MOZILLA_INTERNAL_API`` and ``FORCE_STATIC_LIB``.
         """, None),
 
     'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list,
         """Additional directories to be searched for include files by the compiler.
         """, None),
 
     'MSVC_ENABLE_PGO': (bool, bool,
-        """Whether profile-guided optimization is enabled in this directory.
+        """Whether profile-guided optimization is enabled for MSVC in this directory.
+        """, None),
+
+    'NO_PGO': (bool, bool,
+        """Whether profile-guided optimization is disable in this directory.
         """, None),
 
     'NO_VISIBILITY_FLAGS': (bool, bool,
         """Build sources listed in this file without VISIBILITY_FLAGS.
         """, None),
 
     'OS_LIBS': (list, list,
         """System link libraries.
--- a/python/mozbuild/mozbuild/test/test_util.py
+++ b/python/mozbuild/mozbuild/test/test_util.py
@@ -17,16 +17,17 @@ from mozunit import (
 
 from mozbuild.util import (
     FileAvoidWrite,
     hash_file,
     resolve_target_to_make,
     MozbuildDeletionError,
     HierarchicalStringList,
     StrictOrderingOnAppendList,
+    StrictOrderingOnAppendListWithFlagsFactory,
     UnsortedError,
 )
 
 if sys.version_info[0] == 3:
     str_type = 'str'
 else:
     str_type = 'unicode'
 
@@ -280,10 +281,44 @@ class TestStrictOrderingOnAppendList(uni
         self.assertIsInstance(l, StrictOrderingOnAppendList)
 
         with self.assertRaises(UnsortedError):
             l += ['b', 'a']
 
         self.assertEqual(len(l), 2)
 
 
+class TestStrictOrderingOnAppendListWithFlagsFactory(unittest.TestCase):
+    def test_strict_ordering_on_append_list_with_flags_factory(self):
+        cls = StrictOrderingOnAppendListWithFlagsFactory({
+            'foo': bool,
+            'bar': int,
+        })
+
+        l = cls()
+        l += ['a', 'b']
+
+        with self.assertRaises(Exception):
+            l['a'] = 'foo'
+
+        with self.assertRaises(Exception):
+            c = l['c']
+
+        self.assertEqual(l['a'].foo, False)
+        l['a'].foo = True
+        self.assertEqual(l['a'].foo, True)
+
+        with self.assertRaises(TypeError):
+            l['a'].bar = 'bar'
+
+        self.assertEqual(l['a'].bar, 0)
+        l['a'].bar = 42
+        self.assertEqual(l['a'].bar, 42)
+
+        l['b'].foo = True
+        self.assertEqual(l['b'].foo, True)
+
+        with self.assertRaises(AttributeError):
+            l['b'].baz = False
+
+
 if __name__ == '__main__':
     main()
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -296,16 +296,84 @@ class StrictOrderingOnAppendList(list):
         list.__iadd__(self, other)
 
         return self
 
 
 class MozbuildDeletionError(Exception):
     pass
 
+
+def StrictOrderingOnAppendListWithFlagsFactory(flags):
+    """Returns a StrictOrderingOnAppendList-like object, with optional
+    flags on each item.
+
+    The flags are defined in the dict given as argument, where keys are
+    the flag names, and values the type used for the value of that flag.
+
+    Example:
+        FooList = StrictOrderingOnAppendListWithFlagsFactory({
+            'foo': bool, 'bar': unicode
+        })
+        foo = FooList(['a', 'b', 'c'])
+        foo['a'].foo = True
+        foo['b'].bar = 'bar'
+    """
+
+    assert isinstance(flags, dict)
+    assert all(isinstance(v, type) for v in flags.values())
+
+    class Flags(object):
+        __slots__ = flags.keys()
+        _flags = flags
+
+        def __getattr__(self, name):
+            if name not in self.__slots__:
+                raise AttributeError("'%s' object has no attribute '%s'" %
+                                     (self.__class__.__name__, name))
+            try:
+                return object.__getattr__(self, name)
+            except AttributeError:
+                value = self._flags[name]()
+                self.__setattr__(name, value)
+                return value
+
+        def __setattr__(self, name, value):
+            if name not in self.__slots__:
+                raise AttributeError("'%s' object has no attribute '%s'" %
+                                     (self.__class__.__name__, name))
+            if not isinstance(value, self._flags[name]):
+                raise TypeError("'%s' attribute of class '%s' must be '%s'" %
+                                (name, self.__class__.__name__,
+                                 self._flags[name].__name__))
+            return object.__setattr__(self, name, value)
+
+        def __delattr__(self, name):
+            raise MozbuildDeletionError('Unable to delete attributes for this object')
+
+    class StrictOrderingOnAppendListWithFlags(StrictOrderingOnAppendList):
+        def __init__(self, iterable=[]):
+            StrictOrderingOnAppendList.__init__(self, iterable)
+            self._flags_type = Flags
+            self._flags = dict()
+
+        def __getitem__(self, name):
+            if name not in self._flags:
+                if name not in self:
+                    raise KeyError("'%s'" % name)
+                self._flags[name] = self._flags_type()
+            return self._flags[name]
+
+        def __setitem__(self, name, value):
+            raise TypeError("'%s' object does not support item assignment" %
+                            self.__class__.__name__)
+
+    return StrictOrderingOnAppendListWithFlags
+
+
 class HierarchicalStringList(object):
     """A hierarchy of lists of strings.
 
     Each instance of this object contains a list of strings, which can be set or
     appended to. A sub-level of the hierarchy is also an instance of this class,
     can be added by appending to an attribute instead.
 
     For example, the moz.build variable EXPORTS is an instance of this class. We