Bug 1043802 - Remove TOOLS_DIRS and TEST_TOOLS_DIRS. r=gps
authorMike Hommey <mh+mozilla@glandium.org>
Tue, 29 Jul 2014 08:55:55 +0900
changeset 196402 ac2f9ea38a5642c7ec680b188441dabb8d0d89bd
parent 196401 87663bfc852445a67a3a637ba68df039e3777cc3
child 196403 22850cacf0f9527a7408375aa9270ebe835175a4
push id46877
push usermh@glandium.org
push dateTue, 29 Jul 2014 00:03:39 +0000
treeherdermozilla-inbound@dd8b06f73253 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1043802
milestone34.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 1043802 - Remove TOOLS_DIRS and TEST_TOOLS_DIRS. r=gps
config/makefiles/debugmake.mk
config/recurse.mk
config/rules.mk
content/base/moz.build
content/base/test/moz.build
content/media/moz.build
content/media/webaudio/moz.build
content/moz.build
dom/audiochannel/moz.build
dom/canvas/moz.build
dom/smil/moz.build
editor/txmgr/moz.build
extensions/cookie/moz.build
gfx/moz.build
intl/lwbrk/moz.build
intl/strres/moz.build
intl/uconv/moz.build
intl/unicharutil/moz.build
ipc/ipdl/test/cxx/moz.build
ipc/moz.build
js/xpconnect/moz.build
js/xpconnect/tests/moz.build
layout/moz.build
layout/style/moz.build
media/libcubeb/moz.build
memory/mozalloc/moz.build
modules/libjar/moz.build
modules/libjar/test/moz.build
modules/libpref/moz.build
mozglue/linker/moz.build
mozglue/moz.build
netwerk/moz.build
netwerk/streamconv/moz.build
netwerk/test/moz.build
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/frontend/reader.py
python/mozbuild/mozbuild/frontend/sandbox_symbols.py
python/mozbuild/mozbuild/test/frontend/data/reader-error-traversal-tools/foo/biz/moz.build
python/mozbuild/mozbuild/test/frontend/data/reader-error-traversal-tools/foo/moz.build
python/mozbuild/mozbuild/test/frontend/data/reader-error-traversal-tools/moz.build
python/mozbuild/mozbuild/test/frontend/data/traversal-all-vars/moz.build
python/mozbuild/mozbuild/test/frontend/data/traversal-all-vars/test_tool/moz.build
python/mozbuild/mozbuild/test/frontend/data/traversal-all-vars/tool/moz.build
python/mozbuild/mozbuild/test/frontend/test_emitter.py
python/mozbuild/mozbuild/test/frontend/test_reader.py
rdf/moz.build
rdf/tests/moz.build
security/manager/ssl/tests/moz.build
startupcache/moz.build
storage/moz.build
toolkit/components/places/tests/moz.build
toolkit/components/url-classifier/moz.build
toolkit/crashreporter/moz.build
widget/moz.build
xpcom/moz.build
xpcom/sample/moz.build
xpcom/tests/moz.build
--- a/config/makefiles/debugmake.mk
+++ b/config/makefiles/debugmake.mk
@@ -58,17 +58,16 @@ ifneq (,$(filter $(PROGRAM) $(HOST_PROGR
 		STATIC_LIBS \
 		EXTRA_DSO_LDOPTS \
 		DEPENDENT_LIBS \
 	)
 	@echo --------------------------------------------------------------------------------
 endif
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
 
 showbuild:
 	$(call print_vars,\
 		MOZ_BUILD_ROOT \
 		MOZ_WIDGET_TOOLKIT \
 		CC \
 		CXX \
 		CCC \
--- a/config/recurse.mk
+++ b/config/recurse.mk
@@ -96,26 +96,26 @@ else
 
 ifndef STAMP_TOUCH
 .PHONY: $(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS))
 endif
 
 # Dummy rules for possibly inexisting dependencies for the above tier targets
 $(addsuffix /Makefile,$(CURRENT_DIRS)) $(addsuffix /backend.mk,$(CURRENT_DIRS)):
 
+ifeq ($(CURRENT_TIER),export)
 # At least build/export requires config/export for buildid, but who knows what
 # else, so keep this global dependency to make config/export first for now.
 $(addsuffix /$(CURRENT_TIER),$(filter-out config,$(CURRENT_DIRS))): config/$(CURRENT_TIER)
 
 # The export tier requires nsinstall, which is built from config. So every
 # subdirectory traversal needs to happen after building nsinstall in config, which
 # is done with the config/host target. Note the config/host target only exists if
 # nsinstall is actually built, which it is not on Windows, because we use
 # nsinstall.py there.
-ifeq ($(CURRENT_TIER),export)
 ifneq (,$(filter config/host, $(compile_targets)))
 $(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS)): config/host
 
 # Ensure rules for config/host and its possible dependencies.
 .PHONY: $(filter %/host, $(compile_targets))
 $(filter %/host, $(compile_targets)):
 	$(call SUBMAKE,host,$(@D))
 endif
@@ -195,19 +195,16 @@ ifdef PARALLEL_DIRS
 	+@$(MAKE) $$(PARALLEL_DIRS_$(1))
 endif
 	$$(LOOP_OVER_DIRS)
 
 endef
 
 $(foreach subtier,export binaries libs tools,$(eval $(call CREATE_SUBTIER_TRAVERSAL_RULE,$(subtier))))
 
-tools export:: $(SUBMAKEFILES)
-	$(LOOP_OVER_TOOL_DIRS)
-
 endif # ifdef TIERS
 
 endif # ifeq ($(NO_RECURSE_MAKELEVEL),$(MAKELEVEL))
 
 endif # ifeq (.,$(DEPTH))
 
 ifdef COMPILE_ENVIRONMENT
 
@@ -232,9 +229,8 @@ endif
 endif
 
 endif
 
 recurse:
 	@$(RECURSED_COMMAND)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -58,19 +58,18 @@ endif # -s
 # Testing frameworks support
 ################################################################################
 
 testxpcobjdir = $(DEPTH)/_tests/xpcshell
 
 ifdef ENABLE_TESTS
 
 # Add test directories to the regular directories list. TEST_DIRS should
-# arguably have the same status as TOOL_DIRS and other *_DIRS variables. It is
-# coded this way until Makefiles stop using the "ifdef ENABLE_TESTS; DIRS +="
-# convention.
+# arguably have the same status as other *_DIRS variables. It is coded this way
+# until Makefiles stop using the "ifdef ENABLE_TESTS; DIRS +=" convention.
 #
 # The current developer workflow expects tests to be updated when processing
 # the default target. If we ever change this implementation, the behavior
 # should be preserved or the change should be widely communicated. A
 # consequence of not processing test dir targets during the default target is
 # that changes to tests may not be updated and code could assume to pass
 # locally against non-current test code.
 DIRS += $(TEST_DIRS)
@@ -351,21 +350,16 @@ LOOP_OVER_DIRS = \
 endif
 
 # we only use this for the makefiles target and other stuff that doesn't matter
 ifneq (,$(strip $(PARALLEL_DIRS)))
 LOOP_OVER_PARALLEL_DIRS = \
   $(foreach dir,$(PARALLEL_DIRS),$(call SUBMAKE,$@,$(dir)))
 endif
 
-ifneq (,$(strip $(TOOL_DIRS)))
-LOOP_OVER_TOOL_DIRS = \
-  $(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,$@,$(dir)))
-endif
-
 #
 # Now we can differentiate between objects used to build a library, and
 # objects used to build an executable in the same directory.
 #
 ifndef PROGOBJS
 PROGOBJS		= $(OBJS)
 endif
 
