зеркало из https://github.com/mozilla/gecko-dev.git
Bug 907365 - Pseudo-derecursify the build (opt-in). r=gps
Also remove the compile tier added in bug 912856 when pseudo-derecursify is disabled.
This commit is contained in:
Родитель
c56305c3a6
Коммит
bbe7163df0
|
@ -104,7 +104,7 @@ include $(topsrcdir)/testing/testsuite-targets.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
default all::
|
default all::
|
||||||
$(call BUILDSTATUS,TIERS export compile libs tools)
|
$(call BUILDSTATUS,TIERS export $(if $(MOZ_PSEUDO_DERECURSE),compile )libs tools)
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
|
@ -179,7 +179,10 @@ ifdef MOZ_CRASHREPORTER
|
||||||
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) "$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip"
|
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) "$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# defined in package-name.mk
|
# MOZ_SOURCE_STAMP is defined in package-name.mk with a deferred assignment.
|
||||||
|
# exporting it makes make run its $(shell) command for each invoked submake,
|
||||||
|
# so transform it to an immediate assignment.
|
||||||
|
MOZ_SOURCE_STAMP := $(MOZ_SOURCE_STAMP)
|
||||||
export MOZ_SOURCE_STAMP
|
export MOZ_SOURCE_STAMP
|
||||||
|
|
||||||
#XXX: this is a hack, since we don't want to clobber for MSVC
|
#XXX: this is a hack, since we don't want to clobber for MSVC
|
||||||
|
|
|
@ -181,3 +181,5 @@ if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_SUBST([MOZ_PSEUDO_DERECURSE])
|
||||||
|
|
|
@ -6,15 +6,106 @@ ifndef INCLUDED_RULES_MK
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# The traditional model of directory traversal with make is as follows:
|
||||||
|
# make -C foo
|
||||||
|
# Entering foo
|
||||||
|
# make -C bar
|
||||||
|
# Entering foo/bar
|
||||||
|
# make -C baz
|
||||||
|
# Entering foo/baz
|
||||||
|
# make -C qux
|
||||||
|
# Entering qux
|
||||||
|
#
|
||||||
|
# Pseudo derecurse transforms the above into:
|
||||||
|
# make -C foo
|
||||||
|
# make -C foo/bar
|
||||||
|
# make -C foo/baz
|
||||||
|
# make -C qux
|
||||||
|
|
||||||
|
ifeq (1_.,$(MOZ_PSEUDO_DERECURSE)_$(DEPTH))
|
||||||
|
|
||||||
|
include root.mk
|
||||||
|
|
||||||
|
# Disable build status for mach in top directories without TIERS.
|
||||||
|
# In practice this disables it when recursing under js/src, which confuses mach.
|
||||||
|
ifndef TIERS
|
||||||
|
BUILDSTATUS =
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Main rules (export, compile, libs and tools) call recurse_* rules.
|
||||||
|
# This wrapping is only really useful for build status.
|
||||||
|
compile libs export tools::
|
||||||
|
$(call BUILDSTATUS,TIER_START $@ $($@_subtiers))
|
||||||
|
+$(MAKE) recurse_$@
|
||||||
|
$(call BUILDSTATUS,TIER_FINISH $@)
|
||||||
|
|
||||||
|
# Carefully avoid $(eval) type of rule generation, which makes pymake slower
|
||||||
|
# than necessary.
|
||||||
|
# Get current tier and corresponding subtiers from the data in root.mk.
|
||||||
|
CURRENT_TIER := $(filter $(foreach tier,compile libs export tools,recurse_$(tier)),$(MAKECMDGOALS))
|
||||||
|
ifneq (,$(filter-out 0 1,$(words $(CURRENT_TIER))))
|
||||||
|
$(error $(CURRENT_TIER) not supported on the same make command line)
|
||||||
|
endif
|
||||||
|
CURRENT_TIER := $(subst recurse_,,$(CURRENT_TIER))
|
||||||
|
CURRENT_SUBTIERS := $($(CURRENT_TIER)_subtiers)
|
||||||
|
|
||||||
|
# The rules here are doing directory traversal, so we don't want further
|
||||||
|
# recursion to happen when running make -C subdir $tier. But some make files
|
||||||
|
# further call make -C something else, and sometimes expect recursion to
|
||||||
|
# happen in that case (see browser/metro/locales/Makefile.in for example).
|
||||||
|
# Conveniently, every invocation of make increases MAKELEVEL, so only stop
|
||||||
|
# recursion from happening at current MAKELEVEL + 1.
|
||||||
|
ifdef CURRENT_TIER
|
||||||
|
ifeq (0,$(MAKELEVEL))
|
||||||
|
export NO_RECURSE_MAKELEVEL=1
|
||||||
|
else
|
||||||
|
export NO_RECURSE_MAKELEVEL=$(word $(MAKELEVEL),2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Get all directories traversed for all subtiers in the current tier, or use
|
||||||
|
# directly the $(*_dirs) variables available in root.mk when there is no
|
||||||
|
# TIERS (like for js/src).
|
||||||
|
CURRENT_DIRS := $(or $($(CURRENT_TIER)_dirs),$(foreach subtier,$(CURRENT_SUBTIERS),$($(CURRENT_TIER)_subtier_$(subtier))))
|
||||||
|
|
||||||
|
# Subtier delimiter rules
|
||||||
|
$(addprefix subtiers/,$(addsuffix _start/$(CURRENT_TIER),$(CURRENT_SUBTIERS))): subtiers/%_start/$(CURRENT_TIER):
|
||||||
|
$(call BUILDSTATUS,SUBTIER_START $(CURRENT_TIER) $* $(if $(BUG_915535_FIXED),$($(CURRENT_TIER)_subtier_$*)))
|
||||||
|
|
||||||
|
$(addprefix subtiers/,$(addsuffix _finish/$(CURRENT_TIER),$(CURRENT_SUBTIERS))): subtiers/%_finish/$(CURRENT_TIER):
|
||||||
|
$(call BUILDSTATUS,SUBTIER_FINISH $(CURRENT_TIER) $*)
|
||||||
|
|
||||||
|
# Recursion rule for all directories traversed for all subtiers in the
|
||||||
|
# current tier.
|
||||||
|
# root.mk defines subtier_of_* variables, that map a normalized subdir path to
|
||||||
|
# a subtier name (e.g. subtier_of_memory_jemalloc = base)
|
||||||
|
$(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS)): %/$(CURRENT_TIER):
|
||||||
|
ifdef BUG_915535_FIXED
|
||||||
|
$(call BUILDSTATUS,TIERDIR_START $(CURRENT_TIER) $(subtier_of_$(subst /,_,$*)) $*)
|
||||||
|
endif
|
||||||
|
+@$(MAKE) -C $* $(if $(filter $*,$(tier_$(subtier_of_$(subst /,_,$*))_staticdirs)),,$(CURRENT_TIER))
|
||||||
|
ifdef BUG_915535_FIXED
|
||||||
|
$(call BUILDSTATUS,TIERDIR_FINISH $(CURRENT_TIER) $(subtier_of_$(subst /,_,$*)) $*)
|
||||||
|
endif
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
# Don't recurse if MAKELEVEL is NO_RECURSE_MAKELEVEL as defined above, but
|
||||||
|
# still recurse for externally managed make files (gyp-generated ones).
|
||||||
|
ifeq ($(EXTERNALLY_MANAGED_MAKE_FILE)_$(NO_RECURSE_MAKELEVEL),_$(MAKELEVEL))
|
||||||
|
|
||||||
|
compile libs export tools::
|
||||||
|
|
||||||
|
else
|
||||||
#########################
|
#########################
|
||||||
# Tier traversal handling
|
# Tier traversal handling
|
||||||
#########################
|
#########################
|
||||||
|
|
||||||
ifdef TIERS
|
ifdef TIERS
|
||||||
|
|
||||||
compile libs export tools::
|
libs export tools::
|
||||||
$(call BUILDSTATUS,TIER_START $@ $(filter-out $(if $(filter export,$@),,precompile),$(TIERS)))
|
$(call BUILDSTATUS,TIER_START $@ $(filter-out $(if $(filter export,$@),,precompile),$(TIERS)))
|
||||||
$(foreach tier,$(TIERS), $(if $(filter-out compile_precompile libs_precompile tools_precompile,$@_$(tier)), \
|
$(foreach tier,$(TIERS), $(if $(filter-out libs_precompile tools_precompile,$@_$(tier)), \
|
||||||
$(call BUILDSTATUS,SUBTIER_START $@ $(tier) $(if $(filter libs,$@),$(tier_$(tier)_staticdirs)) $(tier_$(tier)_dirs)) \
|
$(call BUILDSTATUS,SUBTIER_START $@ $(tier) $(if $(filter libs,$@),$(tier_$(tier)_staticdirs)) $(tier_$(tier)_dirs)) \
|
||||||
$(if $(filter libs,$@),$(foreach dir, $(tier_$(tier)_staticdirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),,1))) \
|
$(if $(filter libs,$@),$(foreach dir, $(tier_$(tier)_staticdirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),,1))) \
|
||||||
$(foreach dir, $(tier_$(tier)_dirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),$@)) \
|
$(foreach dir, $(tier_$(tier)_dirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),$@)) \
|
||||||
|
@ -41,9 +132,13 @@ endif
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(foreach subtier,export compile libs tools,$(eval $(call CREATE_SUBTIER_TRAVERSAL_RULE,$(subtier))))
|
$(foreach subtier,export libs tools,$(eval $(call CREATE_SUBTIER_TRAVERSAL_RULE,$(subtier))))
|
||||||
|
|
||||||
compile export tools:: $(SUBMAKEFILES)
|
tools export:: $(SUBMAKEFILES)
|
||||||
$(LOOP_OVER_TOOL_DIRS)
|
$(LOOP_OVER_TOOL_DIRS)
|
||||||
|
|
||||||
endif
|
endif # ifdef TIERS
|
||||||
|
|
||||||
|
endif # ifeq ($(EXTERNALLY_MANAGED_MAKE_FILE)_$(NO_RECURSE_MAKELEVEL),_$(MAKELEVEL))
|
||||||
|
|
||||||
|
endif # ifeq (1_.,$(MOZ_PSEUDO_DERECURSE)_$(DEPTH))
|
||||||
|
|
|
@ -695,7 +695,9 @@ SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
|
||||||
ifndef SUPPRESS_DEFAULT_RULES
|
ifndef SUPPRESS_DEFAULT_RULES
|
||||||
default all::
|
default all::
|
||||||
$(MAKE) export
|
$(MAKE) export
|
||||||
|
ifdef MOZ_PSEUDO_DERECURSE
|
||||||
$(MAKE) compile
|
$(MAKE) compile
|
||||||
|
endif
|
||||||
$(MAKE) libs
|
$(MAKE) libs
|
||||||
$(MAKE) tools
|
$(MAKE) tools
|
||||||
endif # SUPPRESS_DEFAULT_RULES
|
endif # SUPPRESS_DEFAULT_RULES
|
||||||
|
|
|
@ -206,7 +206,7 @@ jsconfig_TARGET := export
|
||||||
|
|
||||||
.PHONY: buildffi buildicu
|
.PHONY: buildffi buildicu
|
||||||
buildffi buildicu:
|
buildffi buildicu:
|
||||||
compile:: buildffi buildicu
|
$(if $(MOZ_PSEUDO_DERECURSE),compile,export):: buildffi buildicu
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
|
|
|
@ -181,3 +181,5 @@ if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_SUBST([MOZ_PSEUDO_DERECURSE])
|
||||||
|
|
|
@ -6,15 +6,106 @@ ifndef INCLUDED_RULES_MK
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# The traditional model of directory traversal with make is as follows:
|
||||||
|
# make -C foo
|
||||||
|
# Entering foo
|
||||||
|
# make -C bar
|
||||||
|
# Entering foo/bar
|
||||||
|
# make -C baz
|
||||||
|
# Entering foo/baz
|
||||||
|
# make -C qux
|
||||||
|
# Entering qux
|
||||||
|
#
|
||||||
|
# Pseudo derecurse transforms the above into:
|
||||||
|
# make -C foo
|
||||||
|
# make -C foo/bar
|
||||||
|
# make -C foo/baz
|
||||||
|
# make -C qux
|
||||||
|
|
||||||
|
ifeq (1_.,$(MOZ_PSEUDO_DERECURSE)_$(DEPTH))
|
||||||
|
|
||||||
|
include root.mk
|
||||||
|
|
||||||
|
# Disable build status for mach in top directories without TIERS.
|
||||||
|
# In practice this disables it when recursing under js/src, which confuses mach.
|
||||||
|
ifndef TIERS
|
||||||
|
BUILDSTATUS =
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Main rules (export, compile, libs and tools) call recurse_* rules.
|
||||||
|
# This wrapping is only really useful for build status.
|
||||||
|
compile libs export tools::
|
||||||
|
$(call BUILDSTATUS,TIER_START $@ $($@_subtiers))
|
||||||
|
+$(MAKE) recurse_$@
|
||||||
|
$(call BUILDSTATUS,TIER_FINISH $@)
|
||||||
|
|
||||||
|
# Carefully avoid $(eval) type of rule generation, which makes pymake slower
|
||||||
|
# than necessary.
|
||||||
|
# Get current tier and corresponding subtiers from the data in root.mk.
|
||||||
|
CURRENT_TIER := $(filter $(foreach tier,compile libs export tools,recurse_$(tier)),$(MAKECMDGOALS))
|
||||||
|
ifneq (,$(filter-out 0 1,$(words $(CURRENT_TIER))))
|
||||||
|
$(error $(CURRENT_TIER) not supported on the same make command line)
|
||||||
|
endif
|
||||||
|
CURRENT_TIER := $(subst recurse_,,$(CURRENT_TIER))
|
||||||
|
CURRENT_SUBTIERS := $($(CURRENT_TIER)_subtiers)
|
||||||
|
|
||||||
|
# The rules here are doing directory traversal, so we don't want further
|
||||||
|
# recursion to happen when running make -C subdir $tier. But some make files
|
||||||
|
# further call make -C something else, and sometimes expect recursion to
|
||||||
|
# happen in that case (see browser/metro/locales/Makefile.in for example).
|
||||||
|
# Conveniently, every invocation of make increases MAKELEVEL, so only stop
|
||||||
|
# recursion from happening at current MAKELEVEL + 1.
|
||||||
|
ifdef CURRENT_TIER
|
||||||
|
ifeq (0,$(MAKELEVEL))
|
||||||
|
export NO_RECURSE_MAKELEVEL=1
|
||||||
|
else
|
||||||
|
export NO_RECURSE_MAKELEVEL=$(word $(MAKELEVEL),2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Get all directories traversed for all subtiers in the current tier, or use
|
||||||
|
# directly the $(*_dirs) variables available in root.mk when there is no
|
||||||
|
# TIERS (like for js/src).
|
||||||
|
CURRENT_DIRS := $(or $($(CURRENT_TIER)_dirs),$(foreach subtier,$(CURRENT_SUBTIERS),$($(CURRENT_TIER)_subtier_$(subtier))))
|
||||||
|
|
||||||
|
# Subtier delimiter rules
|
||||||
|
$(addprefix subtiers/,$(addsuffix _start/$(CURRENT_TIER),$(CURRENT_SUBTIERS))): subtiers/%_start/$(CURRENT_TIER):
|
||||||
|
$(call BUILDSTATUS,SUBTIER_START $(CURRENT_TIER) $* $(if $(BUG_915535_FIXED),$($(CURRENT_TIER)_subtier_$*)))
|
||||||
|
|
||||||
|
$(addprefix subtiers/,$(addsuffix _finish/$(CURRENT_TIER),$(CURRENT_SUBTIERS))): subtiers/%_finish/$(CURRENT_TIER):
|
||||||
|
$(call BUILDSTATUS,SUBTIER_FINISH $(CURRENT_TIER) $*)
|
||||||
|
|
||||||
|
# Recursion rule for all directories traversed for all subtiers in the
|
||||||
|
# current tier.
|
||||||
|
# root.mk defines subtier_of_* variables, that map a normalized subdir path to
|
||||||
|
# a subtier name (e.g. subtier_of_memory_jemalloc = base)
|
||||||
|
$(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS)): %/$(CURRENT_TIER):
|
||||||
|
ifdef BUG_915535_FIXED
|
||||||
|
$(call BUILDSTATUS,TIERDIR_START $(CURRENT_TIER) $(subtier_of_$(subst /,_,$*)) $*)
|
||||||
|
endif
|
||||||
|
+@$(MAKE) -C $* $(if $(filter $*,$(tier_$(subtier_of_$(subst /,_,$*))_staticdirs)),,$(CURRENT_TIER))
|
||||||
|
ifdef BUG_915535_FIXED
|
||||||
|
$(call BUILDSTATUS,TIERDIR_FINISH $(CURRENT_TIER) $(subtier_of_$(subst /,_,$*)) $*)
|
||||||
|
endif
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
# Don't recurse if MAKELEVEL is NO_RECURSE_MAKELEVEL as defined above, but
|
||||||
|
# still recurse for externally managed make files (gyp-generated ones).
|
||||||
|
ifeq ($(EXTERNALLY_MANAGED_MAKE_FILE)_$(NO_RECURSE_MAKELEVEL),_$(MAKELEVEL))
|
||||||
|
|
||||||
|
compile libs export tools::
|
||||||
|
|
||||||
|
else
|
||||||
#########################
|
#########################
|
||||||
# Tier traversal handling
|
# Tier traversal handling
|
||||||
#########################
|
#########################
|
||||||
|
|
||||||
ifdef TIERS
|
ifdef TIERS
|
||||||
|
|
||||||
compile libs export tools::
|
libs export tools::
|
||||||
$(call BUILDSTATUS,TIER_START $@ $(filter-out $(if $(filter export,$@),,precompile),$(TIERS)))
|
$(call BUILDSTATUS,TIER_START $@ $(filter-out $(if $(filter export,$@),,precompile),$(TIERS)))
|
||||||
$(foreach tier,$(TIERS), $(if $(filter-out compile_precompile libs_precompile tools_precompile,$@_$(tier)), \
|
$(foreach tier,$(TIERS), $(if $(filter-out libs_precompile tools_precompile,$@_$(tier)), \
|
||||||
$(call BUILDSTATUS,SUBTIER_START $@ $(tier) $(if $(filter libs,$@),$(tier_$(tier)_staticdirs)) $(tier_$(tier)_dirs)) \
|
$(call BUILDSTATUS,SUBTIER_START $@ $(tier) $(if $(filter libs,$@),$(tier_$(tier)_staticdirs)) $(tier_$(tier)_dirs)) \
|
||||||
$(if $(filter libs,$@),$(foreach dir, $(tier_$(tier)_staticdirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),,1))) \
|
$(if $(filter libs,$@),$(foreach dir, $(tier_$(tier)_staticdirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),,1))) \
|
||||||
$(foreach dir, $(tier_$(tier)_dirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),$@)) \
|
$(foreach dir, $(tier_$(tier)_dirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),$@)) \
|
||||||
|
@ -41,9 +132,13 @@ endif
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(foreach subtier,export compile libs tools,$(eval $(call CREATE_SUBTIER_TRAVERSAL_RULE,$(subtier))))
|
$(foreach subtier,export libs tools,$(eval $(call CREATE_SUBTIER_TRAVERSAL_RULE,$(subtier))))
|
||||||
|
|
||||||
compile export tools:: $(SUBMAKEFILES)
|
tools export:: $(SUBMAKEFILES)
|
||||||
$(LOOP_OVER_TOOL_DIRS)
|
$(LOOP_OVER_TOOL_DIRS)
|
||||||
|
|
||||||
endif
|
endif # ifdef TIERS
|
||||||
|
|
||||||
|
endif # ifeq ($(EXTERNALLY_MANAGED_MAKE_FILE)_$(NO_RECURSE_MAKELEVEL),_$(MAKELEVEL))
|
||||||
|
|
||||||
|
endif # ifeq (1_.,$(MOZ_PSEUDO_DERECURSE)_$(DEPTH))
|
||||||
|
|
|
@ -695,7 +695,9 @@ SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
|
||||||
ifndef SUPPRESS_DEFAULT_RULES
|
ifndef SUPPRESS_DEFAULT_RULES
|
||||||
default all::
|
default all::
|
||||||
$(MAKE) export
|
$(MAKE) export
|
||||||
|
ifdef MOZ_PSEUDO_DERECURSE
|
||||||
$(MAKE) compile
|
$(MAKE) compile
|
||||||
|
endif
|
||||||
$(MAKE) libs
|
$(MAKE) libs
|
||||||
$(MAKE) tools
|
$(MAKE) tools
|
||||||
endif # SUPPRESS_DEFAULT_RULES
|
endif # SUPPRESS_DEFAULT_RULES
|
||||||
|
|
|
@ -9,6 +9,8 @@ import logging
|
||||||
import os
|
import os
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from mozpack.copier import FilePurger
|
from mozpack.copier import FilePurger
|
||||||
from mozpack.manifests import (
|
from mozpack.manifests import (
|
||||||
InstallManifest,
|
InstallManifest,
|
||||||
|
@ -35,6 +37,7 @@ from ..frontend.data import (
|
||||||
WebIDLFile,
|
WebIDLFile,
|
||||||
)
|
)
|
||||||
from ..util import FileAvoidWrite
|
from ..util import FileAvoidWrite
|
||||||
|
from ..makeutil import Makefile
|
||||||
|
|
||||||
|
|
||||||
class BackendMakeFile(object):
|
class BackendMakeFile(object):
|
||||||
|
@ -66,6 +69,7 @@ class BackendMakeFile(object):
|
||||||
def __init__(self, srcdir, objdir, environment):
|
def __init__(self, srcdir, objdir, environment):
|
||||||
self.srcdir = srcdir
|
self.srcdir = srcdir
|
||||||
self.objdir = objdir
|
self.objdir = objdir
|
||||||
|
self.relobjdir = objdir[len(environment.topobjdir) + 1:]
|
||||||
self.environment = environment
|
self.environment = environment
|
||||||
self.path = os.path.join(objdir, 'backend.mk')
|
self.path = os.path.join(objdir, 'backend.mk')
|
||||||
|
|
||||||
|
@ -107,6 +111,135 @@ class BackendMakeFile(object):
|
||||||
return self.fh.close()
|
return self.fh.close()
|
||||||
|
|
||||||
|
|
||||||
|
class RecursiveMakeTraversal(object):
|
||||||
|
"""
|
||||||
|
Helper class to keep track of how the "traditional" recursive make backend
|
||||||
|
recurses subdirectories. This is useful until all adhoc rules are removed
|
||||||
|
from Makefiles.
|
||||||
|
|
||||||
|
Each directory may have one or more types of subdirectories:
|
||||||
|
- parallel
|
||||||
|
- static
|
||||||
|
- (normal) dirs
|
||||||
|
- tests
|
||||||
|
- tools
|
||||||
|
|
||||||
|
The "traditional" recursive make backend recurses through those by first
|
||||||
|
building the current directory, followed by parallel directories (in
|
||||||
|
parallel), then static directories, dirs, tests and tools (all
|
||||||
|
sequentially).
|
||||||
|
"""
|
||||||
|
SubDirectoryCategories = ['parallel', 'static', 'dirs', 'tests', 'tools']
|
||||||
|
SubDirectoriesTuple = namedtuple('SubDirectories', SubDirectoryCategories)
|
||||||
|
class SubDirectories(SubDirectoriesTuple):
|
||||||
|
def __new__(self):
|
||||||
|
return RecursiveMakeTraversal.SubDirectoriesTuple.__new__(self, [], [], [], [], [])
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._traversal = {}
|
||||||
|
|
||||||
|
def add(self, dir, **kargs):
|
||||||
|
"""
|
||||||
|
Function signature is, in fact:
|
||||||
|
def add(self, dir, parallel=[], static=[], dirs=[],
|
||||||
|
tests=[], tools=[])
|
||||||
|
but it's done with **kargs to avoid repetitive code.
|
||||||
|
|
||||||
|
Adds a directory to traversal, registering its subdirectories,
|
||||||
|
sorted by categories. If the directory was already added to
|
||||||
|
traversal, adds the new subdirectories to the already known lists.
|
||||||
|
"""
|
||||||
|
subdirs = self._traversal.setdefault(dir, self.SubDirectories())
|
||||||
|
for key, value in kargs.items():
|
||||||
|
assert(key in self.SubDirectoryCategories)
|
||||||
|
getattr(subdirs, key).extend(value)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def default_filter(current, subdirs):
|
||||||
|
"""
|
||||||
|
Default filter for use with compute_dependencies and traverse.
|
||||||
|
"""
|
||||||
|
return current, subdirs.parallel, \
|
||||||
|
subdirs.static + subdirs.dirs + subdirs.tests + subdirs.tools
|
||||||
|
|
||||||
|
def call_filter(self, current, filter):
|
||||||
|
"""
|
||||||
|
Helper function to call a filter from compute_dependencies and
|
||||||
|
traverse.
|
||||||
|
"""
|
||||||
|
return filter(current, self._traversal.get(current,
|
||||||
|
self.SubDirectories()))
|
||||||
|
|
||||||
|
def compute_dependencies(self, filter=None):
|
||||||
|
"""
|
||||||
|
Compute make dependencies corresponding to the registered directory
|
||||||
|
traversal.
|
||||||
|
|
||||||
|
filter is a function with the following signature:
|
||||||
|
def filter(current, subdirs)
|
||||||
|
where current is the directory being traversed, and subdirs the
|
||||||
|
SubDirectories instance corresponding to it.
|
||||||
|
The filter function returns a tuple (filtered_current, filtered_parallel,
|
||||||
|
filtered_dirs) where filtered_current is either current or None if
|
||||||
|
the current directory is to be skipped, and filtered_parallel and
|
||||||
|
filtered_dirs are lists of parallel directories and sequential
|
||||||
|
directories, which can be rearranged from whatever is given in the
|
||||||
|
SubDirectories members.
|
||||||
|
|
||||||
|
The default filter corresponds to a default recursive traversal.
|
||||||
|
"""
|
||||||
|
filter = filter or self.default_filter
|
||||||
|
|
||||||
|
deps = {}
|
||||||
|
|
||||||
|
def recurse(start_node, prev_nodes=None):
|
||||||
|
current, parallel, sequential = self.call_filter(start_node, filter)
|
||||||
|
if current is not None:
|
||||||
|
if start_node != '':
|
||||||
|
deps[start_node] = prev_nodes
|
||||||
|
prev_nodes = (start_node,)
|
||||||
|
if not start_node in self._traversal:
|
||||||
|
return prev_nodes
|
||||||
|
parallel_nodes = []
|
||||||
|
for node in parallel:
|
||||||
|
nodes = recurse(node, prev_nodes)
|
||||||
|
if nodes != ('',):
|
||||||
|
parallel_nodes.extend(nodes)
|
||||||
|
if parallel_nodes:
|
||||||
|
prev_nodes = tuple(parallel_nodes)
|
||||||
|
for dir in sequential:
|
||||||
|
prev_nodes = recurse(dir, prev_nodes)
|
||||||
|
return prev_nodes
|
||||||
|
|
||||||
|
return recurse(''), deps
|
||||||
|
|
||||||
|
def traverse(self, start, filter=None):
|
||||||
|
"""
|
||||||
|
Iterate over the filtered subdirectories, following the traditional
|
||||||
|
make traversal order.
|
||||||
|
"""
|
||||||
|
if filter is None:
|
||||||
|
filter = self.default_filter
|
||||||
|
|
||||||
|
current, parallel, sequential = self.call_filter(start, filter)
|
||||||
|
if current is not None:
|
||||||
|
yield start
|
||||||
|
if not start in self._traversal:
|
||||||
|
return
|
||||||
|
for node in parallel:
|
||||||
|
for n in self.traverse(node, filter):
|
||||||
|
yield n
|
||||||
|
for dir in sequential:
|
||||||
|
for d in self.traverse(dir, filter):
|
||||||
|
yield d
|
||||||
|
|
||||||
|
def get_subdirs(self, dir):
|
||||||
|
"""
|
||||||
|
Returns all direct subdirectories under the given directory.
|
||||||
|
"""
|
||||||
|
return self._traversal.get(dir, self.SubDirectories())
|
||||||
|
|
||||||
|
|
||||||
class RecursiveMakeBackend(CommonBackend):
|
class RecursiveMakeBackend(CommonBackend):
|
||||||
"""Backend that integrates with the existing recursive make build system.
|
"""Backend that integrates with the existing recursive make build system.
|
||||||
|
|
||||||
|
@ -159,6 +292,8 @@ class RecursiveMakeBackend(CommonBackend):
|
||||||
'xpidl',
|
'xpidl',
|
||||||
]}
|
]}
|
||||||
|
|
||||||
|
self._traversal = RecursiveMakeTraversal()
|
||||||
|
|
||||||
def _update_from_avoid_write(self, result):
|
def _update_from_avoid_write(self, result):
|
||||||
existed, updated = result
|
existed, updated = result
|
||||||
|
|
||||||
|
@ -249,9 +384,108 @@ class RecursiveMakeBackend(CommonBackend):
|
||||||
|
|
||||||
self._backend_files[obj.srcdir] = backend_file
|
self._backend_files[obj.srcdir] = backend_file
|
||||||
|
|
||||||
|
def _fill_root_mk(self):
|
||||||
|
"""
|
||||||
|
Create two files, root.mk and root-deps.mk, the first containing
|
||||||
|
convenience variables, and the other dependency definitions for a
|
||||||
|
hopefully proper directory traversal.
|
||||||
|
"""
|
||||||
|
# Skip static dirs during export traversal
|
||||||
|
def export_filter(current, subdirs):
|
||||||
|
return current, subdirs.parallel, \
|
||||||
|
subdirs.dirs + subdirs.tests + subdirs.tools
|
||||||
|
|
||||||
|
# compile and tools tiers use the same traversal as export, but skip
|
||||||
|
# precompile.
|
||||||
|
def other_filter(current, subdirs):
|
||||||
|
if current == 'subtiers/precompile':
|
||||||
|
return None, [], []
|
||||||
|
return export_filter(current, subdirs)
|
||||||
|
|
||||||
|
# Skip tools dirs during libs traversal
|
||||||
|
def libs_filter(current, subdirs):
|
||||||
|
if current == 'subtiers/precompile':
|
||||||
|
return None, [], []
|
||||||
|
return current, subdirs.parallel, \
|
||||||
|
subdirs.static + subdirs.dirs + subdirs.tests
|
||||||
|
|
||||||
|
# compile and tools tiers use the same traversal as export
|
||||||
|
filters = {
|
||||||
|
'export': export_filter,
|
||||||
|
'compile': other_filter,
|
||||||
|
'libs': libs_filter,
|
||||||
|
'tools': other_filter,
|
||||||
|
}
|
||||||
|
|
||||||
|
root_deps_mk = Makefile()
|
||||||
|
|
||||||
|
# Fill the dependencies for traversal of each tier.
|
||||||
|
for tier, filter in filters.items():
|
||||||
|
main, all_deps = \
|
||||||
|
self._traversal.compute_dependencies(filter)
|
||||||
|
for dir, deps in all_deps.items():
|
||||||
|
rule = root_deps_mk.create_rule(['%s/%s' % (dir, tier)])
|
||||||
|
if deps is not None:
|
||||||
|
rule.add_dependencies('%s/%s' % (d, tier) for d in deps if d)
|
||||||
|
root_deps_mk.create_rule(['recurse_%s' % tier]) \
|
||||||
|
.add_dependencies('%s/%s' % (d, tier) for d in main)
|
||||||
|
|
||||||
|
root_mk = Makefile()
|
||||||
|
|
||||||
|
# Fill root.mk with the convenience variables.
|
||||||
|
for tier, filter in filters.items() + [('all', self._traversal.default_filter)]:
|
||||||
|
# Gather filtered subtiers for the given tier
|
||||||
|
all_direct_subdirs = reduce(lambda x, y: x + y,
|
||||||
|
self._traversal.get_subdirs(''), [])
|
||||||
|
direct_subdirs = [d for d in all_direct_subdirs
|
||||||
|
if filter(d, self._traversal.get_subdirs(d))[0]]
|
||||||
|
subtiers = [d.replace('subtiers/', '') for d in direct_subdirs
|
||||||
|
if d.startswith('subtiers/')]
|
||||||
|
|
||||||
|
if tier != 'all':
|
||||||
|
# Gather filtered directories for the given tier
|
||||||
|
dirs = [d for d in direct_subdirs if not d.startswith('subtiers/')]
|
||||||
|
if dirs:
|
||||||
|
# For build systems without tiers (js/src), output a list
|
||||||
|
# of directories for each tier.
|
||||||
|
root_mk.add_statement('%s_dirs := %s' % (tier, ' '.join(dirs)))
|
||||||
|
continue
|
||||||
|
if subtiers:
|
||||||
|
# Output the list of filtered subtiers for the given tier.
|
||||||
|
root_mk.add_statement('%s_subtiers := %s' % (tier, ' '.join(subtiers)))
|
||||||
|
|
||||||
|
for subtier in subtiers:
|
||||||
|
# subtier_dirs[0] is 'subtiers/%s_start' % subtier, skip it
|
||||||
|
subtier_dirs = list(self._traversal.traverse('subtiers/%s_start' % subtier, filter))[1:]
|
||||||
|
if tier == 'all':
|
||||||
|
for dir in subtier_dirs:
|
||||||
|
# Output convenience variables to be able to map directories
|
||||||
|
# to subtier names from Makefiles.
|
||||||
|
stamped = dir.replace('/', '_')
|
||||||
|
root_mk.add_statement('subtier_of_%s := %s' % (stamped, subtier))
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Output the list of filtered directories for each tier/subtier
|
||||||
|
# pair.
|
||||||
|
root_mk.add_statement('%s_subtier_%s := %s' % (tier, subtier, ' '.join(subtier_dirs)))
|
||||||
|
|
||||||
|
root_mk.add_statement('$(call include_deps,root-deps.mk)')
|
||||||
|
|
||||||
|
root = FileAvoidWrite(
|
||||||
|
os.path.join(self.environment.topobjdir, 'root.mk'))
|
||||||
|
root_deps = FileAvoidWrite(
|
||||||
|
os.path.join(self.environment.topobjdir, 'root-deps.mk'))
|
||||||
|
root_mk.dump(root, removal_guard=False)
|
||||||
|
root_deps_mk.dump(root_deps, removal_guard=False)
|
||||||
|
self._update_from_avoid_write(root.close())
|
||||||
|
self._update_from_avoid_write(root_deps.close())
|
||||||
|
|
||||||
|
|
||||||
def consume_finished(self):
|
def consume_finished(self):
|
||||||
CommonBackend.consume_finished(self)
|
CommonBackend.consume_finished(self)
|
||||||
|
|
||||||
|
self._fill_root_mk()
|
||||||
|
|
||||||
for srcdir in sorted(self._backend_files.keys()):
|
for srcdir in sorted(self._backend_files.keys()):
|
||||||
bf = self._backend_files[srcdir]
|
bf = self._backend_files[srcdir]
|
||||||
|
|
||||||
|
@ -365,41 +599,82 @@ class RecursiveMakeBackend(CommonBackend):
|
||||||
"""Process a data.DirectoryTraversal instance."""
|
"""Process a data.DirectoryTraversal instance."""
|
||||||
fh = backend_file.fh
|
fh = backend_file.fh
|
||||||
|
|
||||||
|
def relativize(dirs):
|
||||||
|
return [mozpath.normpath(mozpath.join(backend_file.relobjdir, d))
|
||||||
|
for d in dirs]
|
||||||
|
|
||||||
for tier, dirs in obj.tier_dirs.iteritems():
|
for tier, dirs in obj.tier_dirs.iteritems():
|
||||||
fh.write('TIERS += %s\n' % tier)
|
fh.write('TIERS += %s\n' % tier)
|
||||||
|
# For pseudo derecursification, subtiers are treated as pseudo
|
||||||
|
# directories, with a special hierarchy:
|
||||||
|
# - subtier1 - subtier1_start - dirA - dirAA
|
||||||
|
# | | | + dirAB
|
||||||
|
# | | ...
|
||||||
|
# | | + dirB
|
||||||
|
# | + subtier1_finish
|
||||||
|
# + subtier2 - subtier2_start ...
|
||||||
|
# ... + subtier2_finish
|
||||||
|
self._traversal.add('subtiers/%s' % tier,
|
||||||
|
dirs=['subtiers/%s_start' % tier,
|
||||||
|
'subtiers/%s_finish' % tier])
|
||||||
|
|
||||||
if dirs:
|
if dirs:
|
||||||
fh.write('tier_%s_dirs += %s\n' % (tier, ' '.join(dirs)))
|
fh.write('tier_%s_dirs += %s\n' % (tier, ' '.join(dirs)))
|
||||||
fh.write('DIRS += $(tier_%s_dirs)\n' % tier)
|
fh.write('DIRS += $(tier_%s_dirs)\n' % tier)
|
||||||
|
self._traversal.add('subtiers/%s_start' % tier,
|
||||||
|
dirs=relativize(dirs))
|
||||||
|
|
||||||
# tier_static_dirs should have the same keys as tier_dirs.
|
# tier_static_dirs should have the same keys as tier_dirs.
|
||||||
if obj.tier_static_dirs[tier]:
|
if obj.tier_static_dirs[tier]:
|
||||||
fh.write('tier_%s_staticdirs += %s\n' % (
|
fh.write('tier_%s_staticdirs += %s\n' % (
|
||||||
tier, ' '.join(obj.tier_static_dirs[tier])))
|
tier, ' '.join(obj.tier_static_dirs[tier])))
|
||||||
|
self._traversal.add('subtiers/%s_start' % tier,
|
||||||
|
static=relativize(obj.tier_static_dirs[tier]))
|
||||||
|
|
||||||
|
self._traversal.add('subtiers/%s_start' % tier)
|
||||||
|
self._traversal.add('subtiers/%s_finish' % tier)
|
||||||
|
self._traversal.add('', dirs=['subtiers/%s' % tier])
|
||||||
|
|
||||||
if obj.dirs:
|
if obj.dirs:
|
||||||
fh.write('DIRS := %s\n' % ' '.join(obj.dirs))
|
fh.write('DIRS := %s\n' % ' '.join(obj.dirs))
|
||||||
|
self._traversal.add(backend_file.relobjdir, dirs=relativize(obj.dirs))
|
||||||
|
|
||||||
if obj.parallel_dirs:
|
if obj.parallel_dirs:
|
||||||
fh.write('PARALLEL_DIRS := %s\n' % ' '.join(obj.parallel_dirs))
|
fh.write('PARALLEL_DIRS := %s\n' % ' '.join(obj.parallel_dirs))
|
||||||
|
self._traversal.add(backend_file.relobjdir,
|
||||||
|
parallel=relativize(obj.parallel_dirs))
|
||||||
|
|
||||||
if obj.tool_dirs:
|
if obj.tool_dirs:
|
||||||
fh.write('TOOL_DIRS := %s\n' % ' '.join(obj.tool_dirs))
|
fh.write('TOOL_DIRS := %s\n' % ' '.join(obj.tool_dirs))
|
||||||
|
self._traversal.add(backend_file.relobjdir,
|
||||||
|
tools=relativize(obj.tool_dirs))
|
||||||
|
|
||||||
if obj.test_dirs:
|
if obj.test_dirs:
|
||||||
fh.write('TEST_DIRS := %s\n' % ' '.join(obj.test_dirs))
|
fh.write('TEST_DIRS := %s\n' % ' '.join(obj.test_dirs))
|
||||||
|
self._traversal.add(backend_file.relobjdir,
|
||||||
|
tests=relativize(obj.test_dirs))
|
||||||
|
|
||||||
if obj.test_tool_dirs and \
|
if obj.test_tool_dirs and \
|
||||||
self.environment.substs.get('ENABLE_TESTS', False):
|
self.environment.substs.get('ENABLE_TESTS', False):
|
||||||
|
|
||||||
fh.write('TOOL_DIRS += %s\n' % ' '.join(obj.test_tool_dirs))
|
fh.write('TOOL_DIRS += %s\n' % ' '.join(obj.test_tool_dirs))
|
||||||
|
self._traversal.add(backend_file.relobjdir,
|
||||||
|
tools=relativize(obj.test_tool_dirs))
|
||||||
|
|
||||||
if len(obj.external_make_dirs):
|
if len(obj.external_make_dirs):
|
||||||
fh.write('DIRS += %s\n' % ' '.join(obj.external_make_dirs))
|
fh.write('DIRS += %s\n' % ' '.join(obj.external_make_dirs))
|
||||||
|
self._traversal.add(backend_file.relobjdir,
|
||||||
|
dirs=relativize(obj.external_make_dirs))
|
||||||
|
|
||||||
if len(obj.parallel_external_make_dirs):
|
if len(obj.parallel_external_make_dirs):
|
||||||
fh.write('PARALLEL_DIRS += %s\n' %
|
fh.write('PARALLEL_DIRS += %s\n' %
|
||||||
' '.join(obj.parallel_external_make_dirs))
|
' '.join(obj.parallel_external_make_dirs))
|
||||||
|
self._traversal.add(backend_file.relobjdir,
|
||||||
|
parallel=relativize(obj.parallel_external_make_dirs))
|
||||||
|
|
||||||
|
# The directory needs to be registered whether subdirectories have been
|
||||||
|
# registered or not.
|
||||||
|
self._traversal.add(backend_file.relobjdir)
|
||||||
|
|
||||||
if obj.is_tool_dir:
|
if obj.is_tool_dir:
|
||||||
fh.write('IS_TOOL_DIR := 1\n')
|
fh.write('IS_TOOL_DIR := 1\n')
|
||||||
|
|
|
@ -5,19 +5,148 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import unittest
|
||||||
|
|
||||||
from mozpack.manifests import (
|
from mozpack.manifests import (
|
||||||
InstallManifest,
|
InstallManifest,
|
||||||
)
|
)
|
||||||
from mozunit import main
|
from mozunit import main
|
||||||
|
|
||||||
from mozbuild.backend.recursivemake import RecursiveMakeBackend
|
from mozbuild.backend.recursivemake import (
|
||||||
|
RecursiveMakeBackend,
|
||||||
|
RecursiveMakeTraversal,
|
||||||
|
)
|
||||||
from mozbuild.frontend.emitter import TreeMetadataEmitter
|
from mozbuild.frontend.emitter import TreeMetadataEmitter
|
||||||
from mozbuild.frontend.reader import BuildReader
|
from mozbuild.frontend.reader import BuildReader
|
||||||
|
|
||||||
from mozbuild.test.backend.common import BackendTester
|
from mozbuild.test.backend.common import BackendTester
|
||||||
|
|
||||||
|
|
||||||
|
class TestRecursiveMakeTraversal(unittest.TestCase):
|
||||||
|
def test_traversal(self):
|
||||||
|
traversal = RecursiveMakeTraversal()
|
||||||
|
traversal.add('', dirs=['A', 'B', 'C'])
|
||||||
|
traversal.add('', dirs=['D'])
|
||||||
|
traversal.add('A')
|
||||||
|
traversal.add('B', dirs=['E', 'F'])
|
||||||
|
traversal.add('C', parallel=['G', 'H'])
|
||||||
|
traversal.add('D', parallel=['I'], dirs=['K'])
|
||||||
|
traversal.add('D', parallel=['J'], dirs=['L'])
|
||||||
|
traversal.add('E')
|
||||||
|
traversal.add('F')
|
||||||
|
traversal.add('G')
|
||||||
|
traversal.add('H')
|
||||||
|
traversal.add('I', dirs=['M', 'N'])
|
||||||
|
traversal.add('J', parallel=['O', 'P'])
|
||||||
|
traversal.add('K', parallel=['Q', 'R'])
|
||||||
|
traversal.add('L', dirs=['S'])
|
||||||
|
traversal.add('M')
|
||||||
|
traversal.add('N', dirs=['T'])
|
||||||
|
traversal.add('O')
|
||||||
|
traversal.add('P', parallel=['U'])
|
||||||
|
traversal.add('Q')
|
||||||
|
traversal.add('R', dirs=['V'])
|
||||||
|
traversal.add('S', dirs=['W'])
|
||||||
|
traversal.add('T')
|
||||||
|
traversal.add('U')
|
||||||
|
traversal.add('V')
|
||||||
|
traversal.add('W', dirs=['X'])
|
||||||
|
traversal.add('X')
|
||||||
|
|
||||||
|
start, deps = traversal.compute_dependencies()
|
||||||
|
self.assertEqual(start, ('X',))
|
||||||
|
self.assertEqual(deps, {
|
||||||
|
'A': ('',),
|
||||||
|
'B': ('A',),
|
||||||
|
'C': ('F',),
|
||||||
|
'D': ('G', 'H'),
|
||||||
|
'E': ('B',),
|
||||||
|
'F': ('E',),
|
||||||
|
'G': ('C',),
|
||||||
|
'H': ('C',),
|
||||||
|
'I': ('D',),
|
||||||
|
'J': ('D',),
|
||||||
|
'K': ('T', 'O', 'U'),
|
||||||
|
'L': ('Q', 'V'),
|
||||||
|
'M': ('I',),
|
||||||
|
'N': ('M',),
|
||||||
|
'O': ('J',),
|
||||||
|
'P': ('J',),
|
||||||
|
'Q': ('K',),
|
||||||
|
'R': ('K',),
|
||||||
|
'S': ('L',),
|
||||||
|
'T': ('N',),
|
||||||
|
'U': ('P',),
|
||||||
|
'V': ('R',),
|
||||||
|
'W': ('S',),
|
||||||
|
'X': ('W',),
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertEqual(list(traversal.traverse('')),
|
||||||
|
['', 'A', 'B', 'E', 'F', 'C', 'G', 'H', 'D', 'I',
|
||||||
|
'M', 'N', 'T', 'J', 'O', 'P', 'U', 'K', 'Q', 'R',
|
||||||
|
'V', 'L', 'S', 'W', 'X'])
|
||||||
|
|
||||||
|
self.assertEqual(list(traversal.traverse('C')),
|
||||||
|
['C', 'G', 'H'])
|
||||||
|
|
||||||
|
def test_traversal_2(self):
|
||||||
|
traversal = RecursiveMakeTraversal()
|
||||||
|
traversal.add('', dirs=['A', 'B', 'C'])
|
||||||
|
traversal.add('A')
|
||||||
|
traversal.add('B', static=['D'], dirs=['E', 'F'])
|
||||||
|
traversal.add('C', parallel=['G', 'H'], dirs=['I'])
|
||||||
|
# Don't register D
|
||||||
|
traversal.add('E')
|
||||||
|
traversal.add('F')
|
||||||
|
traversal.add('G')
|
||||||
|
traversal.add('H')
|
||||||
|
traversal.add('I')
|
||||||
|
|
||||||
|
start, deps = traversal.compute_dependencies()
|
||||||
|
self.assertEqual(start, ('I',))
|
||||||
|
self.assertEqual(deps, {
|
||||||
|
'A': ('',),
|
||||||
|
'B': ('A',),
|
||||||
|
'C': ('F',),
|
||||||
|
'D': ('B',),
|
||||||
|
'E': ('D',),
|
||||||
|
'F': ('E',),
|
||||||
|
'G': ('C',),
|
||||||
|
'H': ('C',),
|
||||||
|
'I': ('G', 'H'),
|
||||||
|
})
|
||||||
|
|
||||||
|
def test_traversal_filter(self):
|
||||||
|
traversal = RecursiveMakeTraversal()
|
||||||
|
traversal.add('', dirs=['A', 'B', 'C'])
|
||||||
|
traversal.add('A')
|
||||||
|
traversal.add('B', static=['D'], dirs=['E', 'F'])
|
||||||
|
traversal.add('C', parallel=['G', 'H'], dirs=['I'])
|
||||||
|
traversal.add('D')
|
||||||
|
traversal.add('E')
|
||||||
|
traversal.add('F')
|
||||||
|
traversal.add('G')
|
||||||
|
traversal.add('H')
|
||||||
|
traversal.add('I')
|
||||||
|
|
||||||
|
def filter(current, subdirs):
|
||||||
|
if current == 'B':
|
||||||
|
current = None
|
||||||
|
return current, subdirs.parallel, subdirs.dirs
|
||||||
|
|
||||||
|
start, deps = traversal.compute_dependencies(filter)
|
||||||
|
self.assertEqual(start, ('I',))
|
||||||
|
self.assertEqual(deps, {
|
||||||
|
'A': ('',),
|
||||||
|
'C': ('F',),
|
||||||
|
'E': ('A',),
|
||||||
|
'F': ('E',),
|
||||||
|
'G': ('C',),
|
||||||
|
'H': ('C',),
|
||||||
|
'I': ('G', 'H'),
|
||||||
|
})
|
||||||
|
|
||||||
class TestRecursiveMakeBackend(BackendTester):
|
class TestRecursiveMakeBackend(BackendTester):
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
"""Ensure the RecursiveMakeBackend works without error."""
|
"""Ensure the RecursiveMakeBackend works without error."""
|
||||||
|
|
Загрузка…
Ссылка в новой задаче