Bug 1586358 - Replace existing instances of GENERATED_FILES with references to the GeneratedFile template r=nalexander
☠☠ backed out by b121d61e533a ☠ ☠
authorRicky Stewart <rstewart@mozilla.com>
Mon, 07 Oct 2019 15:31:05 +0000
changeset 496539 8d95f2c8867b13432cf2e0c51c7765e6592441ea
parent 496538 b739370f346d53aafce4709bb5ce8dc040edca2f
child 496540 54fa3474aca1c0674eba17bfeaa4f14536b9b20e
push id36661
push userccoroiu@mozilla.com
push dateMon, 07 Oct 2019 21:50:01 +0000
treeherdermozilla-central@2b4c8b7a255c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1586358
milestone71.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 1586358 - Replace existing instances of GENERATED_FILES with references to the GeneratedFile template r=nalexander This patch doesn't remove all references to GENERATED_FILES, but does remove most of them, leaving only those which can't be trivially translated to the new template. Try push: https://treeherder.mozilla.org/#/jobs?repo=try&revision=e4a25230c3992b9c5519ceb351fb37f6b2bf605e Differential Revision: https://phabricator.services.mozilla.com/D48230
accessible/ipc/win/typelib/moz.build
accessible/xpcom/moz.build
browser/app/winlauncher/freestanding/moz.build
build/clang-plugin/moz.build
build/moz.build
build/test_templates.mozbuild
build/unix/elfhack/inject/moz.build
config/external/ffi/moz.build
config/external/icu/data/moz.build
config/moz.build
devtools/shared/webconsole/moz.build
dom/base/moz.build
dom/bindings/moz.build
dom/encoding/moz.build
gfx/layers/moz.build
gfx/webrender_bindings/moz.build
intl/locale/moz.build
js/src/frontend/moz.build
js/src/gc/moz.build
js/src/moz.build
js/src/shell/moz.build
layout/generic/moz.build
layout/style/moz.build
mobile/android/base/moz.build
netwerk/dns/moz.build
security/apps/moz.build
security/manager/ssl/moz.build
toolkit/components/featuregates/moz.build
toolkit/components/telemetry/moz.build
toolkit/crashreporter/moz.build
toolkit/library/build/moz.build
toolkit/library/moz.build
toolkit/locales/moz.build
widget/android/moz.build
xpcom/base/moz.build
xpcom/build/moz.build
xpcom/components/moz.build
xpcom/ds/moz.build
xpcom/idl-parser/xpidl/moz.build
xpcom/reflect/xptcall/md/win32/moz.build
--- a/accessible/ipc/win/typelib/moz.build
+++ b/accessible/ipc/win/typelib/moz.build
@@ -3,11 +3,9 @@
 # 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/.
 
 FINAL_TARGET_FILES += [
     '!Accessible.tlb',
 ]
 
-GENERATED_FILES += [
-    'Accessible.tlb',
-]
+GeneratedFile('Accessible.tlb')
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -51,20 +51,24 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'an
     LOCAL_INCLUDES += [
         '/accessible/android',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
-GENERATED_FILES += [('xpcAccEvents.h', 'xpcAccEvents.cpp')]
 
-xpc_acc = GENERATED_FILES[('xpcAccEvents.h', 'xpcAccEvents.cpp')]
-xpc_acc.script = 'AccEventGen.py:gen_files'
-xpc_acc.inputs += ['AccEvents.conf', '!/xpcom/idl-parser/xpidl/xpidllex.py', '!/xpcom/idl-parser/xpidl/xpidlyacc.py']
+GeneratedFile(
+    'xpcAccEvents.h', 'xpcAccEvents.cpp',
+    script='AccEventGen.py', entry_point='gen_files',
+    inputs=[
+        'AccEvents.conf',
+        '!/xpcom/idl-parser/xpidl/xpidllex.py',
+        '!/xpcom/idl-parser/xpidl/xpidlyacc.py',
+    ])
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/browser/app/winlauncher/freestanding/moz.build
+++ b/browser/app/winlauncher/freestanding/moz.build
@@ -37,25 +37,19 @@ else:
 CXXFLAGS += [ SRCDIR + '/Freestanding.h' ]
 
 OS_LIBS += [
     'ntdll',
     'ntdll_freestanding',
 ]
 
 if CONFIG['COMPILE_ENVIRONMENT']:
-    ntdll_freestanding_lib = '%sntdll_freestanding.%s' % (CONFIG['LIB_PREFIX'],
-                                                          CONFIG['LIB_SUFFIX'])
-
-    GENERATED_FILES += [
-        ntdll_freestanding_lib,
-    ]
-
-    ntdll_freestanding_gen = GENERATED_FILES[ntdll_freestanding_lib]
-    ntdll_freestanding_gen.script = 'gen_ntdll_freestanding_lib.py'
-    ntdll_freestanding_gen.inputs = ['ntdll_freestanding.def']
-    ntdll_freestanding_gen.flags = [CONFIG['LLVM_DLLTOOL']] + \
-                                   CONFIG['LLVM_DLLTOOL_FLAGS']
+    GeneratedFile(
+        '%sntdll_freestanding.%s' % (CONFIG['LIB_PREFIX'],
+                                     CONFIG['LIB_SUFFIX']),
+        script='gen_ntdll_freestanding_lib.py',
+        inputs=['ntdll_freestanding.def'],
+        flags=[CONFIG['LLVM_DLLTOOL']] + CONFIG['LLVM_DLLTOOL_FLAGS'])
 
 DisableStlWrapping()
 
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'Launcher Process')
--- a/build/clang-plugin/moz.build
+++ b/build/clang-plugin/moz.build
@@ -52,23 +52,21 @@ if CONFIG['OS_ARCH'] == 'WINNT':
 if CONFIG['ENABLE_MOZSEARCH_PLUGIN']:
     HOST_SOURCES += [
         'mozsearch-plugin/FileOperations.cpp',
         'mozsearch-plugin/JSONFormatter.cpp',
         'mozsearch-plugin/MozsearchIndexer.cpp',
         'mozsearch-plugin/StringOperations.cpp',
     ]
 
-GENERATED_FILES += ['ThirdPartyPaths.cpp']
-third_party_paths = GENERATED_FILES['ThirdPartyPaths.cpp']
-third_party_paths.script = "ThirdPartyPaths.py:generate"
-third_party_paths.inputs = [
-    '/tools/rewriting/ThirdPartyPaths.txt',
-    '/tools/rewriting/Generated.txt',
-]
+GeneratedFile('ThirdPartyPaths.cpp', script="ThirdPartyPaths.py",
+              entry_point="generate", inputs=[
+                  '/tools/rewriting/ThirdPartyPaths.txt',
+                  '/tools/rewriting/Generated.txt',
+              ])
 
 HOST_COMPILE_FLAGS['STL'] = []
 HOST_COMPILE_FLAGS['VISIBILITY'] = []
 
 # libc++ is required to build plugins against clang on OS X.
 if CONFIG['HOST_OS_ARCH'] == 'Darwin':
     HOST_CXXFLAGS += ['-stdlib=libc++']
 
--- a/build/moz.build
+++ b/build/moz.build
@@ -73,37 +73,34 @@ if CONFIG['MOZ_APP_BASENAME']:
 
     if CONFIG['MOZ_APP_PROFILE']:
         appini_defines['MOZ_APP_PROFILE'] = CONFIG['MOZ_APP_PROFILE']
 
     for var in ('MOZ_CRASHREPORTER', 'MOZ_PROFILE_MIGRATOR'):
         if CONFIG[var]:
             appini_defines[var] = True
 
-    GENERATED_FILES += ['application.ini']
-
-    appini = GENERATED_FILES['application.ini']
-    appini.script = '../python/mozbuild/mozbuild/action/preprocessor.py:generate'
-    appini.inputs = ['application.ini.in']
-    appini.flags = ['-D%s=%s' % (k, '1' if v is True else v)
-                    for k, v in appini_defines.iteritems()]
+    GeneratedFile(
+        'application.ini',
+        script='../python/mozbuild/mozbuild/action/preprocessor.py',
+        entry_point='generate',
+        inputs=['application.ini.in'],
+        flags=['-D%s=%s' % (k, '1' if v is True else v)
+               for k, v in appini_defines.iteritems()])
+    
     FINAL_TARGET_FILES += ['!application.ini']
     if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android' and CONFIG['MOZ_UPDATER']:
         FINAL_TARGET_PP_FILES += ['update-settings.ini']
 