@@ -595,23 +589,16 @@ compile:: host target
 
 host:: $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS)
 
 target:: $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS)
 
 include $(topsrcdir)/config/makefiles/target_binaries.mk
 endif
 
-ifdef IS_TOOL_DIR
-# One would think "tools:: libs" would work, but it turns out that combined with
-# bug 907365, this makes make forget to run some rules sometimes.
-tools::
-	@$(MAKE) libs
-endif
-
 ##############################################
 ifneq (1,$(NO_PROFILE_GUIDED_OPTIMIZE))
 ifdef MOZ_PROFILE_USE
 ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
 # When building with PGO, we have to make sure to re-link
 # in the MOZ_PROFILE_USE phase if we linked in the
 # MOZ_PROFILE_GENERATE phase. We'll touch this pgo.relink
 # file in the link rule in the GENERATE phase to indicate
@@ -672,17 +659,17 @@ clean clobber realclean clobber_all::
 
 ifdef TIERS
 clean clobber realclean clobber_all distclean::
 	$(foreach dir, \
 		$(foreach tier, $(TIERS), $(tier_$(tier)_staticdirs) $(tier_$(tier)_dirs)), \
 		-$(call SUBMAKE,$@,$(dir)))
 else
 clean clobber realclean clobber_all distclean::
-	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
+	$(foreach dir,$(PARALLEL_DIRS) $(DIRS),-$(call SUBMAKE,$@,$(dir)))
 endif
 
 distclean::
 	-$(RM) -r $(ALL_TRASH_DIRS)
 	-$(RM) $(ALL_TRASH)  \
 	Makefile .HSancillary \
 	$(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
 	$(wildcard *.$(LIB_SUFFIX)) $(wildcard *$(DLL_SUFFIX)) \
@@ -1290,17 +1277,16 @@ endif # SDK_BINARY
 
 ################################################################################
 # CHROME PACKAGING
 
 chrome::
 	$(MAKE) realchrome
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
 
 $(FINAL_TARGET)/chrome: $(call mkdir_deps,$(FINAL_TARGET)/chrome)
 
 ifneq (,$(JAR_MANIFEST))
 ifndef NO_DIST_INSTALL
 
 ifdef XPI_NAME
 ifdef XPI_ROOT_APPID
@@ -1336,16 +1322,18 @@ endif
 endif
 
 ifneq ($(DIST_FILES),)
 DIST_FILES_PATH := $(FINAL_TARGET)
 DIST_FILES_FLAGS := $(XULAPP_DEFINES)
 PP_TARGETS += DIST_FILES
 endif
 
+# When you move this out of the tools tier, please remove the corresponding
+# hacks in recursivemake.py that check if Makefile.in sets the variable.
 ifneq ($(XPI_PKGNAME),)
 tools realchrome::
 ifdef STRIP_XPI
 ifndef MOZ_DEBUG
 	@echo 'Stripping $(XPI_PKGNAME) package directory...'
 	@echo $(FINAL_TARGET)
 	@cd $(FINAL_TARGET) && find . ! -type d \
 			! -name '*.js' \
@@ -1371,16 +1359,17 @@ ifndef MOZ_DEBUG
 			$(PLATFORM_EXCLUDE_LIST) \
 			-exec $(STRIP) $(STRIP_FLAGS) {} >/dev/null 2>&1 \;
 endif
 endif
 	@echo 'Packaging $(XPI_PKGNAME).xpi...'
 	cd $(FINAL_TARGET) && $(ZIP) -qr ../$(XPI_PKGNAME).xpi *
 endif
 
+# See comment above about moving this out of the tools tier.
 ifdef INSTALL_EXTENSION_ID
 ifndef XPI_NAME
 $(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
 endif
 
 tools::
 	$(RM) -r '$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
 	$(NSINSTALL) -D '$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
@@ -1615,17 +1604,17 @@ endif
 # hundreds of built-in suffix rules for stuff we don't need.
 #
 .SUFFIXES:
 
 #
 # Fake targets.  Always run these rules, even if a file/directory with that
 # name already exists.
 #
-.PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE
+.PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) FORCE
 
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
 tags: TAGS
@@ -1645,17 +1634,16 @@ endif #}
 documentation:
 	@cd $(DEPTH)
 	$(DOXYGEN) $(DEPTH)/config/doxygen.cfg
 
 ifdef ENABLE_TESTS
 check::
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
 endif
 
 
 FREEZE_VARIABLES = \
   CSRCS \
   CPPSRCS \
   EXPORTS \
   DIRS \
--- a/content/base/moz.build
+++ b/content/base/moz.build
@@ -1,8 +1,8 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 PARALLEL_DIRS += ['public', 'src']
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
--- a/content/base/test/moz.build
+++ b/content/base/test/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += [
+TEST_DIRS += [
     'csp',
     'websocket_hybi',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 
 # FIXME/bug 575918: out-of-process xpcshell is broken on OS X
 if CONFIG['OS_ARCH'] != 'Darwin':
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -8,17 +8,17 @@ PARALLEL_DIRS += [
   'encoder',
   'gmp',
   'mediasource',
   'ogg',
   'webaudio',
   'webvtt'
 ]
 
-TEST_TOOL_DIRS += ['compiledtest']
+TEST_DIRS += ['compiledtest']
 
 if CONFIG['MOZ_RAW']:
     PARALLEL_DIRS += ['raw']
 
 if CONFIG['MOZ_WAVE']:
     PARALLEL_DIRS += ['wave']
 
 if CONFIG['MOZ_WEBM']:
--- a/content/media/webaudio/moz.build
+++ b/content/media/webaudio/moz.build
@@ -1,17 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 PARALLEL_DIRS += ['blink', 'test']
 
-TEST_TOOL_DIRS += ['compiledtest']
+TEST_DIRS += ['compiledtest']
 
 EXPORTS += [
     'AudioContext.h',
     'AudioParamTimeline.h',
     'MediaBufferDecoder.h',
     'ThreeDPoint.h',
     'WebAudioUtils.h',
 ]
--- a/content/moz.build
+++ b/content/moz.build
@@ -7,10 +7,10 @@
 PARALLEL_DIRS += [
     'base',
     'html',
     'media',
     'svg',
     'xul',
 ]
 
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
--- a/dom/audiochannel/moz.build
+++ b/dom/audiochannel/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsIAudioChannelAgent.idl',
 ]
 
 XPIDL_MODULE = 'dom_audiochannel'
 
 EXPORTS += [
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -1,16 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 TEST_DIRS += ['test']
-TEST_TOOL_DIRS += ['compiledtest']
+TEST_DIRS += ['compiledtest']
 
 EXPORTS += [
     'nsICanvasRenderingContextInternal.h',
 ]
 
 EXPORTS.mozilla.ipc += [
     'DocumentRendererChild.h',
     'DocumentRendererParent.h',
--- a/dom/smil/moz.build
+++ b/dom/smil/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
 EXPORTS += [
     'nsISMILAttr.h',
     'nsISMILType.h',
     'nsSMILAnimationController.h',
     'nsSMILAnimationFunction.h',
     'nsSMILCompositorTable.h',
     'nsSMILCSSProperty.h',
--- a/editor/txmgr/moz.build
+++ b/editor/txmgr/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsITransaction.idl',
     'nsITransactionList.idl',
     'nsITransactionListener.idl',
     'nsITransactionManager.idl',
 ]
 
--- a/extensions/cookie/moz.build
+++ b/extensions/cookie/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsICookieAcceptDialog.idl',
     'nsICookiePromptService.idl',
 ]
 
 XPIDL_MODULE = 'cookie'
 
--- a/gfx/moz.build
+++ b/gfx/moz.build
@@ -23,10 +23,10 @@ DIRS += [
 ]
 
 if CONFIG['MOZ_ENABLE_SKIA']:
     DIRS += ['skia']
 
 if CONFIG['ENABLE_TESTS']:
     DIRS += ['tests/gtest']
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
--- a/intl/lwbrk/moz.build
+++ b/intl/lwbrk/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsISemanticUnitScanner.idl',
 ]
 
 XPIDL_MODULE = 'lwbrk'
 
 EXPORTS += [
--- a/intl/strres/moz.build
+++ b/intl/strres/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsIStringBundle.idl',
     'nsIStringBundleOverride.idl',
 ]
 
 XPIDL_MODULE = 'intl'
 
--- a/intl/uconv/moz.build
+++ b/intl/uconv/moz.build
@@ -8,17 +8,17 @@ DIRS += [
     'ucvja',
     'ucvcn',
     'ucvlatin',
     'ucvtw',
     'ucvko',
     'ucvibm',
 ]
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsICurrentCharsetListener.idl',
     'nsIScriptableUConv.idl',
     'nsITextToSubURI.idl',
     'nsIUTF8ConverterService.idl',
 ]
 
--- a/intl/unicharutil/moz.build
+++ b/intl/unicharutil/moz.build
@@ -1,16 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['util', 'tables']
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsIEntityConverter.idl',
     'nsISaveAsCharset.idl',
     'nsIUnicodeNormalizer.idl',
 ]
 
 XPIDL_MODULE = 'unicharutil'
