Bug 905879 - More robust tier tracking; r=glandium

This commit is contained in:
Gregory Szorc 2013-08-20 00:06:32 -07:00
parent 850a171242
commit acd9d1a011
12 changed files with 263 additions and 122 deletions

View File

@ -94,6 +94,9 @@ ifdef ENABLE_TESTS
include $(topsrcdir)/testing/testsuite-targets.mk include $(topsrcdir)/testing/testsuite-targets.mk
endif endif
# Hacky way for precompile tier to bypass default tier traversal mechanism.
TIER_precompile_CUSTOM := 1
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
distclean:: distclean::

View File

@ -24,10 +24,12 @@ $(call BUILDSTATUS,SUBTIER_FINISH precompile $(1))
endef endef
export:: default::
$(call BUILDSTATUS,SUBTIERS IPDL WebIDL XPIDL XPIDLParser) $(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: ipdl:
$(call make_subtier_dir,IPDL,$(DEPTH)/ipc/ipdl,ipdl) $(call make_subtier_dir,IPDL,$(DEPTH)/ipc/ipdl,ipdl)
@ -35,9 +37,9 @@ ipdl:
webidl: webidl:
$(call make_subtier_dir,WebIDL,$(DEPTH)/dom/bindings,webidl) $(call make_subtier_dir,WebIDL,$(DEPTH)/dom/bindings,webidl)
xpidl-parser: xpidl:
$(call make_subtier_dir,XPIDLParser,$(DEPTH)/xpcom/idl-parser,xpidl-parser) $(call BUILDSTATUS,SUBTIER_START precompile XPIDL)
+$(MAKE) -C $(DEPTH)/xpcom/idl-parser xpidl-parser
xpidl: xpidl-parser
$(call py_action,process_install_manifest,$(DIST)/idl $(DEPTH)/_build_manifests/install/dist_idl) $(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)

View File

@ -14,7 +14,7 @@ PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
############### ###############
$(addprefix export_tier_,$(TIERS)): export_tier_%: $(addprefix export_tier_,$(TIERS)): export_tier_%:
@$(ECHO) "$@" @$(ECHO) "$@"
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,export,$(dir))) $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,export,$(dir),export))
################# #################
## Common targets ## Common targets

View File

@ -14,7 +14,7 @@ PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
############### ###############
$(addprefix libs_tier_,$(TIERS)): libs_tier_%: $(addprefix libs_tier_,$(TIERS)): libs_tier_%:
@$(ECHO) "$@" @$(ECHO) "$@"
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,libs,$(dir))) $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,libs,$(dir),libs))
################# #################
## Common targets ## Common targets

View File

@ -14,7 +14,7 @@ PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
############### ###############
$(addprefix tools_tier_,$(TIERS)): tools_tier_%: $(addprefix tools_tier_,$(TIERS)): tools_tier_%:
@$(ECHO) "$@" @$(ECHO) "$@"
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,tools,$(dir))) $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,tools,$(dir),tools))
################# #################
## Common targets ## Common targets

View File

