diff --git a/Makefile.in b/Makefile.in index 4b9ccd3754c..84ef5934ade 100644 --- a/Makefile.in +++ b/Makefile.in @@ -94,6 +94,9 @@ ifdef ENABLE_TESTS include $(topsrcdir)/testing/testsuite-targets.mk endif +# Hacky way for precompile tier to bypass default tier traversal mechanism. +TIER_precompile_CUSTOM := 1 + include $(topsrcdir)/config/rules.mk distclean:: diff --git a/config/makefiles/precompile/Makefile.in b/config/makefiles/precompile/Makefile.in index 0484db81e3b..b05da7dcfd9 100644 --- a/config/makefiles/precompile/Makefile.in +++ b/config/makefiles/precompile/Makefile.in @@ -24,10 +24,12 @@ $(call BUILDSTATUS,SUBTIER_FINISH precompile $(1)) endef -export:: - $(call BUILDSTATUS,SUBTIERS IPDL WebIDL XPIDL XPIDLParser) +default:: + $(call BUILDSTATUS,TIER_START precompile IPDL WebIDL XPIDL) + +$(MAKE) export + $(call BUILDSTATUS,TIER_FINISH precompile) -export:: ipdl webidl xpidl-parser xpidl +export:: ipdl webidl xpidl ipdl: $(call make_subtier_dir,IPDL,$(DEPTH)/ipc/ipdl,ipdl) @@ -35,9 +37,9 @@ ipdl: webidl: $(call make_subtier_dir,WebIDL,$(DEPTH)/dom/bindings,webidl) -xpidl-parser: - $(call make_subtier_dir,XPIDLParser,$(DEPTH)/xpcom/idl-parser,xpidl-parser) - -xpidl: xpidl-parser +xpidl: + $(call BUILDSTATUS,SUBTIER_START precompile XPIDL) + +$(MAKE) -C $(DEPTH)/xpcom/idl-parser xpidl-parser $(call py_action,process_install_manifest,$(DIST)/idl $(DEPTH)/_build_manifests/install/dist_idl) - $(call make_subtier_dir,XPIDL,$(DEPTH)/config/makefiles/xpidl,xpidl) + +$(MAKE) -C $(DEPTH)/config/makefiles/xpidl xpidl + $(call BUILDSTATUS,SUBTIER_FINISH precompile XPIDL) diff --git a/config/makefiles/target_export.mk b/config/makefiles/target_export.mk index c3ec5ac58b9..8e664747e7d 100644 --- a/config/makefiles/target_export.mk +++ b/config/makefiles/target_export.mk @@ -14,7 +14,7 @@ PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS)) ############### $(addprefix export_tier_,$(TIERS)): export_tier_%: @$(ECHO) "$@" - $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,export,$(dir))) + $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,export,$(dir),export)) ################# ## Common targets diff --git a/config/makefiles/target_libs.mk b/config/makefiles/target_libs.mk index cd1405bc68a..9b7e2c2bb60 100644 --- a/config/makefiles/target_libs.mk +++ b/config/makefiles/target_libs.mk @@ -14,7 +14,7 @@ PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS)) ############### $(addprefix libs_tier_,$(TIERS)): libs_tier_%: @$(ECHO) "$@" - $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,libs,$(dir))) + $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,libs,$(dir),libs)) ################# ## Common targets diff --git a/config/makefiles/target_tools.mk b/config/makefiles/target_tools.mk index d94acc9dc42..3508f468644 100644 --- a/config/makefiles/target_tools.mk +++ b/config/makefiles/target_tools.mk @@ -14,7 +14,7 @@ PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS)) ############### $(addprefix tools_tier_,$(TIERS)): tools_tier_%: @$(ECHO) "$@" - $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,tools,$(dir))) + $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,tools,$(dir),tools)) ################# ## Common targets diff --git a/config/rules.mk b/config/rules.mk index df815fe7a31..c9f3160cfb0 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -429,8 +429,9 @@ UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-de endif ifdef MACH -BUILDSTATUS=@echo BUILDSTATUS $1 +BUILDSTATUS=@echo "BUILDSTATUS $1" endif + # Static directories are largely independent of our build system. But, they # could share the same build mechanism (like moz.build files). We need to # prevent leaking of our backend state to these independent build systems. This @@ -443,9 +444,9 @@ define SUBMAKE # $(call SUBMAKE,target,directory,static) endef # The extra line is important here! don't delete it define TIER_DIR_SUBMAKE -$(call BUILDSTATUS,TIERDIR_START $(2)) -$(call SUBMAKE,$(1),$(2),$(3)) -$(call BUILDSTATUS,TIERDIR_FINISH $(2)) +$(call BUILDSTATUS,TIERDIR_START $(1) $(2) $(3)) +$(call SUBMAKE,$(4),$(3),$(5)) +$(call BUILDSTATUS,TIERDIR_FINISH $(1) $(2) $(3)) endef # Ths empty line is important. @@ -712,32 +713,38 @@ QUIET := -q endif # This function is called and evaluated to produce the rule to build the -# specified tier. Each tier begins by building the "static" directories. -# The BUILDSTATUS echo commands are used to faciliate easier parsing -# of build output. Build drivers are encouraged to filter these lines -# from the user. +# specified tier. +# +# Tiers are traditionally composed of directories that are invoked either +# once (so-called "static" directories) or 3 times with the export, libs, and +# tools sub-tiers. +# +# If the TIER_$(tier)_CUSTOM variable is defined, then these traditional +# tier rules are ignored and each directory in the tier is executed via a +# sub-make invocation (make -C). define CREATE_TIER_RULE tier_$(1):: - $(call BUILDSTATUS,TIER_START $(1)) - $(call BUILDSTATUS,SUBTIERS $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools)) - $(call BUILDSTATUS,STATICDIRS $$($$@_staticdirs)) - $(call BUILDSTATUS,DIRS $$($$@_dirs)) +ifdef TIER_$(1)_CUSTOM + $$(foreach dir,$$($$@_dirs),$$(call SUBMAKE,,$$(dir))) +else + $(call BUILDSTATUS,TIER_START $(1) $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools)) ifneq (,$(tier_$(1)_staticdirs)) - $(call BUILDSTATUS,SUBTIER_START $(1) static) - $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1)) + $(call BUILDSTATUS,SUBTIER_START $(1) static $$($$@_staticdirs)) + $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,$(1),static,$$(dir),,1)) $(call BUILDSTATUS,SUBTIER_FINISH $(1) static) endif ifneq (,$(tier_$(1)_dirs)) - $(call BUILDSTATUS,SUBTIER_START $(1) export) + $(call BUILDSTATUS,SUBTIER_START $(1) export $$($$@_dirs)) $$(MAKE) export_$$@ $(call BUILDSTATUS,SUBTIER_FINISH $(1) export) - $(call BUILDSTATUS,SUBTIER_START $(1) libs) + $(call BUILDSTATUS,SUBTIER_START $(1) libs $$($$@_dirs)) $$(MAKE) libs_$$@ $(call BUILDSTATUS,SUBTIER_FINISH $(1) libs) - $(call BUILDSTATUS,SUBTIER_START $(1) tools) + $(call BUILDSTATUS,SUBTIER_START $(1) tools $$($$@_dirs)) $$(MAKE) tools_$$@ $(call BUILDSTATUS,SUBTIER_FINISH $(1) tools) - $(call BUILDSTATUS TIER_FINISH $(1)) +endif + $(call BUILDSTATUS,TIER_FINISH $(1)) endif endef diff --git a/js/src/config/makefiles/target_export.mk b/js/src/config/makefiles/target_export.mk index c3ec5ac58b9..8e664747e7d 100644 --- a/js/src/config/makefiles/target_export.mk +++ b/js/src/config/makefiles/target_export.mk @@ -14,7 +14,7 @@ PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS)) ############### $(addprefix export_tier_,$(TIERS)): export_tier_%: @$(ECHO) "$@" - $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,export,$(dir))) + $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,export,$(dir),export)) ################# ## Common targets diff --git a/js/src/config/makefiles/target_libs.mk b/js/src/config/makefiles/target_libs.mk index cd1405bc68a..9b7e2c2bb60 100644 --- a/js/src/config/makefiles/target_libs.mk +++ b/js/src/config/makefiles/target_libs.mk @@ -14,7 +14,7 @@ PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS)) ############### $(addprefix libs_tier_,$(TIERS)): libs_tier_%: @$(ECHO) "$@" - $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,libs,$(dir))) + $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,libs,$(dir),libs)) ################# ## Common targets diff --git a/js/src/config/makefiles/target_tools.mk b/js/src/config/makefiles/target_tools.mk index d94acc9dc42..3508f468644 100644 --- a/js/src/config/makefiles/target_tools.mk +++ b/js/src/config/makefiles/target_tools.mk @@ -14,7 +14,7 @@ PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS)) ############### $(addprefix tools_tier_,$(TIERS)): tools_tier_%: @$(ECHO) "$@" - $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,tools,$(dir))) + $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,tools,$(dir),tools)) ################# ## Common targets diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index df815fe7a31..c9f3160cfb0 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -429,8 +429,9 @@ UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-de endif ifdef MACH -BUILDSTATUS=@echo BUILDSTATUS $1 +BUILDSTATUS=@echo "BUILDSTATUS $1" endif + # Static directories are largely independent of our build system. But, they # could share the same build mechanism (like moz.build files). We need to # prevent leaking of our backend state to these independent build systems. This @@ -443,9 +444,9 @@ define SUBMAKE # $(call SUBMAKE,target,directory,static) endef # The extra line is important here! don't delete it define TIER_DIR_SUBMAKE -$(call BUILDSTATUS,TIERDIR_START $(2)) -$(call SUBMAKE,$(1),$(2),$(3)) -$(call BUILDSTATUS,TIERDIR_FINISH $(2)) +$(call BUILDSTATUS,TIERDIR_START $(1) $(2) $(3)) +$(call SUBMAKE,$(4),$(3),$(5)) +$(call BUILDSTATUS,TIERDIR_FINISH $(1) $(2) $(3)) endef # Ths empty line is important. @@ -712,32 +713,38 @@ QUIET := -q endif # This function is called and evaluated to produce the rule to build the -# specified tier. Each tier begins by building the "static" directories. -# The BUILDSTATUS echo commands are used to faciliate easier parsing -# of build output. Build drivers are encouraged to filter these lines -# from the user. +# specified tier. +# +# Tiers are traditionally composed of directories that are invoked either +# once (so-called "static" directories) or 3 times with the export, libs, and +# tools sub-tiers. +# +# If the TIER_$(tier)_CUSTOM variable is defined, then these traditional +# tier rules are ignored and each directory in the tier is executed via a +# sub-make invocation (make -C). define CREATE_TIER_RULE tier_$(1):: - $(call BUILDSTATUS,TIER_START $(1)) - $(call BUILDSTATUS,SUBTIERS $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools)) - $(call BUILDSTATUS,STATICDIRS $$($$@_staticdirs)) - $(call BUILDSTATUS,DIRS $$($$@_dirs)) +ifdef TIER_$(1)_CUSTOM + $$(foreach dir,$$($$@_dirs),$$(call SUBMAKE,,$$(dir))) +else + $(call BUILDSTATUS,TIER_START $(1) $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools)) ifneq (,$(tier_$(1)_staticdirs)) - $(call BUILDSTATUS,SUBTIER_START $(1) static) - $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1)) + $(call BUILDSTATUS,SUBTIER_START $(1) static $$($$@_staticdirs)) + $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,$(1),static,$$(dir),,1)) $(call BUILDSTATUS,SUBTIER_FINISH $(1) static) endif ifneq (,$(tier_$(1)_dirs)) - $(call BUILDSTATUS,SUBTIER_START $(1) export) + $(call BUILDSTATUS,SUBTIER_START $(1) export $$($$@_dirs)) $$(MAKE) export_$$@ $(call BUILDSTATUS,SUBTIER_FINISH $(1) export) - $(call BUILDSTATUS,SUBTIER_START $(1) libs) + $(call BUILDSTATUS,SUBTIER_START $(1) libs $$($$@_dirs)) $$(MAKE) libs_$$@ $(call BUILDSTATUS,SUBTIER_FINISH $(1) libs) - $(call BUILDSTATUS,SUBTIER_START $(1) tools) + $(call BUILDSTATUS,SUBTIER_START $(1) tools $$($$@_dirs)) $$(MAKE) tools_$$@ $(call BUILDSTATUS,SUBTIER_FINISH $(1) tools) - $(call BUILDSTATUS TIER_FINISH $(1)) +endif + $(call BUILDSTATUS,TIER_FINISH $(1)) endif endef diff --git a/python/mozbuild/mozbuild/controller/building.py b/python/mozbuild/mozbuild/controller/building.py index 3010551332b..eb1aed91df3 100644 --- a/python/mozbuild/mozbuild/controller/building.py +++ b/python/mozbuild/mozbuild/controller/building.py @@ -9,7 +9,10 @@ import os import sys import time -from collections import namedtuple +from collections import ( + namedtuple, + OrderedDict, +) # keep in sync with psutil os support, see psutil/__init__.py if sys.platform.startswith("freebsd") or sys.platform.startswith("darwin") or sys.platform.startswith("win32") or sys.platform.startswith("linux"): @@ -20,6 +23,8 @@ if sys.platform.startswith("freebsd") or sys.platform.startswith("darwin") or sy else: psutil = None +from ..base import MozbuildObject + from ..compilation.warnings import ( WarningsCollector, WarningsDatabase, @@ -30,27 +35,150 @@ BuildOutputResult = namedtuple('BuildOutputResult', ('warning', 'state_changed', 'for_display')) -class BuildMonitor(object): +class TierStatus(object): + """Represents the state and progress of tier traversal. + + The build system is organized into linear phases called tiers. Each tier + executes in the order it was defined, 1 at a time. + + Tiers can have subtiers. Subtiers can execute in any order. Some subtiers + execute sequentially. Others are concurrent. + + Subtiers can have directories. Directories can execute in any order, just + like subtiers. + """ + + def __init__(self): + self.tiers = OrderedDict() + self.active_tier = None + self.active_subtiers = set() + + def set_tiers(self, tiers): + """Record the set of known tiers.""" + for tier in tiers: + self.tiers[tier] = dict( + begin_time=None, + finish_time=None, + duration=None, + subtiers=OrderedDict(), + ) + + def begin_tier(self, tier, subtiers): + """Record that execution of a tier has begun.""" + t = self.tiers[tier] + # We should ideally use a monotonic clock here. Unfortunately, we won't + # have one until Python 3. + t['begin_time'] = time.time() + for subtier in subtiers: + t['subtiers'][subtier] = dict( + begin_time=None, + finish_time=None, + duration=None, + concurrent=False, + dirs=OrderedDict(), + dirs_complete=0, + ) + + self.active_tier = tier + self.active_subtiers = set() + self.active_dirs = {} + + def finish_tier(self, tier): + """Record that execution of a tier has finished.""" + t = self.tiers[tier] + t['finish_time'] = time.time() + t['duration'] = t['finish_time'] - t['begin_time'] + + def begin_subtier(self, tier, subtier, dirs): + """Record that execution of a subtier has begun.""" + st = self.tiers[tier]['subtiers'][subtier] + st['begin_time'] = time.time() + + for d in dirs: + st['dirs'][d] = dict( + begin_time=None, + finish_time=None, + duration=None, + concurrent=False, + ) + + if self.active_subtiers: + st['concurrent'] = True + + self.active_subtiers.add(subtier) + + def finish_subtier(self, tier, subtier): + """Record that execution of a subtier has finished.""" + st = self.tiers[tier]['subtiers'][subtier] + st['finish_time'] = time.time() + + self.active_subtiers.remove(subtier) + if self.active_subtiers: + st['concurrent'] = True + + # A subtier may not have directories. + try: + del self.active_dirs[subtier] + except KeyError: + pass + + st['duration'] = st['finish_time'] - st['begin_time'] + + def begin_dir(self, tier, subtier, d): + """Record that execution of a directory has begun.""" + entry = self.tiers[tier]['subtiers'][subtier]['dirs'][d] + entry['begin_time'] = time.time() + + self.active_dirs.setdefault(subtier, set()).add(d) + + if len(self.active_dirs[subtier]) > 1: + entry['concurrent'] = True + + def finish_dir(self, tier, subtier, d): + """Record that execution of a directory has finished.""" + st = self.tiers[tier]['subtiers'][subtier] + st['dirs_complete'] += 1 + + entry = st['dirs'][d] + entry['finish_time'] = time.time() + + self.active_dirs[subtier].remove(d) + entry['duration'] = entry['finish_time'] - entry['begin_time'] + + if self.active_dirs[subtier]: + entry['concurrent'] = True + + def tier_status(self): + for tier, state in self.tiers.items(): + active = self.active_tier == tier + finished = state['finish_time'] is not None + + yield tier, active, finished + + def current_subtier_status(self): + for subtier, state in self.tiers[self.active_tier]['subtiers'].items(): + active = subtier in self.active_subtiers + finished = state['finish_time'] is not None + + yield subtier, active, finished + + def current_dirs_status(self): + for subtier, dirs in self.active_dirs.items(): + st = self.tiers[self.active_tier]['subtiers'][subtier] + yield subtier, st['dirs'].keys(), dirs, st['dirs_complete'] + + +class BuildMonitor(MozbuildObject): """Monitors the output of the build.""" - def __init__(self, topobjdir, warnings_path): + def init(self, warnings_path): """Create a new monitor. warnings_path is a path of a warnings database to use. """ self._warnings_path = warnings_path - self.tiers = [] - self.subtiers = [] - self.current_tier = None - self.current_subtier = None - self.current_tier_dirs = [] - self.current_tier_static_dirs = [] - self.current_subtier_dirs = [] - self.current_subtier_started = set() - self.current_subtier_finished = set() - self.current_tier_dir = None - self.current_tier_dir_index = 0 + self.tiers = TierStatus() self.warnings_database = WarningsDatabase() if os.path.exists(warnings_path): @@ -60,7 +188,7 @@ class BuildMonitor(object): os.remove(warnings_path) self._warnings_collector = WarningsCollector( - database=self.warnings_database, objdir=topobjdir) + database=self.warnings_database, objdir=self.topobjdir) def start(self): """Record the start of the build.""" @@ -93,51 +221,28 @@ class BuildMonitor(object): update_needed = True if action == 'TIERS': - self.tiers = args - update_needed = False - elif action == 'SUBTIERS': - self.subtiers = args - update_needed = False - elif action == 'STATICDIRS': - self.current_tier_static_dirs = args - update_needed = False - elif action == 'DIRS': - self.current_tier_dirs = args + self.tiers.set_tiers(args) update_needed = False elif action == 'TIER_START': - assert len(args) == 1 - self.current_tier = args[0] - self.current_subtier = None - self.current_tier_dirs = [] - self.current_subtier_started = set() - self.current_subtier_finished = set() - self.current_tier_dir = None + tier = args[0] + subtiers = args[1:] + self.tiers.begin_tier(tier, subtiers) elif action == 'TIER_FINISH': - assert len(args) == 1 - assert args[0] == self.current_tier + tier, = args + self.tiers.finish_tier(tier) elif action == 'SUBTIER_START': - assert len(args) == 2 - tier, subtier = args - assert tier == self.current_tier - self.current_subtier = subtier - if subtier == 'static': - self.current_subtier_dirs = self.current_tier_static_dirs - else: - self.current_subtier_dirs = self.current_tier_dirs - self.current_tier_dir_index = 0 - self.current_subtier_started.add(subtier) + tier, subtier = args[0:2] + dirs = args[2:] + self.tiers.begin_subtier(tier, subtier, dirs) elif action == 'SUBTIER_FINISH': - assert len(args) == 2 tier, subtier = args - assert tier == self.current_tier - self.current_subtier_finished.add(subtier) + self.tiers.finish_subtier(tier, subtier) elif action == 'TIERDIR_START': - assert len(args) == 1 - self.current_tier_dir = args[0] - self.current_tier_dir_index += 1 + tier, subtier, d = args + self.tiers.begin_dir(tier, subtier, d) elif action == 'TIERDIR_FINISH': - assert len(args) == 1 - assert self.current_tier_dir == args[0] + tier, subtier, d = args + self.tiers.finish_dir(tier, subtier, d) else: raise Exception('Unknown build status: %s' % action) diff --git a/python/mozbuild/mozbuild/mach_commands.py b/python/mozbuild/mozbuild/mach_commands.py index b1c387f9e45..88a6f55014a 100644 --- a/python/mozbuild/mozbuild/mach_commands.py +++ b/python/mozbuild/mozbuild/mach_commands.py @@ -113,7 +113,9 @@ class BuildProgressFooter(object): def draw(self): """Draws this footer in the terminal.""" - if not self._monitor.tiers: + tiers = self._monitor.tiers + + if not tiers.tiers: return # The drawn terminal looks something like: @@ -124,34 +126,48 @@ class BuildProgressFooter(object): # big comment below. parts = [('bold', 'TIER'), ':', ' '] - current_encountered = False - for tier in self._monitor.tiers: - if tier == self._monitor.current_tier: + for tier, active, finished in tiers.tier_status(): + if active: parts.extend([('underline_yellow', tier), ' ']) - current_encountered = True - elif not current_encountered: + elif finished: parts.extend([('green', tier), ' ']) else: parts.extend([tier, ' ']) parts.extend([('bold', 'SUBTIER'), ':', ' ']) - for subtier in self._monitor.subtiers: - if subtier in self._monitor.current_subtier_finished: - parts.extend([('green', subtier), ' ']) - elif subtier in self._monitor.current_subtier_started: + for subtier, active, finished in tiers.current_subtier_status(): + if active: parts.extend([('underline_yellow', subtier), ' ']) + elif finished: + parts.extend([('green', subtier), ' ']) else: parts.extend([subtier, ' ']) - if self._monitor.current_subtier_dirs and self._monitor.current_tier_dir: - parts.extend([ - ('bold', 'DIRECTORIES'), ': ', - '%02d' % self._monitor.current_tier_dir_index, - '/', - '%02d' % len(self._monitor.current_subtier_dirs), - ' ', - '(', ('magenta', self._monitor.current_tier_dir), ')', - ]) + if tiers.active_dirs: + parts.extend([('bold', 'DIRECTORIES'), ': ']) + have_dirs = False + + for subtier, all_dirs, active_dirs, complete in tiers.current_dirs_status(): + if len(all_dirs) < 2: + continue + + have_dirs = True + + parts.extend([ + '%02d' % (complete + 1), + '/', + '%02d' % len(all_dirs), + ' ', + '(', + ]) + for d in active_dirs: + parts.extend([ + ('magenta', d), ' ,' + ]) + parts[-1] = ')' + + if not have_dirs: + parts = parts[0:-2] # We don't want to write more characters than the current width of the # terminal otherwise wrapping may result in weird behavior. We can't @@ -274,7 +290,8 @@ class Build(MachCommandBase): from mozbuild.util import resolve_target_to_make warnings_path = self._get_state_filename('warnings.json') - monitor = BuildMonitor(self.topobjdir, warnings_path) + monitor = self._spawn(BuildMonitor) + monitor.init(warnings_path) with BuildOutputManager(self.log_manager, monitor) as output: monitor.start()