--- a/ipc/ipdl/test/cxx/moz.build
+++ b/ipc/ipdl/test/cxx/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TOOL_DIRS += ['app']
+DIRS += ['app']
 
 EXPORTS.mozilla._ipdltest += [
     'IPDLUnitTestProcessChild.h',
     'IPDLUnitTests.h',
     'IPDLUnitTestTypes.h',
     'IPDLUnitTestUtils.h',
 ]
 
--- a/ipc/moz.build
+++ b/ipc/moz.build
@@ -21,9 +21,9 @@ if CONFIG['MOZ_NFC']:
     DIRS += ['nfc']
 
 if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT'] or CONFIG['MOZ_NFC'] or CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['unixfd', 'unixsocket']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['keystore', 'netd']
 
-TOOL_DIRS += ['app']
+DIRS += ['app']
--- a/js/xpconnect/moz.build
+++ b/js/xpconnect/moz.build
@@ -1,13 +1,13 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['public', 'idl', 'wrappers', 'loader', 'src']
-TOOL_DIRS += ['shell']
-TEST_TOOL_DIRS += ['tests']
+DIRS += ['shell']
+TEST_DIRS += ['tests']
 
 if CONFIG['MOZ_XPCTOOLS']:
-    TOOL_DIRS += ['tools']
+    DIRS += ['tools']
 