@ -429,8 +429,9 @@ UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-de
endif endif
ifdef MACH ifdef MACH
BUILDSTATUS=@echo BUILDSTATUS $1 BUILDSTATUS=@echo "BUILDSTATUS $1"
endif endif
# Static directories are largely independent of our build system. But, they # Static directories are largely independent of our build system. But, they
# could share the same build mechanism (like moz.build files). We need to # 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 # 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 endef # The extra line is important here! don't delete it
define TIER_DIR_SUBMAKE define TIER_DIR_SUBMAKE
$(call BUILDSTATUS,TIERDIR_START $(2)) $(call BUILDSTATUS,TIERDIR_START $(1) $(2) $(3))
$(call SUBMAKE,$(1),$(2),$(3)) $(call SUBMAKE,$(4),$(3),$(5))
$(call BUILDSTATUS,TIERDIR_FINISH $(2)) $(call BUILDSTATUS,TIERDIR_FINISH $(1) $(2) $(3))
endef # Ths empty line is important. endef # Ths empty line is important.
@ -712,32 +713,38 @@ QUIET := -q
endif endif
# This function is called and evaluated to produce the rule to build the # This function is called and evaluated to produce the rule to build the
# specified tier. Each tier begins by building the "static" directories. # specified tier.
# The BUILDSTATUS echo commands are used to faciliate easier parsing #
# of build output. Build drivers are encouraged to filter these lines # Tiers are traditionally composed of directories that are invoked either
# from the user. # 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 define CREATE_TIER_RULE
tier_$(1):: tier_$(1)::
$(call BUILDSTATUS,TIER_START $(1)) ifdef TIER_$(1)_CUSTOM
$(call BUILDSTATUS,SUBTIERS $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools)) $$(foreach dir,$$($$@_dirs),$$(call SUBMAKE,,$$(dir)))
$(call BUILDSTATUS,STATICDIRS $$($$@_staticdirs)) else
$(call BUILDSTATUS,DIRS $$($$@_dirs)) $(call BUILDSTATUS,TIER_START $(1) $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools))
ifneq (,$(tier_$(1)_staticdirs)) ifneq (,$(tier_$(1)_staticdirs))
$(call BUILDSTATUS,SUBTIER_START $(1) static) $(call BUILDSTATUS,SUBTIER_START $(1) static $$($$@_staticdirs))
$$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1)) $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,$(1),static,$$(dir),,1))
$(call BUILDSTATUS,SUBTIER_FINISH $(1) static) $(call BUILDSTATUS,SUBTIER_FINISH $(1) static)
endif endif
ifneq (,$(tier_$(1)_dirs)) ifneq (,$(tier_$(1)_dirs))
$(call BUILDSTATUS,SUBTIER_START $(1) export) $(call BUILDSTATUS,SUBTIER_START $(1) export $$($$@_dirs))
$$(MAKE) export_$$@ $$(MAKE) export_$$@
$(call BUILDSTATUS,SUBTIER_FINISH $(1) export) $(call BUILDSTATUS,SUBTIER_FINISH $(1) export)
$(call BUILDSTATUS,SUBTIER_START $(1) libs) $(call BUILDSTATUS,SUBTIER_START $(1) libs $$($$@_dirs))
$$(MAKE) libs_$$@ $$(MAKE) libs_$$@
$(call BUILDSTATUS,SUBTIER_FINISH $(1) libs) $(call BUILDSTATUS,SUBTIER_FINISH $(1) libs)
$(call BUILDSTATUS,SUBTIER_START $(1) tools) $(call BUILDSTATUS,SUBTIER_START $(1) tools $$($$@_dirs))
$$(MAKE) tools_$$@ $$(MAKE) tools_$$@
$(call BUILDSTATUS,SUBTIER_FINISH $(1) tools) $(call BUILDSTATUS,SUBTIER_FINISH $(1) tools)
$(call BUILDSTATUS TIER_FINISH $(1)) endif
$(call BUILDSTATUS,TIER_FINISH $(1))
endif endif
endef endef

View File

@ -14,7 +14,7 @@ PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
############### ###############
$(addprefix export_tier_,$(TIERS)): export_tier_%: $(addprefix export_tier_,$(TIERS)): export_tier_%:
@$(ECHO) "$@" @$(ECHO) "$@"
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,export,$(dir))) $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,export,$(dir),export))
################# #################
## Common targets ## Common targets

View File

@ -14,7 +14,7 @@ PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
############### ###############
$(addprefix libs_tier_,$(TIERS)): libs_tier_%: $(addprefix libs_tier_,$(TIERS)): libs_tier_%:
@$(ECHO) "$@" @$(ECHO) "$@"
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,libs,$(dir))) $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,libs,$(dir),libs))
################# #################
## Common targets ## Common targets

View File

@ -14,7 +14,7 @@ PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
############### ###############
$(addprefix tools_tier_,$(TIERS)): tools_tier_%: $(addprefix tools_tier_,$(TIERS)): tools_tier_%:
@$(ECHO) "$@" @$(ECHO) "$@"
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,tools,$(dir))) $(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,tools,$(dir),tools))
################# #################
## Common targets ## Common targets

View File