-    GENERATED_FILES += ['application.ini.h']
-    appini = GENERATED_FILES['application.ini.h']
-    appini.script = 'appini_header.py'
-    appini.inputs = ['!application.ini']
+    GeneratedFile('application.ini.h', script='appini_header.py',
+                  inputs=['!application.ini'])
 
 if CONFIG['ENABLE_TESTS']:
-    GENERATED_FILES += ['automation.py']
-    auto = GENERATED_FILES['automation.py']
-    auto.script = 'gen_automation.py'
-    auto.inputs = ['automation.py.in']
+    GeneratedFile('automation.py', script='gen_automation.py',
+                  inputs=['automation.py.in'])
 
     TEST_HARNESS_FILES.reftest += [
         '!automation.py',
     ]
 
     TEST_HARNESS_FILES.testing.mochitest += [
         '!automation.py',
     ]
--- a/build/test_templates.mozbuild
+++ b/build/test_templates.mozbuild
@@ -3,37 +3,31 @@
 # 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/.
 
 @template
 def GeneratedTestCertificate(name):
     if not CONFIG['COMPILE_ENVIRONMENT']:
         return
-
-    GENERATED_FILES += [name]
-    props = GENERATED_FILES[name]
-    props.script = '/security/manager/ssl/tests/unit/pycert.py'
-    props.inputs = ['%s.certspec' % name]
+    GeneratedFile(name, script='/security/manager/ssl/tests/unit/pycert.py',
+                  inputs=['%s.certspec' % name])
     # Turn RELATIVEDIR into list entry: like
     # 'security/manager/ssl/tests/unit/bad_certs' ->
     # TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.bad_certs.
     files = TEST_HARNESS_FILES.xpcshell
     for part in RELATIVEDIR.split('/'):
         files = files[part]
     files += ['!%s' % name]
 
 @template
 def GeneratedTestKey(name):
     if not CONFIG['COMPILE_ENVIRONMENT']:
         return
-
-    GENERATED_FILES += [name]
-    props = GENERATED_FILES[name]
-    props.script = '/security/manager/ssl/tests/unit/pykey.py'
-    props.inputs = ['%s.keyspec' % name]
+    GeneratedFile(name, script='/security/manager/ssl/tests/unit/pykey.py',
+                  inputs=['%s.keyspec' % name])
     # Turn RELATIVEDIR into list entry: like
     # 'security/manager/ssl/tests/unit/bad_certs' ->
     # TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.bad_certs.
     files = TEST_HARNESS_FILES.xpcshell
     for part in RELATIVEDIR.split('/'):
         files = files[part]
     files += ['!%s' % name]
--- a/build/unix/elfhack/inject/moz.build
+++ b/build/unix/elfhack/inject/moz.build
@@ -8,22 +8,18 @@
 # we only need the object for.
 Library('elfhack_inject')
 
 DIST_INSTALL = False
 
 cpu = CONFIG['CPU_ARCH']
 
 gen_src = '%s.c' % cpu