--- a/js/xpconnect/tests/moz.build
+++ b/js/xpconnect/tests/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += [
+TEST_DIRS += [
     'idl',
     'mochitest',
     'chrome',
     'browser',
     'components/native',
     'components/js',
 ]
 
--- a/layout/moz.build
+++ b/layout/moz.build
@@ -16,17 +16,17 @@ PARALLEL_DIRS += [
     'mathml',
     'inspector',
     'tools/recording',
 ]
 
 if CONFIG['NS_PRINTING']:
     PARALLEL_DIRS += ['printing']
 
-TEST_TOOL_DIRS += [
+TEST_DIRS += [
     'tools/reftest',
 ]
 
 DIRS += ['build', 'media']
 
 if CONFIG['MOZ_DEBUG']:
     TEST_DIRS += ['tools/layout-debug']
 
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -1,16 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['xbl-marquee']
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
 EXPORTS += [
     'AnimationCommon.h',
     'CounterStyleManager.h',
     'nsAnimationManager.h',
     'nsComputedDOMStylePropertyList.h',
     'nsCSSAnonBoxes.h',
     'nsCSSAnonBoxList.h',
--- a/media/libcubeb/moz.build
+++ b/media/libcubeb/moz.build
@@ -1,9 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['include', 'src']
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
--- a/memory/mozalloc/moz.build
+++ b/memory/mozalloc/moz.build
@@ -63,13 +63,13 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
     FORCE_STATIC_LIB = True
 else:
     FORCE_SHARED_LIB = True
     SDK_LIBRARY = True
 
 # The strndup declaration in string.h is in an ifdef __USE_GNU section
 DEFINES['_GNU_SOURCE'] = True
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 GENERATED_INCLUDES += ['/xpcom']
 
 DISABLE_STL_WRAPPING = True
--- a/modules/libjar/moz.build
+++ b/modules/libjar/moz.build
@@ -2,17 +2,17 @@
 # vim: set filetype=python:
 # 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/.
 
 if CONFIG['MOZ_ZIPWRITER']:
     DIRS += ['zipwriter']
 
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsIJARChannel.idl',
     'nsIJARProtocolHandler.idl',
     'nsIJARURI.idl',
     'nsIZipReader.idl',
 ]
 
--- a/modules/libjar/test/moz.build
+++ b/modules/libjar/test/moz.build
@@ -1,9 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['mochitest', 'chrome']
+TEST_DIRS += ['mochitest', 'chrome']
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
--- a/modules/libpref/moz.build
+++ b/modules/libpref/moz.build
@@ -1,9 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['public', 'src']
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
--- a/mozglue/linker/moz.build
+++ b/mozglue/linker/moz.build
@@ -22,9 +22,9 @@ HOST_SOURCES += [
 HOST_PROGRAM = 'szip'
 
 FINAL_LIBRARY = 'mozglue'
 
 DEFINES['IMPL_MFBT'] = True
 
 DISABLE_STL_WRAPPING = True
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
--- a/mozglue/moz.build
+++ b/mozglue/moz.build
@@ -7,9 +7,9 @@
 if CONFIG['MOZ_LINKER']:
     DIRS += ['linker']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     DIRS += ['android']
 
 DIRS += ['build']
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
--- a/netwerk/moz.build
+++ b/netwerk/moz.build
@@ -25,11 +25,11 @@ if CONFIG['MOZ_SCTP']:
     PARALLEL_DIRS += ['sctp/src', 'sctp/datachannel']
 
 if CONFIG['NECKO_WIFI']:
     PARALLEL_DIRS += ['wifi']
 
 PARALLEL_DIRS += ['locales']
 
 DIRS += ['build']
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
 CONFIGURE_DEFINE_FILES += ['necko-config.h']
--- a/netwerk/streamconv/moz.build
+++ b/netwerk/streamconv/moz.build
@@ -1,8 +1,8 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['public', 'src', 'converters']
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
--- a/netwerk/test/moz.build
+++ b/netwerk/test/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['httpserver']
+TEST_DIRS += ['httpserver']
 
 FAIL_ON_WARNINGS = True
 
 BROWSER_CHROME_MANIFESTS += ['browser/browser.ini']
 MOCHITEST_MANIFESTS += ['mochitests/mochitest.ini']
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 
 # FIXME/bug 575918: out-of-process xpcshell is broken on OS X
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -3,16 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import unicode_literals
 
 import itertools
 import json
 import logging
 import os
+import re
 import types
 
 from collections import (
     defaultdict,
     namedtuple,
 )
 
 import mozwebidlcodegen
@@ -139,28 +140,27 @@ class RecursiveMakeTraversal(object):
     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']
+    SubDirectoryCategories = ['parallel', 'static', 'dirs', 'tests']
     SubDirectoriesTuple = namedtuple('SubDirectories', SubDirectoryCategories)
     class SubDirectories(SubDirectoriesTuple):
         def __new__(self):
-            return RecursiveMakeTraversal.SubDirectoriesTuple.__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=[],
@@ -177,17 +177,17 @@ class RecursiveMakeTraversal(object):
             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
+               subdirs.static + subdirs.dirs + subdirs.tests
 
     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()))
@@ -324,16 +324,18 @@ class RecursiveMakeBackend(CommonBackend
         self._traversal = RecursiveMakeTraversal()
         self._compile_graph = defaultdict(set)
         self._triggers = defaultdict(set)
 
         self._may_skip = {
             'export': set(),
             'binaries': set(),
             'libs': set(),
+        }
+        self._no_skip = {
             'tools': set(),
         }
 
     def consume_object(self, obj):
         """Write out build files necessary to build with recursive make."""
 
         if not isinstance(obj, SandboxDerived):
             return
@@ -497,45 +499,49 @@ class RecursiveMakeBackend(CommonBackend
         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.
         """
         for tier, skip in self._may_skip.items():
             self.log(logging.DEBUG, 'fill_root_mk', {
                 'number': len(skip), 'tier': tier
                 }, 'Ignoring {number} directories during {tier}')
+        for tier, no_skip in self._no_skip.items():
+            self.log(logging.DEBUG, 'fill_root_mk', {
+                'number': len(no_skip), 'tier': tier
+                }, 'Using {number} directories during {tier}')
 
         # Traverse directories in parallel, and skip static dirs
         def parallel_filter(current, subdirs):
             all_subdirs = subdirs.parallel + subdirs.dirs + \
-                          subdirs.tests + subdirs.tools
+                          subdirs.tests
             if current in self._may_skip[tier] \
                     or current.startswith('subtiers/'):
                 current = None
             return current, all_subdirs, []
 
         # build everything in parallel, including static dirs
-        # Skip tools dirs during libs traversal. Because of bug 925236 and
-        # possible other unknown race conditions, don't parallelize the libs
-        # tier.
+        # Because of bug 925236 and possible other unknown race conditions,
+        # don't parallelize the libs tier.
         def libs_filter(current, subdirs):
-            if current in self._may_skip[tier] \
+            if current in self._may_skip['libs'] \
                     or current.startswith('subtiers/'):
                 current = None
             return current, [], subdirs.parallel + \
                 subdirs.dirs + subdirs.tests
 
         # Because of bug 925236 and possible other unknown race conditions,
-        # don't parallelize the tools tier.
+        # don't parallelize the tools tier. There aren't many directories for
+        # this tier anyways, and none of them are under a PARALLEL_DIRS.
         def tools_filter(current, subdirs):
-            if current in self._may_skip[tier] \
+            if current not in self._no_skip['tools'] \
                     or current.startswith('subtiers/'):
                 current = None
-            return current, subdirs.parallel, \
-                subdirs.dirs + subdirs.tests + subdirs.tools
+            return current, [], subdirs.parallel + \
+                subdirs.dirs + subdirs.tests
 
         # compile, binaries and tools tiers use the same traversal as export
         filters = [
             ('export', parallel_filter),
             ('binaries', parallel_filter),
             ('libs', libs_filter),
             ('tools', tools_filter),
         ]
@@ -716,16 +722,29 @@ class RecursiveMakeBackend(CommonBackend
                 with open(obj.output_path) as fh:
                     content = fh.read()
                     for trigger, targets in self._triggers.items():
                         if trigger.encode('ascii') in content:
                             for target in targets:
                                 t = '%s/target' % mozpath.relpath(objdir,
                                     bf.environment.topobjdir)
                                 self._compile_graph[t].add(target)
+                    # Skip every directory but those with a Makefile
+                    # containing a tools target, or XPI_PKGNAME or
+                    # INSTALL_EXTENSION_ID.
+                    for t in (b'XPI_PKGNAME', b'INSTALL_EXTENSION_ID',
+                            b'tools'):
+                        if t not in content:
+                            continue
+                        if t == b'tools' and not re.search('(?:^|\s)tools.*::', content, re.M):
+                            continue
+                        if objdir == bf.environment.topobjdir:
+                            continue
+                        self._no_skip['tools'].add(mozpath.relpath(objdir,
+                            bf.environment.topobjdir))
 
         # Write out a master list of all IPDL source files.
         ipdl_dir = mozpath.join(self.environment.topobjdir, 'ipc', 'ipdl')
         mk = mozmakeutil.Makefile()
 
         sorted_ipdl_sources = list(sorted(self._ipdl_sources))
         mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources))
 
@@ -829,49 +848,31 @@ class RecursiveMakeBackend(CommonBackend
             fh.write('DIRS := %s\n' % ' '.join(obj.dirs))
             self._traversal.add(backend_file.relobjdir, dirs=relativize(obj.dirs))
 
         if 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:
-            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:
             fh.write('TEST_DIRS := %s\n' % ' '.join(obj.test_dirs))
             if self.environment.substs.get('ENABLE_TESTS', False):
                 self._traversal.add(backend_file.relobjdir,
                                     tests=relativize(obj.test_dirs))
 
-        if obj.test_tool_dirs and \
-            self.environment.substs.get('ENABLE_TESTS', False):
-
-            fh.write('TOOL_DIRS += %s\n' % ' '.join(obj.test_tool_dirs))
-            self._traversal.add(backend_file.relobjdir,
-                                tools=relativize(obj.test_tool_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:
-            fh.write('IS_TOOL_DIR := 1\n')
-
         affected_tiers = set(obj.affected_tiers)
         # Until all SOURCES are really in moz.build, consider all directories
         # building binaries to require a pass at compile, too.
         if 'binaries' in affected_tiers:
             affected_tiers.add('libs')
-        if obj.is_tool_dir and 'libs' in affected_tiers:
-            affected_tiers.remove('libs')
-            affected_tiers.add('tools')
 
         for tier in set(self._may_skip.keys()) - affected_tiers:
             self._may_skip[tier].add(backend_file.relobjdir)
 
     def _process_hierarchy(self, obj, element, namespace, action):
         """Walks the ``HierarchicalStringList`` ``element`` and performs
         ``action`` on each string in the heirarcy.
 
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -98,31 +98,27 @@ class DirectoryTraversal(SandboxDerived)
     files is complete and we move to a more optimal build backend.
 
     Fields in this class correspond to similarly named variables in the
     frontend files.
     """
     __slots__ = (
         'dirs',
         'parallel_dirs',
-        'tool_dirs',
         'test_dirs',
-        'test_tool_dirs',
         'tier_dirs',
         'tier_static_dirs',
     )
 
     def __init__(self, sandbox):
         SandboxDerived.__init__(self, sandbox)
 
         self.dirs = []
         self.parallel_dirs = []
-        self.tool_dirs = []
         self.test_dirs = []
-        self.test_tool_dirs = []
         self.tier_dirs = OrderedDict()
         self.tier_static_dirs = OrderedDict()
 
 
 class BaseConfigSubstitution(SandboxDerived):
     """Base class describing autogenerated files as part of config.status."""
 
     __slots__ = (
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -930,20 +930,17 @@ class TreeMetadataEmitter(LoggingMixin):
             })
 
         yield obj
 
     def _emit_directory_traversal_from_sandbox(self, sandbox):
         o = DirectoryTraversal(sandbox)
         o.dirs = sandbox.get('DIRS', [])
         o.parallel_dirs = sandbox.get('PARALLEL_DIRS', [])
-        o.tool_dirs = sandbox.get('TOOL_DIRS', [])
         o.test_dirs = sandbox.get('TEST_DIRS', [])
-        o.test_tool_dirs = sandbox.get('TEST_TOOL_DIRS', [])
-        o.is_tool_dir = sandbox.get('IS_TOOL_DIR', False)
         o.affected_tiers = sandbox.get_affected_tiers()
 
         if 'TIERS' in sandbox:
             for tier in sandbox['TIERS']:
                 o.tier_dirs[tier] = sandbox['TIERS'][tier]['regular'] + \
                     sandbox['TIERS'][tier]['external']
                 o.tier_static_dirs[tier] = sandbox['TIERS'][tier]['static']
 
--- a/python/mozbuild/mozbuild/frontend/reader.py
+++ b/python/mozbuild/mozbuild/frontend/reader.py
@@ -53,16 +53,17 @@ from .sandbox import (
     SandboxExecutionError,
     SandboxLoadError,
     Sandbox,
 )
 
 from .sandbox_symbols import (
     FUNCTIONS,
     VARIABLES,
+    DEPRECATION_HINTS,
 )
 
 if sys.version_info.major == 2:
     text_type = unicode
     type_type = types.TypeType
 else:
     text_type = str
     type_type = type
@@ -186,20 +187,16 @@ class MozbuildSandbox(Sandbox):
             d['TOPOBJDIR'] = topobjdir
             d['RELATIVEDIR'] = reldir
             d['SRCDIR'] = mozpath.join(topsrcdir, reldir).rstrip('/')
             d['OBJDIR'] = mozpath.join(topobjdir, reldir).rstrip('/')
 
             d['CONFIG'] = ReadOnlyDefaultDict(lambda: None,
                 self.config.substs_unicode)
 
-            var = metadata.get('var', None)
-            if var and var in ['TOOL_DIRS', 'TEST_TOOL_DIRS']:
-                d['IS_TOOL_DIR'] = True
-
             # Register functions.
             for name, func in FUNCTIONS.items():
                 d[name] = getattr(self, func[0])
 
             # Initialize the exports that we need in the global.
             extra_vars = self.metadata.get('exports', dict())
             self._globals.update(extra_vars)
 
@@ -595,16 +592,21 @@ class BuildReaderError(Exception):
 
             s.write('The underlying problem is an attempt to %s ' % verb)
             s.write('a reserved UPPERCASE variable that does not exist.\n')
             s.write('\n')
             s.write('The variable %s causing the error is:\n' % verb)
             s.write('\n')
             s.write('    %s\n' % inner.args[2])
             s.write('\n')
+
+            if inner.args[2] in DEPRECATION_HINTS:
+                s.write('%s\n' % DEPRECATION_HINTS[inner.args[2]])
+                return
+
             s.write('Please change the file to not use this variable.\n')
             s.write('\n')
             s.write('For reference, the set of valid variables is:\n')
             s.write('\n')
             s.write(', '.join(sorted(VARIABLES.keys())) + '\n')
             return
 
         s.write('The underlying problem is a reference to an undefined ')
@@ -792,35 +794,21 @@ class BuildReader(object):
         time_start = time.time()
         sandbox = MozbuildSandbox(config, path, metadata=metadata)
         sandbox.exec_file(path, filesystem_absolute=filesystem_absolute)
         sandbox.execution_time = time.time() - time_start
 
         if self._sandbox_post_eval_cb:
             self._sandbox_post_eval_cb(sandbox)
 
-        var = metadata.get('var', None)
-        forbidden = {
-            'TOOL_DIRS': ['DIRS', 'PARALLEL_DIRS', 'TEST_DIRS'],
-            'TEST_TOOL_DIRS': ['DIRS', 'PARALLEL_DIRS', 'TEST_DIRS', 'TOOL_DIRS'],
-        }
-        if var in forbidden:
-            matches = [v for v in forbidden[var] if sandbox[v]]
-            if matches:
-                raise SandboxValidationError('%s is registered as %s.\n'
-                    'The %s variable%s not allowed in such directories.'
-                    % (var, metadata['parent'],
-                       ' and '.join(', '.join(matches).rsplit(', ', 1)),
-                       's are' if len(matches) > 1 else ' is'), sandbox)
-
         # We first collect directories populated in variables.
-        dir_vars = ['DIRS', 'PARALLEL_DIRS', 'TOOL_DIRS']
+        dir_vars = ['DIRS', 'PARALLEL_DIRS']
 
         if sandbox.config.substs.get('ENABLE_TESTS', False) == '1':
-            dir_vars.extend(['TEST_DIRS', 'TEST_TOOL_DIRS'])
+            dir_vars.append('TEST_DIRS')
 
         dirs = [(v, sandbox[v]) for v in dir_vars if v in sandbox]
 
         curdir = mozpath.dirname(path)
 
         gyp_sandboxes = []
         for target_dir in sandbox['GYP_DIRS']:
             gyp_dir = sandbox['GYP_DIRS'][target_dir]
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -459,38 +459,25 @@ VARIABLES = {
         Each name in this variable corresponds to a hosst executable built
         from the corresponding source file with the same base name.
 
         If the configuration token ``HOST_BIN_SUFFIX`` is set, its value will
         be automatically appended to each name. If a name already ends with
         ``HOST_BIN_SUFFIX``, the name will remain unchanged.
         """, 'binaries'),
 
-    'TOOL_DIRS': (list, list,
-        """Like DIRS but for tools.
-
-        Tools are for pieces of the build system that aren't required to
-        produce a working binary (in theory). They provide things like test
-        code and utilities.
-        """, None),
-
     'TEST_DIRS': (list, list,
         """Like DIRS but only for directories that contain test-only code.
 
         If tests are not enabled, this variable will be ignored.
 
         This variable may go away once the transition away from Makefiles is
         complete.
         """, None),
 
-    'TEST_TOOL_DIRS': (list, list,
-        """TOOL_DIRS that is only executed if tests are enabled.
-        """, None),
-
-
     'TIERS': (OrderedDict, dict,
         """Defines directories constituting the tier traversal mechanism.
 
         The recursive make backend iteration is organized into tiers. There are
         major tiers (keys in this dict) that correspond roughly to applications
         or libraries being built. e.g. base, nspr, js, platform, app. Within
         each tier are phases like export, libs, and tools. The recursive make
         backend iterates over each phase in the first tier then proceeds to the
@@ -939,19 +926,18 @@ FUNCTIONS = {
         add_tier_dir call.
         """),
 
     'export': ('_export', (str,),
         """Make the specified variable available to all child directories.
 
         The variable specified by the argument string is added to the
         environment of all directories specified in the DIRS, PARALLEL_DIRS,
-        TOOL_DIRS, TEST_DIRS, and TEST_TOOL_DIRS variables. If those directories
-        themselves have child directories, the variable will be exported to all
-        of them.
+        and TEST_DIRS variables. If those directories themselves have child
+        directories, the variable will be exported to all of them.
 
         The value used for the variable is the final value at the end of the
         moz.build file, so it is possible (but not recommended style) to place
         the export before the definition of the variable.
 
         This function is limited to the upper-case variables that have special
         meaning in moz.build files.
 
@@ -1038,8 +1024,14 @@ SPECIAL_VARIABLES = {
 
         The set of exposed Python built-ins is currently:
 
         - True
         - False
         - None
         """),
 }
+
+# Deprecation hints.
+DEPRECATION_HINTS = {
+    'TOOL_DIRS': 'Please use the DIRS variable instead.',
+    'TEST_TOOL_DIRS': 'Please use the TEST_DIRS variable instead.',
+}
deleted file mode 100644
deleted file mode 100644
--- a/python/mozbuild/mozbuild/test/frontend/data/reader-error-traversal-tools/foo/moz.build
+++ /dev/null
@@ -1,2 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-DIRS = ['biz']
deleted file mode 100644
--- a/python/mozbuild/mozbuild/test/frontend/data/reader-error-traversal-tools/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# Any copyright is dedicated to the Public Domain.
-# http://creativecommons.org/publicdomain/zero/1.0/
-
-TOOL_DIRS = ['foo']
--- a/python/mozbuild/mozbuild/test/frontend/data/traversal-all-vars/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/traversal-all-vars/moz.build
@@ -1,9 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 DIRS += ['regular']
 PARALLEL_DIRS = ['parallel']
 TEST_DIRS = ['test']
-TEST_TOOL_DIRS = ['test_tool']
-TOOL_DIRS = ['tool']
deleted file mode 100644
deleted file mode 100644
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -83,51 +83,46 @@ class TestEmitterBasic(unittest.TestCase
     def test_dirs_traversal_simple(self):
         reader = self.reader('traversal-simple')
         objs = self.read_topsrcdir(reader, filter_common=False)
         self.assertEqual(len(objs), 4)
 
         for o in objs:
             self.assertIsInstance(o, DirectoryTraversal)
             self.assertEqual(o.parallel_dirs, [])
-            self.assertEqual(o.tool_dirs, [])
             self.assertEqual(o.test_dirs, [])
-            self.assertEqual(o.test_tool_dirs, [])
             self.assertEqual(len(o.tier_dirs), 0)
             self.assertEqual(len(o.tier_static_dirs), 0)
             self.assertTrue(os.path.isabs(o.sandbox_main_path))
             self.assertEqual(len(o.sandbox_all_paths), 1)
 
         reldirs = [o.relativedir for o in objs]
         self.assertEqual(reldirs, ['', 'foo', 'foo/biz', 'bar'])
 
         dirs = [o.dirs for o in objs]
         self.assertEqual(dirs, [['foo', 'bar'], ['biz'], [], []])
 
     def test_traversal_all_vars(self):
         reader = self.reader('traversal-all-vars')
         objs = self.read_topsrcdir(reader, filter_common=False)
-        self.assertEqual(len(objs), 6)
+        self.assertEqual(len(objs), 4)
 
         for o in objs:
             self.assertIsInstance(o, DirectoryTraversal)
 
         reldirs = set([o.relativedir for o in objs])
-        self.assertEqual(reldirs, set(['', 'parallel', 'regular', 'test',
-            'test_tool', 'tool']))
+        self.assertEqual(reldirs, set(['', 'parallel', 'regular', 'test']))
 
         for o in objs:
             reldir = o.relativedir
 
             if reldir == '':
                 self.assertEqual(o.dirs, ['regular'])
                 self.assertEqual(o.parallel_dirs, ['parallel'])
                 self.assertEqual(o.test_dirs, ['test'])
-                self.assertEqual(o.test_tool_dirs, ['test_tool'])
-                self.assertEqual(o.tool_dirs, ['tool'])
 
     def test_tier_simple(self):
         reader = self.reader('traversal-tier-simple')
         objs = self.read_topsrcdir(reader, filter_common=False)
         self.assertEqual(len(objs), 4)
 
         reldirs = [o.relativedir for o in objs]
         self.assertEqual(reldirs, ['', 'foo', 'foo/biz', 'bar'])
--- a/python/mozbuild/mozbuild/test/frontend/test_reader.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_reader.py
@@ -61,17 +61,17 @@ class TestBuildReader(unittest.TestCase)
             filesystem_absolute=True, descend=False))
 
         self.assertEqual(len(sandboxes), 1)
 
     def test_dirs_traversal_all_variables(self):
         reader = self.reader('traversal-all-vars', enable_tests=True)
 
         sandboxes = list(reader.read_topsrcdir())