@ -429,8 +429,9 @@ UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-de
endif endif
ifdef MACH ifdef MACH
BUILDSTATUS=@echo BUILDSTATUS $1 BUILDSTATUS=@echo "BUILDSTATUS $1"
endif endif
# Static directories are largely independent of our build system. But, they # Static directories are largely independent of our build system. But, they
# could share the same build mechanism (like moz.build files). We need to # 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 # 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 endef # The extra line is important here! don't delete it
define TIER_DIR_SUBMAKE define TIER_DIR_SUBMAKE
$(call BUILDSTATUS,TIERDIR_START $(2)) $(call BUILDSTATUS,TIERDIR_START $(1) $(2) $(3))
$(call SUBMAKE,$(1),$(2),$(3)) $(call SUBMAKE,$(4),$(3),$(5))
$(call BUILDSTATUS,TIERDIR_FINISH $(2)) $(call BUILDSTATUS,TIERDIR_FINISH $(1) $(2) $(3))
endef # Ths empty line is important. endef # Ths empty line is important.
@ -712,32 +713,38 @@ QUIET := -q
endif endif
# This function is called and evaluated to produce the rule to build the # This function is called and evaluated to produce the rule to build the
# specified tier. Each tier begins by building the "static" directories. # specified tier.
# The BUILDSTATUS echo commands are used to faciliate easier parsing #
# of build output. Build drivers are encouraged to filter these lines # Tiers are traditionally composed of directories that are invoked either
# from the user. # 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 define CREATE_TIER_RULE
tier_$(1):: tier_$(1)::
$(call BUILDSTATUS,TIER_START $(1)) ifdef TIER_$(1)_CUSTOM
$(call BUILDSTATUS,SUBTIERS $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools)) $$(foreach dir,$$($$@_dirs),$$(call SUBMAKE,,$$(dir)))
$(call BUILDSTATUS,STATICDIRS $$($$@_staticdirs)) else
$(call BUILDSTATUS,DIRS $$($$@_dirs)) $(call BUILDSTATUS,TIER_START $(1) $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools))
ifneq (,$(tier_$(1)_staticdirs)) ifneq (,$(tier_$(1)_staticdirs))
$(call BUILDSTATUS,SUBTIER_START $(1) static) $(call BUILDSTATUS,SUBTIER_START $(1) static $$($$@_staticdirs))
$$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1)) $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,$(1),static,$$(dir),,1))
$(call BUILDSTATUS,SUBTIER_FINISH $(1) static) $(call BUILDSTATUS,SUBTIER_FINISH $(1) static)
endif endif
ifneq (,$(tier_$(1)_dirs)) ifneq (,$(tier_$(1)_dirs))
$(call BUILDSTATUS,SUBTIER_START $(1) export) $(call BUILDSTATUS,SUBTIER_START $(1) export $$($$@_dirs))
$$(MAKE) export_$$@ $$(MAKE) export_$$@
$(call BUILDSTATUS,SUBTIER_FINISH $(1) export) $(call BUILDSTATUS,SUBTIER_FINISH $(1) export)
$(call BUILDSTATUS,SUBTIER_START $(1) libs) $(call BUILDSTATUS,SUBTIER_START $(1) libs $$($$@_dirs))
$$(MAKE) libs_$$@ $$(MAKE) libs_$$@
$(call BUILDSTATUS,SUBTIER_FINISH $(1) libs) $(call BUILDSTATUS,SUBTIER_FINISH $(1) libs)
$(call BUILDSTATUS,SUBTIER_START $(1) tools) $(call BUILDSTATUS,SUBTIER_START $(1) tools $$($$@_dirs))
$$(MAKE) tools_$$@ $$(MAKE) tools_$$@
$(call BUILDSTATUS,SUBTIER_FINISH $(1) tools) $(call BUILDSTATUS,SUBTIER_FINISH $(1) tools)
$(call BUILDSTATUS TIER_FINISH $(1)) endif
$(call BUILDSTATUS,TIER_FINISH $(1))
endif endif
endef endef

View File