-GENERATED_FILES += [
-    gen_src,
-]
-
-GENERATED_FILES[gen_src].script = 'copy_source.py:copy'
-GENERATED_FILES[gen_src].inputs = ['../inject.c']
+GeneratedFile(gen_src, script='copy_source.py', entry_point='copy',
+              inputs = ['../inject.c'])
 
 SOURCES += [
     '!%s' % gen_src,
 ]
 
 NO_PGO = True
 
 for v in ('OS_CPPFLAGS', 'OS_CFLAGS', 'DEBUG', 'CLANG_PLUGIN', 'OPTIMIZE',
--- a/config/external/ffi/moz.build
+++ b/config/external/ffi/moz.build
@@ -10,22 +10,19 @@ if CONFIG['MOZ_SYSTEM_FFI']:
     OS_LIBS += CONFIG['MOZ_FFI_LIBS']
 else:
     AllowCompilerWarnings()
     NoVisibilityFlags()
 
     CONFIGURE_DEFINE_FILES += [
         '../../../js/src/ctypes/libffi/fficonfig.h',
     ]
-    GENERATED_FILES += [
-        '../../../js/src/ctypes/libffi/include/ffi.h',
-    ]
-    ffi_h = GENERATED_FILES['../../../js/src/ctypes/libffi/include/ffi.h']
-    ffi_h.script = 'subst_header.py'
-    ffi_h.inputs = ['../../../js/src/ctypes/libffi/include/ffi.h.in']
+    GeneratedFile('../../../js/src/ctypes/libffi/include/ffi.h',
+                  script='subst_header.py',
+                  inputs=['../../../js/src/ctypes/libffi/include/ffi.h.in'])
 
     LOCAL_INCLUDES += [
         '!/js/src/ctypes/libffi',
         '!/js/src/ctypes/libffi/include',
         '/js/src/ctypes/libffi/include',
         '/js/src/ctypes/libffi/src/%s' % CONFIG['FFI_TARGET_DIR'],
     ]
 
@@ -75,64 +72,60 @@ else:
         ffi_srcs = ('sysv.S', 'ffi.c')
         if CONFIG['CC_TYPE'] == 'clang':
             ASFLAGS += ['-no-integrated-as']
     elif CONFIG['FFI_TARGET'] == 'AARCH64':
         ffi_srcs = ('sysv.S', 'ffi.c')
     elif CONFIG['FFI_TARGET'] == 'ARM64_WIN64':
         ffi_srcs = ['ffi.c']
 
-        GENERATED_FILES += ['win64_aarch.asm']
-        asm = GENERATED_FILES['win64_aarch.asm']
-        asm.inputs = [
-            '/js/src/ctypes/libffi/src/aarch64/win64.asm',
-            '!../../../js/src/ctypes/libffi/fficonfig.h',
-            '!../../../js/src/ctypes/libffi/include/ffi.h',
-        ]
-        asm.script = 'preprocess_libffi_asm.py'
-        asm.flags = ['$(DEFINES)', '$(LOCAL_INCLUDES)']
+        GeneratedFile(
+            'win64_aarch.asm',
+            inputs=[
+                '/js/src/ctypes/libffi/src/aarch64/win64.asm',
+                '!../../../js/src/ctypes/libffi/fficonfig.h',
+                '!../../../js/src/ctypes/libffi/include/ffi.h',
+            ],
+            script='preprocess_libffi_asm.py',
+            flags=['$(DEFINES)', '$(LOCAL_INCLUDES)'])
         SOURCES += ['!win64_aarch.asm']
     elif CONFIG['FFI_TARGET'] == 'X86':
         ffi_srcs = ('ffi.c', 'sysv.S', 'win32.S')
     elif CONFIG['FFI_TARGET'] == 'X86_64':
         ffi_srcs = ('ffi64.c', 'unix64.S', 'ffi.c', 'sysv.S')
     elif CONFIG['FFI_TARGET'] == 'X86_WIN32':
         ffi_srcs = ['ffi.c']
         # MinGW Build for 32 bit
         if CONFIG['CC_TYPE'] in ('gcc', 'clang'):
             DEFINES['SYMBOL_UNDERSCORE'] = True
             ffi_srcs += ['win32.S']
         else:
             # libffi asm needs to be preprocessed for MSVC
-            GENERATED_FILES += ['win32.asm']
-            asm = GENERATED_FILES['win32.asm']
-            asm.inputs = [
+            GeneratedFile('win32.asm', inputs=[
                 '/js/src/ctypes/libffi/src/x86/win32.S',
                 '!../../../js/src/ctypes/libffi/fficonfig.h',
                 '!../../../js/src/ctypes/libffi/include/ffi.h',
-            ]
-            asm.script = 'preprocess_libffi_asm.py'
-            asm.flags = ['$(DEFINES)', '$(LOCAL_INCLUDES)']
+            ], script='preprocess_libffi_asm.py',
+            flags=['$(DEFINES)', '$(LOCAL_INCLUDES)'])
             SOURCES += ['!win32.asm']
             ASFLAGS += ['-safeseh']
     elif CONFIG['FFI_TARGET'] == 'X86_WIN64':
         ffi_srcs = ['ffi.c']
         if CONFIG['CC_TYPE'] in ('gcc', 'clang'):
             ffi_srcs += ['win64.S']
         else:
             # libffi asm needs to be preprocessed for MSVC
-            GENERATED_FILES += ['win64.asm']
-            asm = GENERATED_FILES['win64.asm']
-            asm.inputs = [
-                '/js/src/ctypes/libffi/src/x86/win64.S',
-                '!../../../js/src/ctypes/libffi/fficonfig.h',
-                '!../../../js/src/ctypes/libffi/include/ffi.h',
-            ]
-            asm.script = 'preprocess_libffi_asm.py'
-            asm.flags = ['$(DEFINES)', '$(LOCAL_INCLUDES)']
+            GeneratedFile(
+                'win64.asm',
+                inputs=[
+                    '/js/src/ctypes/libffi/src/x86/win64.S',
+                    '!../../../js/src/ctypes/libffi/fficonfig.h',
+                    '!../../../js/src/ctypes/libffi/include/ffi.h',
+                ], script='preprocess_libffi_asm.py',
+                flags=['$(DEFINES)', '$(LOCAL_INCLUDES)'])
             SOURCES += ['!win64.asm']
     elif CONFIG['FFI_TARGET'] == 'X86_DARWIN':
         DEFINES['FFI_MMAP_EXEC_WRIT'] = True
         if CONFIG['CPU_ARCH'] == 'x86':
             ffi_srcs = ('ffi.c', 'darwin.S', 'ffi64.c', 'darwin64.S',
                         'win32.S')
             DEFINES['SYMBOL_UNDERSCORE'] = True
         else:
--- a/config/external/icu/data/moz.build
+++ b/config/external/icu/data/moz.build
@@ -18,22 +18,18 @@ data_symbol = 'icudt%s_dat' % CONFIG['MO
 asflags = [
     '-I%s/config/external/icu/data/' % TOPSRCDIR,
     '-DICU_DATA_FILE="%s"' % CONFIG['ICU_DATA_FILE'],
     '-DICU_DATA_SYMBOL=%s' % data_symbol,
 ]
 LOCAL_INCLUDES += ['.']
 
 if CONFIG['OS_TARGET'] == 'WINNT' and CONFIG['CPU_ARCH'] == 'aarch64':
-    icudata = 'icudata.asm'
-    GENERATED_FILES += [icudata]
+    GeneratedFile('icudata.asm', script='genicudata.py',
+                  inputs=[CONFIG['ICU_DATA_FILE']], flags=[data_symbol])
     SOURCES += ['!%s' % icudata]
-    icudata = GENERATED_FILES[icudata]
-    icudata.script = 'genicudata.py'
-    icudata.inputs = [CONFIG['ICU_DATA_FILE']]
-    icudata.flags = [data_symbol]
 elif CONFIG['HAVE_YASM']:
     USE_YASM = True
     SOURCES += ['icudata.s']
     ASFLAGS += asflags
 elif CONFIG['GNU_AS']:
     SOURCES += ['icudata_gas.S']
     ASFLAGS += asflags
--- a/config/moz.build
+++ b/config/moz.build
@@ -63,23 +63,23 @@ if CONFIG['WRAP_STL_INCLUDES']:
         stl.flags = [output_dir, stl_compiler, template_file]
         stl.flags.extend(stl_headers)
 
     # Wrap <windows.h> to make it easier to use correctly
     # NOTE: If we aren't wrapping STL includes, we're building part of the browser
     # which won't need this wrapper, such as L10N. Just don't try to generate the
     # wrapper in that case.
     if CONFIG['OS_ARCH'] == 'WINNT':
-        GENERATED_FILES += ['../dist/stl_wrappers/windows.h']
-        windows_h = GENERATED_FILES['../dist/stl_wrappers/windows.h']
-        windows_h.script = 'make-windows-h-wrapper.py:generate'
-        windows_h.inputs = ['windows-h-constant.decls.h',
-                            'windows-h-unicode.decls.h',
-                            'windows-h-wrapper.template.h']
-        windows_h.flags = [stl_compiler]
+        GeneratedFile('../dist/stl_wrappers/windows.h',
+                      script='make-windows-h-wrapper.py',
+                      entry_point='generate',
+                      inputs = ['windows-h-constant.decls.h',
+                                'windows-h-unicode.decls.h',
+                                'windows-h-wrapper.template.h'],
+                      flags=[stl_compiler])
 
 if CONFIG['WRAP_SYSTEM_INCLUDES']:
     include('system-headers.mozbuild')
     output_dir = '../dist/system_wrappers'
     outputs = tuple(['system-header.sentinel'] + ['%s/%s' % (output_dir, h) for h in stl_headers + system_headers])
     GENERATED_FILES += [outputs]
     system = GENERATED_FILES[outputs]
     system.script = 'make-system-wrappers.py:gen_wrappers'
--- a/devtools/shared/webconsole/moz.build
+++ b/devtools/shared/webconsole/moz.build
@@ -14,19 +14,17 @@ if CONFIG['OS_TARGET'] != 'Android':
 # See devtools/shared/jar.mn for how this resource is mapped into jar package.
 base = FINAL_TARGET_FILES.chrome.devtools.modules
 
 # Now, navigate to the right sub-directory into devtools root modules folder
 for dir in RELATIVEDIR.split('/'):
     base = base[dir]
 base += ["!reserved-js-words.js"]
 
-GENERATED_FILES += ['reserved-js-words.js']
-ReservedWordsGenerated = GENERATED_FILES['reserved-js-words.js']
-ReservedWordsGenerated.script = 'GenerateReservedWordsJS.py'
-ReservedWordsGenerated.inputs = ['/js/src/frontend/ReservedWords.h']
+GeneratedFile('reserved-js-words.js', script='GenerateReservedWordsJS.py',
+              inputs = ['/js/src/frontend/ReservedWords.h'])
 
 DevToolsModules(
     'js-property-provider.js',
     'network-helper.js',
     'parser-helper.js',
     'throttle.js',
 )
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -536,18 +536,13 @@ include('/ipc/chromium/chromium-config.m
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
     DEFINES['HAVE_SIDEBAR'] = True
 
 if CONFIG['MOZ_X11']:
     CXXFLAGS += CONFIG['TK_CFLAGS']
 
-GENERATED_FILES += [
-    'UseCounterList.h',
-]
-
-counterlist = GENERATED_FILES['UseCounterList.h']
-counterlist.script = 'gen-usecounters.py:use_counter_list'
-counterlist.inputs = ['UseCounters.conf']
+GeneratedFile('UseCounterList.h', script='gen-usecounters.py',
+              entry_point='use_counter_list', inputs=['UseCounters.conf'])
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -170,15 +170,15 @@ PYTHON_UNITTEST_MANIFESTS += [
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
     # Suppress warnings in third-party code.
     CXXFLAGS += [
         '-Wno-maybe-uninitialized',
     ]
 
 if CONFIG['COMPILE_ENVIRONMENT']:
-    GENERATED_FILES += ['CSS2Properties.webidl']
-    css_props = GENERATED_FILES['CSS2Properties.webidl']
-    css_props.script = 'GenerateCSS2PropertiesWebIDL.py:generate'
-    css_props.inputs = [
-        '/dom/webidl/CSS2Properties.webidl.in',
-        '!/layout/style/ServoCSSPropList.py',
-    ]
+    GeneratedFile('CSS2Properties.webidl',
+                  script='GenerateCSS2PropertiesWebIDL.py',
+                  entry_point='generate',
+                  inputs=[
+                      '/dom/webidl/CSS2Properties.webidl.in',
+                      '!/layout/style/ServoCSSPropList.py',
+                  ])
--- a/dom/encoding/moz.build
+++ b/dom/encoding/moz.build
@@ -29,25 +29,20 @@ prefixes = (
     'domainsfallbacks',
     'labelsencodings',
     'localesfallbacks',
 )
 
 for prefix in prefixes:
     input_file = prefix + '.properties'
     header = prefix + '.properties.h'
-    GENERATED_FILES += [header]
-    props = GENERATED_FILES[header]
-    props.script = props2arrays
-    props.inputs = [input_file]
+    GeneratedFile(header, script=props2arrays, inputs=[input_file])
 
 input_file = 'nonparticipatingdomains.properties'
 header = input_file + '.h'
-GENERATED_FILES += [header]
-props = GENERATED_FILES[header]
-props.script = '../../intl/locale/props2arrays.py'
-props.inputs = [input_file]
+GeneratedFile(header, script='../../intl/locale/props2arrays.py',
+              inputs=[input_file])
 
 MOCHITEST_MANIFESTS += [
     'test/mochitest.ini',
 ]
 MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -575,27 +575,20 @@ IPDL_SOURCES += [
     'ipc/PVideoBridge.ipdl',
     'ipc/PWebRenderBridge.ipdl',
     'ipc/WebRenderMessages.ipdlh',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-  GENERATED_FILES = [
-      'CompositorD3D11Shaders.h',
-      'MLGShaders.h',
-  ]
-
-  d3d11_shaders = GENERATED_FILES['CompositorD3D11Shaders.h']
-  d3d11_shaders.script = 'd3d11/genshaders.py'
-  d3d11_shaders.inputs = ['d3d11/shaders.manifest']
-  mlg_shaders = GENERATED_FILES['MLGShaders.h']
-  mlg_shaders.script = 'd3d11/genshaders.py'
-  mlg_shaders.inputs = ['d3d11/mlgshaders/shaders.manifest']
+  GeneratedFile('CompositorD3D11Shaders.h', script='d3d11/genshaders.py',
+                inputs=['d3d11/shaders.manifest'])
+  GeneratedFile('MLGShaders.h', script='d3d11/genshaders.py',
+                inputs=['d3d11/mlgshaders/shaders.manifest'])
 
 LOCAL_INCLUDES += [
     '/docshell/base',  # for nsDocShell.h
     '/layout/base',    # for TouchManager.h
     '/layout/generic', # for nsTextFrame.h
     '/media/libyuv/libyuv/include', # for libyuv.h
 ]
 
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -80,30 +80,26 @@ if CONFIG['MOZ_WAYLAND']:
         'RenderCompositorEGL.cpp',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk'):
     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
 
 if CONFIG['COMPILE_ENVIRONMENT']:
-    GENERATED_FILES += [
-        'webrender_ffi_generated.h',
-    ]
-
     EXPORTS.mozilla.webrender += [
         '!webrender_ffi_generated.h',
     ]
 
-    ffi_generated = GENERATED_FILES['webrender_ffi_generated.h']
-    ffi_generated.script = '/layout/style/RunCbindgen.py:generate'
-    ffi_generated.inputs = [
-        '/gfx/webrender_bindings',
-        '/gfx/wr/webrender',
-        '/gfx/wr/webrender_api',
-    ]
+    GeneratedFile('webrender_ffi_generated.h',
+                  script='/layout/style/RunCbindgen.py', entry_point='generate',
+                  inputs=[
+                      '/gfx/webrender_bindings',
+                      '/gfx/wr/webrender',
+                      '/gfx/wr/webrender_api',
+                  ])
 
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 CXXFLAGS += CONFIG['TK_CFLAGS']
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -71,15 +71,12 @@ RESOURCE_FILES += [
 
 prefixes = (
     'encodingsgroups',
 )
 
 for prefix in prefixes:
     input_file = prefix + '.properties'
     header = prefix + '.properties.h'
-    GENERATED_FILES += [header]
-    props = GENERATED_FILES[header]
-    props.script = 'props2arrays.py'
-    props.inputs = [input_file]
+    GeneratedFile(header, script='props2arrays.py', inputs=[input_file])
 
 if CONFIG['ENABLE_TESTS']:
     DIRS += ['tests/gtest']
--- a/js/src/frontend/moz.build
+++ b/js/src/frontend/moz.build
@@ -12,20 +12,18 @@ LOCAL_INCLUDES += [
     '..'
 ]
 
 include('../js-config.mozbuild')
 include('../js-cxxflags.mozbuild')
 
 
 # Generate frontend/ReservedWordsGenerated.h from frontend/ReservedWords.h
-GENERATED_FILES += ['ReservedWordsGenerated.h']
-ReservedWordsGenerated = GENERATED_FILES['ReservedWordsGenerated.h']
-ReservedWordsGenerated.script = 'GenerateReservedWords.py'
-ReservedWordsGenerated.inputs += ['ReservedWords.h']
+GeneratedFile('ReservedWordsGenerated.h', script='GenerateReservedWords.py',
+              inputs=['ReservedWords.h'])
 
 
 UNIFIED_SOURCES += [
     'BytecodeCompiler.cpp',
     'BytecodeControlStructures.cpp',
     'BytecodeEmitter.cpp',
     'BytecodeSection.cpp',
     'CallOrNewEmitter.cpp',
--- a/js/src/gc/moz.build
+++ b/js/src/gc/moz.build
@@ -12,21 +12,20 @@ LOCAL_INCLUDES += [
     '..'
 ]
 
 include('../js-config.mozbuild')
 include('../js-cxxflags.mozbuild')
 
 
 # Generate GC statistics phase data.
-GENERATED_FILES += ['StatsPhasesGenerated.h', 'StatsPhasesGenerated.inc']
-StatsPhasesGeneratedHeader = GENERATED_FILES['StatsPhasesGenerated.h']
-StatsPhasesGeneratedHeader.script = 'GenerateStatsPhases.py:generateHeader'
-StatsPhasesGeneratedCpp = GENERATED_FILES['StatsPhasesGenerated.inc']
-StatsPhasesGeneratedCpp.script = 'GenerateStatsPhases.py:generateCpp'
+GeneratedFile('StatsPhasesGenerated.h',
+              script='GenerateStatsPhases.py', entry_point='generateHeader')
+GeneratedFile('StatsPhasesGenerated.inc',
+              script='GenerateStatsPhases.py', entry_point='generateCpp')
 
 UNIFIED_SOURCES += [
     'Allocator.cpp',
     'AtomMarking.cpp',
     'Barrier.cpp',
     'GC.cpp',
     'GCTrace.cpp',
     'Marking.cpp',
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -100,18 +100,17 @@ if not CONFIG['JS_STANDALONE']:
         '../../config/emptyvars-js.mk',
     ]
 
 CONFIGURE_DEFINE_FILES += [
     'js-config.h',
 ]
 
 if CONFIG['HAVE_DTRACE']:
-    GENERATED_FILES += ['javascript-trace.h']
-
+    GeneratedFile('javascript-trace.h')
     EXPORTS += ['!javascript-trace.h']
 
 # Changes to internal header files, used externally, massively slow down
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
 EXPORTS += [
     '!js-config.h',
     'js.msg',
@@ -437,21 +436,17 @@ DIRS += [
     'gc',
     'jit',
     'wasm',
     'zydis',
 ]
 
 FINAL_LIBRARY = 'js'
 
-# Prepare self-hosted JS code for embedding
-GENERATED_FILES += [('selfhosted.out.h', 'selfhosted.js')]
-selfhosted = GENERATED_FILES[('selfhosted.out.h', 'selfhosted.js')]
-selfhosted.script = 'builtin/embedjs.py:generate_selfhosted'
-selfhosted.inputs = [
+selfhosted_inputs = [
     'js.msg',
     'builtin/TypedObjectConstants.h',
     'builtin/SelfHostingDefines.h',
     'builtin/Utilities.js',
     'builtin/Array.js',
     'builtin/AsyncFunction.js',
     'builtin/AsyncIteration.js',
     'builtin/BigInt.js',
@@ -472,32 +467,35 @@ selfhosted.inputs = [
     'builtin/RegExpLocalReplaceOpt.h.js',
     'builtin/String.js',
     'builtin/Set.js',
     'builtin/Sorting.js',
     'builtin/TypedArray.js',
     'builtin/TypedObject.js',
     'builtin/WeakMap.js',
     'builtin/WeakSet.js'
-]
+] + ([
+    'builtin/intl/Collator.js',
+    'builtin/intl/CommonFunctions.js',
+    'builtin/intl/CurrencyDataGenerated.js',
+    'builtin/intl/DateTimeFormat.js',
+    'builtin/intl/IntlObject.js',
+    'builtin/intl/LangTagMappingsGenerated.js',
+    'builtin/intl/Locale.js',
+    'builtin/intl/NumberFormat.js',
+    'builtin/intl/PluralRules.js',
+    'builtin/intl/RelativeTimeFormat.js',
+    'builtin/intl/UnicodeExtensionsGenerated.js',
+] if CONFIG['ENABLE_INTL_API'] else [])
 
-if CONFIG['ENABLE_INTL_API']:
-    selfhosted.inputs += [
-        'builtin/intl/Collator.js',
-        'builtin/intl/CommonFunctions.js',
-        'builtin/intl/CurrencyDataGenerated.js',
-        'builtin/intl/DateTimeFormat.js',
-        'builtin/intl/IntlObject.js',
-        'builtin/intl/LangTagMappingsGenerated.js',
-        'builtin/intl/Locale.js',
-        'builtin/intl/NumberFormat.js',
-        'builtin/intl/PluralRules.js',
-        'builtin/intl/RelativeTimeFormat.js',
-        'builtin/intl/UnicodeExtensionsGenerated.js',
-    ]
+# Prepare self-hosted JS code for embedding
+GeneratedFile('selfhosted.out.h', 'selfhosted.js',
+              script='builtin/embedjs.py',
+              entry_point='generate_selfhosted',
+              inputs=selfhosted_inputs)
 
 if CONFIG['JS_HAS_CTYPES']:
     if CONFIG['MOZ_SYSTEM_FFI']:
         CXXFLAGS += CONFIG['MOZ_FFI_CFLAGS']
 
 # Suppress warnings in third-party code.
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     SOURCES['util/DoubleToString.cpp'].flags += ['-Wno-implicit-fallthrough']
--- a/js/src/shell/moz.build
+++ b/js/src/shell/moz.build
@@ -33,24 +33,24 @@ DEFINES['EXPORT_JS_API'] = True
 LOCAL_INCLUDES += [
     '!..',
     '..',
 ]
 
 OS_LIBS += CONFIG['EDITLINE_LIBS']
 
 # Prepare module loader JS code for embedding
-GENERATED_FILES += [('shellmoduleloader.out.h', 'shellmoduleloader.js')]
-shellmoduleloader = GENERATED_FILES[('shellmoduleloader.out.h', 'shellmoduleloader.js')]
-shellmoduleloader.script = '../builtin/embedjs.py:generate_shellmoduleloader'
-shellmoduleloader.inputs = [
-    '../js.msg',
-    'ModuleLoader.js',
-]
-
+GeneratedFile('shellmoduleloader.out.h', 'shellmoduleloader.js', 
+              script='../builtin/embedjs.py',
+              entry_point='generate_shellmoduleloader',
+              inputs=[
+                  '../js.msg',
+                  'ModuleLoader.js',
+              ])
+              
 # Place a GDB Python auto-load file next to the shell executable, both in
 # the build directory and in the dist/bin directory.
 DEFINES['topsrcdir'] = '%s/js/src' % TOPSRCDIR
 FINAL_TARGET_PP_FILES += ['js-gdb.py.in']
 OBJDIR_FILES.js.src.shell += ['!/dist/bin/js-gdb.py']
 
 # People expect the js shell to wind up in the top-level JS dir.
 OBJDIR_FILES.js.src += ['!/dist/bin/js%s' % CONFIG['BIN_SUFFIX']]
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -220,23 +220,22 @@ UNIFIED_SOURCES += [
     'ViewportFrame.cpp',
 ]
 
 # nsPluginFrame.cpp needs to be built separately because of name clashes in the OS X headers.
 SOURCES += [
     'nsPluginFrame.cpp',
 ]
 
-GENERATED_FILES += [
-    'FrameIdList.h',
-    'FrameTypeList.h',
-]
-
-GENERATED_FILES['FrameIdList.h'].script = 'GenerateFrameLists.py:generate_frame_id_list_h'
-GENERATED_FILES['FrameTypeList.h'].script = 'GenerateFrameLists.py:generate_frame_type_list_h'
+GeneratedFile('FrameIdList.h',
+              script='GenerateFrameLists.py',
+              entry_point='generate_frame_id_list_h')
+GeneratedFile('FrameTypeList.h',
+              script='GenerateFrameLists.py',
+              entry_point='generate_frame_type_list_h')
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../../dom/plugins/base',
     '../base',
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -254,82 +254,53 @@ RESOURCE_FILES += [
 CONTENT_ACCESSIBLE_FILES += [
     'ImageDocument.css',
     'res/plaintext.css',
     'res/viewsource.css',
     'TopLevelImageDocument.css',
     'TopLevelVideoDocument.css',
 ]
 
-GENERATED_FILES += [
-    'nsCSSPropertyID.h',
-    'ServoCSSPropList.h',
-    'ServoCSSPropList.py',
-]
 
-prop_id = GENERATED_FILES['nsCSSPropertyID.h']
-prop_id.script = 'GenerateCSSPropertyID.py:generate'
-prop_id.inputs = [
-    'nsCSSPropertyID.h.in',
-    '!ServoCSSPropList.py',
-]
-
-servo_props = GENERATED_FILES['ServoCSSPropList.h']
-servo_props.script = 'GenerateServoCSSPropList.py:generate_header'
-servo_props.inputs = [
-    '!ServoCSSPropList.py',
-]
-
-servo_props = GENERATED_FILES['ServoCSSPropList.py']
-servo_props.script = 'GenerateServoCSSPropList.py:generate_data'
-servo_props.inputs = [
-    'ServoCSSPropList.mako.py',
-]
+GeneratedFile('nsCSSPropertyID.h', script='GenerateCSSPropertyID.py',
+              entry_point='generate',
+              inputs=['nsCSSPropertyID.h.in', '!ServoCSSPropList.py'])
+GeneratedFile('ServoCSSPropList.h',
+              script='GenerateServoCSSPropList.py',
+              entry_point='generate_header',
+              inputs=['!ServoCSSPropList.py'])
+GeneratedFile('ServoCSSPropList.py',
+              script='GenerateServoCSSPropList.py', entry_point='generate_data',
+              inputs=['ServoCSSPropList.mako.py'])
 
 if CONFIG['COMPILE_ENVIRONMENT']:
-    GENERATED_FILES += [
-        'CompositorAnimatableProperties.h',
-        'CountedUnknownProperties.h',
-        'nsComputedDOMStyleGenerated.inc',
-        'nsCSSPropsGenerated.inc',
-        'ServoStyleConsts.h',
-    ]
-
     EXPORTS.mozilla += [
         '!CompositorAnimatableProperties.h',
         '!CountedUnknownProperties.h',
         '!ServoStyleConsts.h',
     ]
 
-    compositor = GENERATED_FILES['CompositorAnimatableProperties.h']
-    compositor.script = 'GenerateCompositorAnimatableProperties.py:generate'
-    compositor.inputs = [
-        '!ServoCSSPropList.py',
-    ]
-
-    counted_unknown = GENERATED_FILES['CountedUnknownProperties.h']
-    counted_unknown.script = 'GenerateCountedUnknownProperties.py:generate'
-    counted_unknown.inputs = [
-        '/servo/components/style/properties/counted_unknown_properties.py',
-    ]
-
-    computed = GENERATED_FILES['nsComputedDOMStyleGenerated.inc']
-    computed.script = 'GenerateComputedDOMStyleGenerated.py:generate'
-    computed.inputs = [
-        '!ServoCSSPropList.py',
-    ]
-
-    css_props = GENERATED_FILES['nsCSSPropsGenerated.inc']
-    css_props.script = 'GenerateCSSPropsGenerated.py:generate'
-    css_props.inputs = [
-        '!ServoCSSPropList.py',
-    ]
-
-    consts = GENERATED_FILES['ServoStyleConsts.h']
-    consts.script = 'RunCbindgen.py:generate'
-    consts.inputs = [
-        '/servo/ports/geckolib',
-        '/servo/components/style',
-    ]
+    GeneratedFile('CompositorAnimatableProperties.h',
+                  script='GenerateCompositorAnimatableProperties.py',
+                  entry_point='generate',
+                  inputs=['!ServoCSSPropList.py'])
+    GeneratedFile(
+        'CountedUnknownProperties.h',
+        script='GenerateCountedUnknownProperties.py',
+        entry_point='generate',
+        inputs=[
+            '/servo/components/style/properties/counted_unknown_properties.py',
+        ])
+    GeneratedFile('nsComputedDOMStyleGenerated.inc',
+                  script='GenerateComputedDOMStyleGenerated.py',
+                  entry_point='generate',
+                  inputs=['!ServoCSSPropList.py'])
+    GeneratedFile('nsCSSPropsGenerated.inc',
+                  script='GenerateCSSPropsGenerated.py',
+                  entry_point='generate',
+                  inputs=['!ServoCSSPropList.py'])
+    GeneratedFile('ServoStyleConsts.h', script='RunCbindgen.py',
+                  entry_point='generate',
+                  inputs = ['/servo/ports/geckolib', '/servo/components/style'])
 
     CONFIGURE_SUBST_FILES += [
         'bindgen.toml',
     ]
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -6,17 +6,16 @@
 
 with Files('**'):
     BUG_COMPONENT = ('Firefox for Android', 'Build Config & IDE Support')
 
 with Files('locales/**'):
     BUG_COMPONENT = ('Firefox for Android', 'General')
 
 DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']
-    
 # The recursive make backend treats the first output specially: it's passed as
 # an open FileAvoidWrite to the invoked script.  That doesn't work well with
 # the Gradle task that generates all of the outputs, so we add a dummy first
 # output.
 t = ('android_apks',)
 
 GENERATED_FILES += [t]
 GENERATED_FILES[t].force = True
--- a/netwerk/dns/moz.build
+++ b/netwerk/dns/moz.build
@@ -69,22 +69,18 @@ IPDL_SOURCES = [
     'PDNSRequest.ipdl',
     'PDNSRequestParams.ipdlh',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
-GENERATED_FILES = [
-    'etld_data.inc',
-]
-etld_data = GENERATED_FILES['etld_data.inc']
-etld_data.script = 'prepare_tlds.py'
-etld_data.inputs = ['effective_tld_names.dat']
+GeneratedFile('etld_data.inc', script='prepare_tlds.py',
+              inputs=['effective_tld_names.dat'])
 
 # need to include etld_data.inc
 LOCAL_INCLUDES += [
     '/netwerk/base',
 ]
 
 USE_LIBS += ['icu']
 
--- a/security/apps/moz.build
+++ b/security/apps/moz.build
@@ -41,12 +41,10 @@ test_ssl_path = '/security/manager/ssl/t
 headers_arrays_certs = [
     ('xpcshell.inc', 'xpcshellRoot', test_ssl_path + '/test_signed_apps/xpcshellTestRoot.der'),
     ('addons-public.inc', 'addonsPublicRoot', 'addons-public.crt'),
     ('addons-public-intermediate.inc', 'addonsPublicIntermediate', 'addons-public-intermediate.crt'),
     ('addons-stage.inc', 'addonsStageRoot', 'addons-stage.crt'),
 ]
 
 for header, array_name, cert in headers_arrays_certs:
-    GENERATED_FILES += [header]
-    h = GENERATED_FILES[header]
-    h.script = 'gen_cert_header.py:' + array_name
-    h.inputs = [cert]
+    GeneratedFile(header, script='gen_cert_header.py',
+                  entry_point=array_name, inputs=[cert])
--- a/security/manager/ssl/moz.build
+++ b/security/manager/ssl/moz.build
@@ -214,22 +214,19 @@ LOCAL_INCLUDES += [
     '/netwerk/base',
     '/security/certverifier',
 ]
 
 LOCAL_INCLUDES += [
     '!/dist/public/nss',
 ]
 
-GENERATED_FILES = [
-    'nsSTSPreloadList.h',
-]
-dafsa_data = GENERATED_FILES['nsSTSPreloadList.h']
-dafsa_data.script = '../../../xpcom/ds/tools/make_dafsa.py'
-dafsa_data.inputs = ['nsSTSPreloadList.inc']
+GeneratedFile('nsSTSPreloadList.h',
+              script='../../../xpcom/ds/tools/make_dafsa.py',
+              inputs=['nsSTSPreloadList.inc'])
 
 if CONFIG['NSS_DISABLE_DBM']:
     DEFINES['NSS_DISABLE_DBM'] = '1'
 
 DEFINES['SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES'] = 'True'
 DEFINES['NSS_ENABLE_ECC'] = 'True'
 
 if not CONFIG['MOZ_SYSTEM_NSS']:
--- a/toolkit/components/featuregates/moz.build
+++ b/toolkit/components/featuregates/moz.build
@@ -9,17 +9,10 @@ with Files('**'):
 
 SPHINX_TREES['featuregates'] = 'docs'
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 PYTHON_UNITTEST_MANIFESTS += ['test/python/python.ini']
 
 JAR_MANIFESTS += ['jar.mn']
 
-GENERATED_FILES = [
-    'feature_definitions.json',
-]
-
-feature_files = ['Features.toml']
-
-feature_defs = GENERATED_FILES['feature_definitions.json']
-feature_defs.script = 'gen_feature_definitions.py'
-feature_defs.inputs = feature_files
+GeneratedFile('feature_definitions.json', script='gen_feature_definitions.py',
+              inputs=['Features.toml'])
--- a/toolkit/components/telemetry/moz.build
+++ b/toolkit/components/telemetry/moz.build
@@ -133,113 +133,97 @@ EXTRA_JS_MODULES += [
 TESTING_JS_MODULES += [
   'tests/unit/TelemetryArchiveTesting.jsm',
 ]
 
 PYTHON_UNITTEST_MANIFESTS += [
     'tests/python/python.ini',
 ]
 
-GENERATED_FILES = [
-    'EventArtifactDefinitions.json',
-    'ScalarArtifactDefinitions.json',
-    'TelemetryEventData.h',
-    'TelemetryEventEnums.h',
-    'TelemetryHistogramData.inc',
-    'TelemetryHistogramEnums.h',
-    'TelemetryHistogramNameMap.h',
-    'TelemetryProcessData.h',
-    'TelemetryProcessEnums.h',
-    'TelemetryScalarData.h',
-    'TelemetryScalarEnums.h',
-]
-
 # Generate histogram files.
 histogram_files = [
     'Histograms.json',
     '/dom/base/UseCounters.conf',
     '/dom/base/nsDeprecatedOperationList.h',
     '!/layout/style/ServoCSSPropList.py',
     '/servo/components/style/properties/counted_unknown_properties.py',
 ]
 if CONFIG['MOZ_TELEMETRY_EXTRA_HISTOGRAM_FILES']:
     histogram_files.extend(CONFIG['MOZ_TELEMETRY_EXTRA_HISTOGRAM_FILES'])
 
-data = GENERATED_FILES['TelemetryHistogramData.inc']
-data.script = 'build_scripts/gen_histogram_data.py'
-data.inputs = histogram_files
-
-enums = GENERATED_FILES['TelemetryHistogramEnums.h']
-enums.script = 'build_scripts/gen_histogram_enum.py'
-enums.inputs = histogram_files
-
-data = GENERATED_FILES['TelemetryHistogramNameMap.h']
-data.script = 'build_scripts/gen_histogram_phf.py'
-data.inputs = histogram_files
+GeneratedFile('TelemetryHistogramData.inc',
+              script='build_scripts/gen_histogram_data.py',
+              inputs=histogram_files)
+GeneratedFile('TelemetryHistogramEnums.h',
+              script='build_scripts/gen_histogram_enum.py',
+              inputs=histogram_files)
+GeneratedFile('TelemetryHistogramNameMap.h',
+              script='build_scripts/gen_histogram_phf.py',
+              inputs=histogram_files)
 
 # Generate scalar files.
 scalar_files = [
     'Scalars.yaml',
 ]
 if CONFIG['MOZ_TELEMETRY_EXTRA_SCALAR_FILES']:
     scalar_files.extend(CONFIG['MOZ_TELEMETRY_EXTRA_SCALAR_FILES'])
 
-scalar_data = GENERATED_FILES['TelemetryScalarData.h']
-scalar_data.script = 'build_scripts/gen_scalar_data.py'
-scalar_data.inputs = scalar_files
-
-scalar_enums = GENERATED_FILES['TelemetryScalarEnums.h']
-scalar_enums.script = 'build_scripts/gen_scalar_enum.py'
-scalar_enums.inputs = scalar_files
+GeneratedFile('TelemetryScalarData.h',
+              script='build_scripts/gen_scalar_data.py',
+              inputs=scalar_files)
+GeneratedFile('TelemetryScalarEnums.h',
+              script='build_scripts/gen_scalar_enum.py',
+              inputs=scalar_files)
 
 # Generate the JSON scalar definitions. They will only be
 # used in artifact or "build faster" builds.
-scalar_json_data = GENERATED_FILES['ScalarArtifactDefinitions.json']
-scalar_json_data.script = 'build_scripts/gen_scalar_data.py:generate_JSON_definitions'
-scalar_json_data.inputs = scalar_files
+GeneratedFile(
+    'ScalarArtifactDefinitions.json',
+    script='build_scripts/gen_scalar_data.py',
+    entry_point='generate_JSON_definitions',
+    inputs=scalar_files)
 
 # Move the scalars JSON file to the directory where the Firefox binary is.
 FINAL_TARGET_FILES += ['!ScalarArtifactDefinitions.json']
 
 # Generate event files.
 event_files = [
     'Events.yaml',
 ]
 if CONFIG['MOZ_TELEMETRY_EXTRA_EVENT_FILES']:
     event_files.extend(CONFIG['MOZ_TELEMETRY_EXTRA_EVENT_FILES'])
 
-event_data = GENERATED_FILES['TelemetryEventData.h']
-event_data.script = 'build_scripts/gen_event_data.py'
-event_data.inputs = event_files
+GeneratedFile('TelemetryEventData.h', script='build_scripts/gen_event_data.py',
+              inputs=event_files)
 
-event_enums = GENERATED_FILES['TelemetryEventEnums.h']
-event_enums.script = 'build_scripts/gen_event_enum.py'
-event_enums.inputs = event_files
+GeneratedFile('TelemetryEventEnums.h', script='build_scripts/gen_event_enum.py',
+              inputs=event_files)
 
 # Generate the JSON event definitions. They will only be
 # used in artifact or "build faster" builds.
-event_json_data = GENERATED_FILES['EventArtifactDefinitions.json']
-event_json_data.script = 'build_scripts/gen_event_data.py:generate_JSON_definitions'
-event_json_data.inputs = event_files
+GeneratedFile('EventArtifactDefinitions.json',
+              script='build_scripts/gen_event_data.py',
+              entryt_point='generate_JSON_definitions', inputs=event_files)
 
 # Move the events JSON file to the directory where the Firefox binary is.
 FINAL_TARGET_FILES += ['!EventArtifactDefinitions.json']
 
 # Generate data from Processes.yaml
 processes_files = [
     'Processes.yaml',
 ]
 
-processes_enum = GENERATED_FILES['TelemetryProcessEnums.h']
-processes_enum.script = 'build_scripts/gen_process_enum.py'
-processes_enum.inputs = processes_files
+GeneratedFile('TelemetryProcessEnums.h',
+              script='build_scripts/gen_process_enum.py',
+              inputs=processes_files)
 
-processes_data = GENERATED_FILES['TelemetryProcessData.h']
-processes_data.script = 'build_scripts/gen_process_data.py'
-processes_data.inputs = processes_files
+
+GeneratedFile('TelemetryProcessData.h',
+              script='build_scripts/gen_process_data.py',
+              inputs=processes_files)
 
 # Add support for GeckoView: please note that building GeckoView
 # implies having an Android build. The packaging step decides
 # which files to include. As a consequence, we can simply only
 # include the GeckoView files on all Android builds.
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     # Introduce this define to conditionally enable Telemetry GV code in the various
     # C++ modules. We need this trick in order to run gtest coverage on Treeherder
--- a/toolkit/crashreporter/moz.build
+++ b/toolkit/crashreporter/moz.build
@@ -4,20 +4,16 @@
 # 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/.
 
 SPHINX_TREES['crashreporter'] = 'docs'
 
 with Files('docs/**'):
     SCHEDULES.exclusive = ['docs']
 
-GENERATED_FILES += [
-    'CrashAnnotations.h',
-]
-
 EXPORTS += [
     '!CrashAnnotations.h',
     'nsExceptionHandler.h',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
 UNIFIED_SOURCES = [
@@ -131,17 +127,16 @@ if CONFIG['MOZ_CRASHREPORTER']:
     if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
         CXXFLAGS += ['-Wno-shadow']
 else:
     UNIFIED_SOURCES += [
         'nsDummyExceptionHandler.cpp',
     ]
 
 # Generate CrashAnnotations.h
-crash_annotations = GENERATED_FILES['CrashAnnotations.h']
-crash_annotations.script = 'generate_crash_reporter_sources.py:emit_header'
-crash_annotations.inputs = [
-    'CrashAnnotations.h.in',
-    'CrashAnnotations.yaml',
-]
+GeneratedFile('CrashAnnotations.h', script='generate_crash_reporter_sources.py',
+              entry_point='emit_header', inputs=[
+                  'CrashAnnotations.h.in',
+                  'CrashAnnotations.yaml',
+              ])
 
 with Files('**'):
     BUG_COMPONENT = ('Toolkit', 'Crash Reporting')
--- a/toolkit/library/build/moz.build
+++ b/toolkit/library/build/moz.build
@@ -18,15 +18,12 @@ if CONFIG['COMPILE_ENVIRONMENT']:
     if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):
         full_libname = SHARED_LIBRARY_NAME
     else:
         full_libname = '%s%s%s' % (
             CONFIG['DLL_PREFIX'],
             SHARED_LIBRARY_NAME,
             CONFIG['DLL_SUFFIX']
         )
-    GENERATED_FILES += [('dependentlibs.list', 'dependentlibs.list.gtest')]
-    dep_libs_list = GENERATED_FILES[('dependentlibs.list', 'dependentlibs.list.gtest')]
-    dep_libs_list.script = 'dependentlibs.py:gen_list'
-    dep_libs_list.inputs = [
-        '!%s' % full_libname,
-    ]
+    GeneratedFile('dependentlibs.list', 'dependentlibs.list.gtest',
+                  script='dependentlibs.py', entry_point='gen_list',
+                  inputs=['!%s' % full_libname])
     FINAL_TARGET_FILES += ['!dependentlibs.list', '!dependentlibs.list.gtest']
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -77,22 +77,19 @@ def Libxul(name, output_category=None):
         LDFLAGS += ['-lresolv']
 
     if CONFIG['MOZ_DEBUG_SYMBOLS'] and CONFIG['CC_TYPE'] == 'clang-cl':
         LDFLAGS += ['-NATVIS:%s/toolkit/library/gecko.natvis' % TOPSRCDIR]
     if CONFIG['RUSTC_NATVIS_LDFLAGS']:
         LDFLAGS += CONFIG['RUSTC_NATVIS_LDFLAGS']
 
     if CONFIG['OS_ARCH'] == 'Linux' and CONFIG['OS_TARGET'] != 'Android':
-        GENERATED_FILES += ['symverscript']
-        GENERATED_FILES['symverscript'].script = '/build/gen_symverscript.py'
-        GENERATED_FILES['symverscript'].inputs = ['../symverscript.in']
-        GENERATED_FILES['symverscript'].flags = [
-            'xul%s' % CONFIG['MOZILLA_SYMBOLVERSION']
-        ]
+        GeneratedFile('symverscript', script='/build/gen_symverscript.py',
+                      inputs=['../symverscript.in'],
+                      flags=['xul%s' % CONFIG['MOZILLA_SYMBOLVERSION']])
         SYMBOLS_FILE = '!symverscript'
 
     # Generate GDB pretty printer-autoload files only on Linux. OSX's GDB is
     # too old to support Python pretty-printers; if this changes, we could
     # make this 'ifdef GNU_CC'.
     if CONFIG['OS_ARCH'] == 'Linux':
         # Create a GDB Python auto-load file alongside the libxul shared library
         # in the build directory.
@@ -358,16 +355,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
 # The buildid is refreshed on every (incremental) build. But we want to avoid
 # rebuilding libxul every time, so instead of having a source file that
 # #include's buildid.h, which would have a dependency on it, and that would
 # thus trigger make to rebuild everything, we generate a source with the
 # buildid hard coded in it. Then we make that source file depend on all the
 # objects files that constitute libxul, so that if any of the files linked into
 # libxul is rebuilt, we refresh the buildid and link it into libxul.
 SOURCES += ['!buildid.cpp']
-GENERATED_FILES += ['buildid.cpp']
-GENERATED_FILES['buildid.cpp'].script = 'gen_buildid.py'
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):
     libxul_list = 'XUL'
 else:
     libxul_list = '%sxul_%s' % (
         CONFIG['DLL_PREFIX'], CONFIG['DLL_SUFFIX'].lstrip('.').replace('.','_'))
-GENERATED_FILES['buildid.cpp'].inputs = ['!build/%s.list' % libxul_list]
+GeneratedFile('buildid.cpp', script = 'gen_buildid.py',
+              inputs=['!build/%s.list' % libxul_list])
+
--- a/toolkit/locales/moz.build
+++ b/toolkit/locales/moz.build
@@ -10,21 +10,17 @@ with Files('**'):
 if CONFIG['MOZ_BUILD_APP'] == 'mobile/android':
   DEFINES['MOZ_FENNEC'] = True
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
   DEFINES['MOZ_GTK'] = True
 
 JAR_MANIFESTS += ['jar.mn']
 
-GENERATED_FILES = [
-    'multilocale.txt',
-]
-multilocale = GENERATED_FILES['multilocale.txt']
-multilocale.script = 'gen_multilocale.py'
+GeneratedFile('multilocale.txt', script='gen_multilocale.py')
 FINAL_TARGET_FILES.res += [
     '!multilocale.txt',
 ]
 
 if CONFIG['MOZ_CRASHREPORTER']:
     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
         # TODO: fixing bug 1223748 should let us remove this special case
         LOCALIZED_FILES['crashreporter.app'].Contents.Resources += [
--- a/widget/android/moz.build
+++ b/widget/android/moz.build
@@ -72,23 +72,20 @@ XPCOM_MANIFESTS += [
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 # The recursive make backend treats the first output specially: it's passed as
 # an open FileAvoidWrite to the invoked script.  That doesn't work well with
 # the Gradle task that generates all of the outputs, so we add a dummy first
 # output.
-t = ('generated_jni_wrappers',
-     'GeneratedJNINatives.h',
-     'GeneratedJNIWrappers.h',
-     'GeneratedJNIWrappers.cpp')
-
-GENERATED_FILES += [t]
-GENERATED_FILES[t].script = '/mobile/android/gradle.py:generate_generated_jni_wrappers'
+GeneratedFile(
+    'generated_jni_wrappers', 'GeneratedJNINatives.h', 'GeneratedJNIWrappers.h',
+    'GeneratedJNIWrappers.cpp', script='/mobile/android/gradle.py',
+    entry_point='generate_generated_jni_wrappers')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/system/android',
     '/gfx/2d',
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -195,49 +195,39 @@ if CONFIG['OS_TARGET'] in ('Linux', 'And
         'MemoryMapping.cpp',
     ]
 
 if CONFIG['OS_TARGET'] == 'WINNT':
     UNIFIED_SOURCES += [
         'MemoryInfo.cpp',
     ]
 
-GENERATED_FILES += [
-    "error_list.rs",
-    "ErrorList.h",
-    "ErrorNamesInternal.h",
-]
-
-GENERATED_FILES["ErrorList.h"].script = "ErrorList.py:error_list_h"
-GENERATED_FILES["ErrorNamesInternal.h"].script = "ErrorList.py:error_names_internal_h"
-GENERATED_FILES["error_list.rs"].script = "ErrorList.py:error_list_rs"
+GeneratedFile("ErrorList.h", script="ErrorList.py", entry_point="error_list_h")
+GeneratedFile("ErrorNamesInternal.h", script="ErrorList.py",
+              entry_point="error_names_internal_h")
+GeneratedFile("error_list.rs", script="ErrorList.py",
+              entry_point="error_list_rs")
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     SOURCES += [
         'nsMacUtilsImpl.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     SOURCES += [
         'nsCrashOnException.cpp',
     ]
 
 if CONFIG['COMPILE_ENVIRONMENT']:
-    GENERATED_FILES += [
-        'gk_rust_utils_ffi_generated.h',
-    ]
-
     EXPORTS.mozilla += [
         '!gk_rust_utils_ffi_generated.h',
     ]
 
-    ffi_generated = GENERATED_FILES['gk_rust_utils_ffi_generated.h']
-    ffi_generated.script = '/layout/style/RunCbindgen.py:generate'
-    ffi_generated.inputs = [
-        '/xpcom/rust/gkrust_utils',
-    ]
+    GeneratedFile('gk_rust_utils_ffi_generated.h',
+                  script='/layout/style/RunCbindgen.py',
+                  entry_point='generate', inputs=['/xpcom/rust/gkrust_utils'])
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../build',
     '/dom/base',
--- a/xpcom/build/moz.build
+++ b/xpcom/build/moz.build
@@ -68,25 +68,19 @@ UNIFIED_SOURCES += [
 
 SOURCES += ['!Services.cpp']
 
 if CONFIG['OS_ARCH'] != 'WINNT':
     SOURCES += [
         'NSPRInterposer.cpp',
     ]
 
-GENERATED_FILES += [
-    'Services.cpp',
-    'Services.h',
-    'services.rs',
-]
-
-GENERATED_FILES['Services.cpp'].script = 'Services.py:services_cpp'
-GENERATED_FILES['Services.h'].script = 'Services.py:services_h'
-GENERATED_FILES['services.rs'].script = 'Services.py:services_rs'
+GeneratedFile('Services.cpp', script='Services.py', entry_point='services_cpp')
+GeneratedFile('Services.h', script='Services.py', entry_point='services_h')
+GeneratedFile('services.rs', script='Services.py', entry_point='services_rs')
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 DEFINES['_IMPL_NS_STRINGAPI'] = True
 DEFINES['OMNIJAR_NAME'] = CONFIG['OMNIJAR_NAME']
 
--- a/xpcom/components/moz.build
+++ b/xpcom/components/moz.build
@@ -33,24 +33,20 @@ XPCOM_MANIFESTS += [
     'components.conf',
 ]
 
 if CONFIG['COMPILE_ENVIRONMENT']:
     EXPORTS.mozilla += [
         '!Components.h',
     ]
 
-    generated = ('Components.h', 'StaticComponentData.h',
-                 'StaticComponents.cpp')
-
-    GENERATED_FILES += [generated]
-
-    gen = GENERATED_FILES[generated]
-    gen.script = 'gen_static_components.py'
-    gen.inputs += ['!manifest-lists.json', 'StaticComponents.cpp.in']
+    GeneratedFile(
+        'Components.h', 'StaticComponentData.h', 'StaticComponents.cpp',
+        script='gen_static_components.py',
+        inputs=['!manifest-lists.json', 'StaticComponents.cpp.in'])
 
 UNIFIED_SOURCES += [
     'GenericFactory.cpp',
     'ManifestParser.cpp',
     'nsCategoryCache.cpp',
     'nsCategoryManager.cpp',
     'nsComponentManager.cpp',
     'nsComponentManagerUtils.cpp',
--- a/xpcom/ds/moz.build
+++ b/xpcom/ds/moz.build
@@ -129,17 +129,17 @@ UNIFIED_SOURCES += [
     'PLDHashTable.cpp',
     'Tokenizer.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '../io',
 ]
 
-GENERATED_FILES += ['nsGkAtomList.h']
-GENERATED_FILES['nsGkAtomList.h'].script = 'StaticAtoms.py:generate_nsgkatomlist_h'
-GENERATED_FILES['nsGkAtomList.h'].inputs = ['Atom.py', 'HTMLAtoms.py']
+GeneratedFile('nsGkAtomList.h', script='StaticAtoms.py',
+              entry_point='generate_nsgkatomlist_h',
+              inputs=['Atom.py', 'HTMLAtoms.py'])
 
-GENERATED_FILES += ['nsGkAtomConsts.h']
-GENERATED_FILES['nsGkAtomConsts.h'].script = 'StaticAtoms.py:generate_nsgkatomconsts_h'
-GENERATED_FILES['nsGkAtomConsts.h'].inputs = ['Atom.py', 'HTMLAtoms.py']
+GeneratedFile('nsGkAtomConsts.h', script='StaticAtoms.py',
+              entry_point='generate_nsgkatomconsts_h',
+              inputs=['Atom.py', 'HTMLAtoms.py'])
 
 FINAL_LIBRARY = 'xul'
--- a/xpcom/idl-parser/xpidl/moz.build
+++ b/xpcom/idl-parser/xpidl/moz.build
@@ -3,13 +3,10 @@
 # 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/.
 
 PYTHON_UNITTEST_MANIFESTS += [
     'python.ini',
 ]
 
-GENERATED_FILES += [
-    ('xpidl.stub', 'xpidllex.py', 'xpidlyacc.py'),
-]
-
-GENERATED_FILES[('xpidl.stub', 'xpidllex.py', 'xpidlyacc.py')].script = 'header.py:main'
+GeneratedFile('xpidl.stub', 'xpidllex.py', 'xpidlyacc.py', script='header.py',
+              entry_point='main')
--- a/xpcom/reflect/xptcall/md/win32/moz.build
+++ b/xpcom/reflect/xptcall/md/win32/moz.build
@@ -44,19 +44,17 @@ elif CONFIG['CPU_ARCH'] == 'aarch64':
         'xptcinvoke_asm_aarch64.asm',
         'xptcstubs_asm_aarch64.asm',
     ]
 
     # make gets confused if the srcdir and objdir files have the same name, so
     # we generate different names for the objdir files
     for src in asm_files:
         obj = src.replace('_asm_aarch64', '')
-        GENERATED_FILES += [obj]
-        asm = GENERATED_FILES[obj]
-        asm.script = 'preprocess.py:preprocess'
-        asm.inputs = [src]
+        GeneratedFile(obj, script='preprocess.py', entry_point='preprocess',
+                      inputs=[src])
         SOURCES += ['!%s' % obj]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../..',
 ]