-        self.assertEqual(len(sandboxes), 6)
+        self.assertEqual(len(sandboxes), 4)
 
     def test_tiers_traversal(self):
         reader = self.reader('traversal-tier-simple')
 
         sandboxes = list(reader.read_topsrcdir())
         self.assertEqual(len(sandboxes), 4)
 
         for sandbox in sandboxes:
@@ -241,25 +241,16 @@ class TestBuildReader(unittest.TestCase)
 
         with self.assertRaises(BuildReaderError) as bre:
             list(reader.read_topsrcdir())
 
         e = bre.exception
         self.assertIn('A moz.build file called the error() function.', str(e))
         self.assertIn('    Some error.', str(e))
 
-    def test_error_traversal_tools(self):
-        reader = self.reader('reader-error-traversal-tools')
-
-        with self.assertRaises(BuildReaderError) as bre:
-            list(reader.read_topsrcdir())
-
-        e = bre.exception
-        self.assertIn('The DIRS variable is not allowed in such directories.', str(e))
-
     def test_inheriting_variables(self):
         reader = self.reader('inheriting-variables')
 
         sandboxes = list(reader.read_topsrcdir())
 
         self.assertEqual(len(sandboxes), 4)
         self.assertEqual([sandbox['RELATIVEDIR'] for sandbox in sandboxes],
             ['', 'foo', 'foo/baz', 'bar'])