@ -9,7 +9,10 @@ import os
import sys import sys
import time import time
from collections import namedtuple from collections import (
namedtuple,
OrderedDict,
)
# keep in sync with psutil os support, see psutil/__init__.py # 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"): 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: else:
psutil = None psutil = None
from ..base import MozbuildObject
from ..compilation.warnings import ( from ..compilation.warnings import (
WarningsCollector, WarningsCollector,
WarningsDatabase, WarningsDatabase,
@ -30,27 +35,150 @@ BuildOutputResult = namedtuple('BuildOutputResult',
('warning', 'state_changed', 'for_display')) ('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.""" """Monitors the output of the build."""
def __init__(self, topobjdir, warnings_path): def init(self, warnings_path):
"""Create a new monitor. """Create a new monitor.
warnings_path is a path of a warnings database to use. warnings_path is a path of a warnings database to use.
""" """
self._warnings_path = warnings_path self._warnings_path = warnings_path
self.tiers = [] self.tiers = TierStatus()
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.warnings_database = WarningsDatabase() self.warnings_database = WarningsDatabase()
if os.path.exists(warnings_path): if os.path.exists(warnings_path):
@ -60,7 +188,7 @@ class BuildMonitor(object):
os.remove(warnings_path) os.remove(warnings_path)
self._warnings_collector = WarningsCollector( self._warnings_collector = WarningsCollector(
database=self.warnings_database, objdir=topobjdir) database=self.warnings_database, objdir=self.topobjdir)
def start(self): def start(self):
"""Record the start of the build.""" """Record the start of the build."""
@ -93,51 +221,28 @@ class BuildMonitor(object):
update_needed = True update_needed = True
if action == 'TIERS': if action == 'TIERS':
self.tiers = args self.tiers.set_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
update_needed = False update_needed = False
elif action == 'TIER_START': elif action == 'TIER_START':
assert len(args) == 1 tier = args[0]
self.current_tier = args[0] subtiers = args[1:]
self.current_subtier = None self.tiers.begin_tier(tier, subtiers)
self.current_tier_dirs = []
self.current_subtier_started = set()
self.current_subtier_finished = set()
self.current_tier_dir = None
elif action == 'TIER_FINISH': elif action == 'TIER_FINISH':
assert len(args) == 1 tier, = args
assert args[0] == self.current_tier self.tiers.finish_tier(tier)
elif action == 'SUBTIER_START': elif action == 'SUBTIER_START':
assert len(args) == 2 tier, subtier = args[0:2]
tier, subtier = args dirs = args[2:]
assert tier == self.current_tier self.tiers.begin_subtier(tier, subtier, dirs)
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)
elif action == 'SUBTIER_FINISH': elif action == 'SUBTIER_FINISH':
assert len(args) == 2
tier, subtier = args tier, subtier = args
assert tier == self.current_tier self.tiers.finish_subtier(tier, subtier)
self.current_subtier_finished.add(subtier)
elif action == 'TIERDIR_START': elif action == 'TIERDIR_START':
assert len(args) == 1 tier, subtier, d = args
self.current_tier_dir = args[0] self.tiers.begin_dir(tier, subtier, d)
self.current_tier_dir_index += 1
elif action == 'TIERDIR_FINISH': elif action == 'TIERDIR_FINISH':
assert len(args) == 1 tier, subtier, d = args
assert self.current_tier_dir == args[0] self.tiers.finish_dir(tier, subtier, d)
else: else:
raise Exception('Unknown build status: %s' % action) raise Exception('Unknown build status: %s' % action)

View File

@ -113,7 +113,9 @@ class BuildProgressFooter(object):
def draw(self): def draw(self):
"""Draws this footer in the terminal.""" """Draws this footer in the terminal."""
if not self._monitor.tiers: tiers = self._monitor.tiers
if not tiers.tiers:
return return
# The drawn terminal looks something like: # The drawn terminal looks something like:
@ -124,34 +126,48 @@ class BuildProgressFooter(object):
# big comment below. # big comment below.
parts = [('bold', 'TIER'), ':', ' '] parts = [('bold', 'TIER'), ':', ' ']
current_encountered = False for tier, active, finished in tiers.tier_status():
for tier in self._monitor.tiers: if active:
if tier == self._monitor.current_tier:
parts.extend([('underline_yellow', tier), ' ']) parts.extend([('underline_yellow', tier), ' '])
current_encountered = True elif finished:
elif not current_encountered:
parts.extend([('green', tier), ' ']) parts.extend([('green', tier), ' '])
else: else:
parts.extend([tier, ' ']) parts.extend([tier, ' '])
parts.extend([('bold', 'SUBTIER'), ':', ' ']) parts.extend([('bold', 'SUBTIER'), ':', ' '])
for subtier in self._monitor.subtiers: for subtier, active, finished in tiers.current_subtier_status():
if subtier in self._monitor.current_subtier_finished: if active:
parts.extend([('green', subtier), ' '])
elif subtier in self._monitor.current_subtier_started:
parts.extend([('underline_yellow', subtier), ' ']) parts.extend([('underline_yellow', subtier), ' '])
elif finished:
parts.extend([('green', subtier), ' '])
else: else:
parts.extend([subtier, ' ']) parts.extend([subtier, ' '])
if self._monitor.current_subtier_dirs and 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([ parts.extend([
('bold', 'DIRECTORIES'), ': ', '%02d' % (complete + 1),
'%02d' % self._monitor.current_tier_dir_index,
'/', '/',
'%02d' % len(self._monitor.current_subtier_dirs), '%02d' % len(all_dirs),
' ', ' ',
'(', ('magenta', self._monitor.current_tier_dir), ')', '(',
]) ])
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 # 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 # 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 from mozbuild.util import resolve_target_to_make
warnings_path = self._get_state_filename('warnings.json') 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: with BuildOutputManager(self.log_manager, monitor) as output:
monitor.start() monitor.start()