--- a/rdf/moz.build
+++ b/rdf/moz.build
@@ -1,9 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['base', 'util', 'datasource', 'build']
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
--- a/rdf/tests/moz.build
+++ b/rdf/tests/moz.build
@@ -1,9 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['rdfcat', 'rdfpoll', 'triplescat']
+TEST_DIRS += ['rdfcat', 'rdfpoll', 'triplescat']
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
--- a/security/manager/ssl/tests/moz.build
+++ b/security/manager/ssl/tests/moz.build
@@ -6,13 +6,13 @@
 
 DIRS += ['unit']
 
 TEST_DIRS += [
     'gtest',
     'mochitest',
 ]
 
-TEST_TOOL_DIRS += [
+TEST_DIRS += [
   'compiled',
 ]
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
--- a/startupcache/moz.build
+++ b/startupcache/moz.build
@@ -1,16 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 if not CONFIG['MOZ_B2G']:
-    TEST_TOOL_DIRS += ['test']
+    TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsIStartupCache.idl',
 ]
 
 XPIDL_MODULE = 'startupcache'
 
 EXPORTS.mozilla.scache += [
--- a/storage/moz.build
+++ b/storage/moz.build
@@ -1,10 +1,10 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['public', 'src', 'build']
 
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
--- a/toolkit/components/places/tests/moz.build
+++ b/toolkit/components/places/tests/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['cpp']
+TEST_DIRS += ['cpp']
 
 XPCSHELL_TESTS_MANIFESTS += [
     'autocomplete/xpcshell.ini',
     'bookmarks/xpcshell.ini',
     'expiration/xpcshell.ini',
     'favicons/xpcshell.ini',
     'inline/xpcshell.ini',
     'migration/xpcshell.ini',
--- a/toolkit/components/url-classifier/moz.build
+++ b/toolkit/components/url-classifier/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 XPIDL_SOURCES += [
     'nsIUrlClassifierDBService.idl',
     'nsIUrlClassifierHashCompleter.idl',
     'nsIUrlClassifierPrefixSet.idl',
     'nsIUrlClassifierStreamUpdater.idl',
     'nsIUrlClassifierUtils.idl',
     'nsIUrlListManager.idl',
--- a/toolkit/crashreporter/moz.build
+++ b/toolkit/crashreporter/moz.build
@@ -52,17 +52,17 @@ DIRS += ['client']
 
 if CONFIG['MOZ_CRASHREPORTER_INJECTOR']:
     DIRS += ['injector']
     UNIFIED_SOURCES += [
         'InjectCrashReporter.cpp',
         'LoadLibraryRemote.cpp',
     ]
 
-TEST_TOOL_DIRS += ['test']
+TEST_DIRS += ['test']
 
 EXPORTS += [
     'nsExceptionHandler.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsExceptionHandler.cpp',
 ]
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -37,17 +37,17 @@ elif toolkit == 'cocoa':
         'nsISystemStatusBar.idl',
         'nsITaskbarProgress.idl',
     ]
     EXPORTS += [
         'nsINativeMenuService.h',
         'nsIPrintDialogService.h',
     ]
 
-TEST_TOOL_DIRS += ['tests']
+TEST_DIRS += ['tests']
 
 # Don't build the DSO under the 'build' directory as windows does.
 #
 # The DSOs get built in the toolkit dir itself.  Do this so that
 # multiple implementations of widget can be built on the same
 # source tree.
 #
 if CONFIG['MOZ_ENABLE_GTK']:
--- a/xpcom/moz.build
+++ b/xpcom/moz.build
@@ -21,24 +21,24 @@ DIRS += [
     'system',
     '../chrome',
     'build',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_DEBUG']:
     DIRS += ['windbgdlg']
 
-TEST_TOOL_DIRS += [
+TEST_DIRS += [
     'tests',
     'sample',
     'typelib/xpt/tests',
 ]
 
 #  Can't build internal xptcall tests that use symbols which are not exported.
-#TEST_TOOL_DIRS += [
+#TEST_DIRS += [
 #    'reflect/xptinfo/tests',
 #    'reflect/xptcall/tests,
 #]
 
 CONFIGURE_DEFINE_FILES += [
     'xpcom-config.h',
     'xpcom-private.h',
 ]
--- a/xpcom/sample/moz.build
+++ b/xpcom/sample/moz.build
@@ -1,17 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 # If you're copying from this file, you'll likely need to replace
-# TEST_TOOL_DIRS with DIRS.
-TEST_TOOL_DIRS += ['program']
+# TEST_DIRS with DIRS.
+TEST_DIRS += ['program']
 
 # XPIDL_SOURCES specifies IDL files. The build system runs the xpidl tool
 # on these files to generate C++ headers and .xpt typelib files.
 XPIDL_SOURCES += ['nsISample.idl']
 
 # XPIDL_MODULE specifies where header files from this Makefile are installed,
 # i.e. dist/include/xpcomsample
 XPIDL_MODULE = 'xpcomsample'
--- a/xpcom/tests/moz.build
+++ b/xpcom/tests/moz.build
@@ -1,26 +1,26 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-TEST_TOOL_DIRS += [
+TEST_DIRS += [
     'external',
     'component',
     'bug656331_component',
     'component_no_aslr',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
-    TEST_TOOL_DIRS += ['windows']
+    TEST_DIRS += ['windows']
 
 if CONFIG['DEHYDRA_PATH']:
-    TEST_TOOL_DIRS += ['static-checker']
+    TEST_DIRS += ['static-checker']
 
 FAIL_ON_WARNINGS = True
 
 EXPORTS.testing += [
     'TestHarness.h',
 ]
 
 SIMPLE_PROGRAMS = [