summaryrefslogtreecommitdiff
path: root/config/makefiles
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commitad18d877ddd2a44d98fa12ccd3dbbcf4d0ac4299 (patch)
tree10027f336435511475e392454359edea8e25895d /config/makefiles
parent15477ed9af4859dacb069040b5d4de600803d3bc (diff)
downloaduxp-ad18d877ddd2a44d98fa12ccd3dbbcf4d0ac4299.tar.gz
Add m-esr52 at 52.6.0
Diffstat (limited to 'config/makefiles')
-rw-r--r--config/makefiles/autotargets.mk94
-rw-r--r--config/makefiles/debugmake.mk119
-rw-r--r--config/makefiles/functions.mk30
-rw-r--r--config/makefiles/java-build.mk159
-rw-r--r--config/makefiles/makeutils.mk121
-rw-r--r--config/makefiles/nonrecursive.mk68
-rw-r--r--config/makefiles/target_binaries.mk42
-rw-r--r--config/makefiles/test/Makefile.in98
-rw-r--r--config/makefiles/test/check-arglist.mk100
-rw-r--r--config/makefiles/test/check-autotargets.mk84
-rw-r--r--config/makefiles/test/check_XinY.mk70
-rw-r--r--config/makefiles/test/moz.build6
-rw-r--r--config/makefiles/xpidl/Makefile.in93
13 files changed, 1084 insertions, 0 deletions
diff --git a/config/makefiles/autotargets.mk b/config/makefiles/autotargets.mk
new file mode 100644
index 0000000000..16e06fb2a4
--- /dev/null
+++ b/config/makefiles/autotargets.mk
@@ -0,0 +1,94 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+#
+
+ifndef INCLUDED_AUTOTARGETS_MK #{
+
+# Conditional does not wrap the entire file so multiple
+# includes will be able to accumulate dependencies.
+
+###########################################################################
+# AUTO_DEPS - A list of deps/targets drived from other macros.
+###########################################################################
+
+MKDIR ?= mkdir -p
+TOUCH ?= touch
+
+# declare for local use, rules.mk may not have been loaded
+space = $(NULL) $(NULL)
+
+# Deps will be considered intermediate when used as a pre-requisite for
+# wildcard targets. Inhibit their removal, mkdir -p is a standalone op.
+.PRECIOUS: %/.mkdir.done
+
+#########################
+##---] FUNCTIONS [---##
+#########################
+
+# Squeeze can be overzealous, restore root for abspath
+getPathPrefix =$(if $(filter /%,$(1)),/)
+
+# Squeeze '//' from the path, easily created by string functions
+_slashSqueeze =$(foreach val,$(getargv),$(call getPathPrefix,$(val))$(subst $(space),/,$(strip $(subst /,$(space),$(val)))))
+
+# Squeeze extraneous directory slashes from the path
+# o protect embedded spaces within the path
+# o replace //+ sequences with /
+slash_strip = \
+ $(strip \
+ $(subst <--[**]-->,$(space),\
+ $(call _slashSqueeze,\
+ $(subst $(space),<--[**]-->,$(1))\
+ )))
+
+# Extract directory path from a dependency file.
+mkdir_stem =$(foreach val,$(getargv),$(subst /.mkdir.done,$(NULL),$(val)))
+
+## Generate timestamp file for threadsafe directory creation
+mkdir_deps =$(foreach dir,$(getargv),$(call slash_strip,$(dir)/.mkdir.done))
+
+#######################
+##---] TARGETS [---##
+#######################
+
+%/.mkdir.done: # mkdir -p -p => mkdir -p
+ $(subst $(space)-p,$(null),$(MKDIR)) -p '$(dir $@)'
+# Make the timestamp old enough for not being a problem with symbolic links
+# targets depending on it. Use Jan 3, 1980 to accomodate any timezone where
+# 198001010000 would translate to something older than FAT epoch.
+ @$(TOUCH) -t 198001030000 '$@'
+
+# A handful of makefiles are attempting "mkdir dot".
+# tbpl/valgrind builds are using this target
+# https://bugzilla.mozilla.org/show_bug.cgi?id=837754
+.mkdir.done:
+ @echo 'WARNING: $(MKDIR) -dot- requested by $(MAKE) -C $(CURDIR) $(MAKECMDGOALS)'
+ @$(TOUCH) -t 198001030000 '$@'
+
+INCLUDED_AUTOTARGETS_MK = 1
+endif #}
+
+
+## Accumulate deps and cleanup
+ifneq (,$(GENERATED_DIRS))
+ GENERATED_DIRS := $(strip $(sort $(GENERATED_DIRS)))
+ tmpauto :=$(call mkdir_deps,GENERATED_DIRS)
+ GENERATED_DIRS_DEPS +=$(tmpauto)
+ GARBAGE_DIRS +=$(GENERATED_DIRS)
+endif
+
+#################################################################
+# One ring/dep to rule them all:
+# config/rules.mk::all target is available by default
+# Add $(AUTO_DEPS) as an explicit target dependency when needed.
+#################################################################
+
+AUTO_DEPS +=$(GENERATED_DIRS_DEPS)
+AUTO_DEPS := $(strip $(sort $(AUTO_DEPS)))
+
+# Complain loudly if deps have not loaded so getargv != $(NULL)
+$(call requiredfunction,getargv)
diff --git a/config/makefiles/debugmake.mk b/config/makefiles/debugmake.mk
new file mode 100644
index 0000000000..ff4f917e3b
--- /dev/null
+++ b/config/makefiles/debugmake.mk
@@ -0,0 +1,119 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+#
+
+###########################################################################
+## Intent: Helper targets for displaying variables and state information
+###########################################################################
+
+# Support usage outside of config/rules.mk
+ifndef INCLUDED_DEBUGMAKE_MK #{
+
+define CR
+
+
+endef
+
+define shell_quote
+'$(subst $(CR),\$(CR),$(subst ','\'',$(1)))'
+endef
+
+echo-variable-%:
+ @echo $(call shell_quote,$($*))
+
+echo-dirs:
+ @echo $(call shell_quote,$(DIRS))
+
+define print_var
+@printf '%20s = %s\n' $1 $(call shell_quote,$($1))
+
+endef
+
+define print_vars
+$(foreach var,$1,$(call print_var,$(var)))
+endef
+
+showtargs:
+ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS)))
+ @echo --------------------------------------------------------------------------------
+ $(call print_vars,\
+ PROGRAM \
+ SIMPLE_PROGRAMS \
+ LIBRARY \
+ SHARED_LIBRARY \
+ LIBS \
+ DEF_FILE \
+ IMPORT_LIBRARY \
+ STATIC_LIBS \
+ SHARED_LIBS \
+ EXTRA_DSO_LDOPTS \
+ DEPENDENT_LIBS \
+ )
+ @echo --------------------------------------------------------------------------------
+endif
+ $(LOOP_OVER_DIRS)
+
+showbuild showhost: _DEPEND_CFLAGS=
+showbuild showhost: COMPILE_PDB_FLAG=
+showbuild:
+ $(call print_vars,\
+ MOZ_BUILD_ROOT \
+ MOZ_WIDGET_TOOLKIT \
+ CC \
+ CXX \
+ CCC \
+ CPP \
+ LD \
+ AR \
+ IMPLIB \
+ FILTER \
+ MKSHLIB \
+ MKCSHLIB \
+ RC \
+ CFLAGS \
+ OS_CFLAGS \
+ COMPILE_CFLAGS \
+ CXXFLAGS \
+ OS_CXXFLAGS \
+ COMPILE_CXXFLAGS \
+ COMPILE_CMFLAGS \
+ COMPILE_CMMFLAGS \
+ LDFLAGS \
+ OS_LDFLAGS \
+ DSO_LDOPTS \
+ OS_INCLUDES \
+ OS_LIBS \
+ EXTRA_LIBS \
+ BIN_FLAGS \
+ INCLUDES \
+ DEFINES \
+ ACDEFINES \
+ BIN_SUFFIX \
+ LIB_SUFFIX \
+ DLL_SUFFIX \
+ IMPORT_LIB_SUFFIX \
+ INSTALL \
+ VPATH \
+ )
+
+showhost:
+ $(call print_vars,\
+ HOST_CC \
+ HOST_CXX \
+ HOST_CFLAGS \
+ HOST_LDFLAGS \
+ HOST_LIBS \
+ HOST_EXTRA_LIBS \
+ HOST_EXTRA_DEPS \
+ HOST_PROGRAM \
+ HOST_OBJS \
+ HOST_PROGOBJS \
+ HOST_LIBRARY \
+ )
+
+INCLUDED_DEBUGMAKE_MK = 1
+endif #}
diff --git a/config/makefiles/functions.mk b/config/makefiles/functions.mk
new file mode 100644
index 0000000000..ac3632b486
--- /dev/null
+++ b/config/makefiles/functions.mk
@@ -0,0 +1,30 @@
+#
+# 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/.
+
+#
+# functions.mk
+#
+# Defines functions that are needed by various Makefiles throughout the build
+# system, which are needed before config.mk can be included.
+#
+
+# Define an include-at-most-once flag
+ifdef INCLUDED_FUNCTIONS_MK
+$(error Do not include functions.mk twice!)
+endif
+INCLUDED_FUNCTIONS_MK = 1
+
+core_abspath = $(error core_abspath is unsupported, use $$(abspath) instead)
+core_realpath = $(error core_realpath is unsupported)
+
+core_winabspath = $(error core_winabspath is unsupported)
+
+# Run a named Python build action. The first argument is the name of the build
+# action. The second argument are the arguments to pass to the action (space
+# delimited arguments). e.g.
+#
+# libs::
+# $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest)
+py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
diff --git a/config/makefiles/java-build.mk b/config/makefiles/java-build.mk
new file mode 100644
index 0000000000..bf667ac446
--- /dev/null
+++ b/config/makefiles/java-build.mk
@@ -0,0 +1,159 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+
+ifndef INCLUDED_JAVA_BUILD_MK #{
+
+ifdef JAVAFILES #{
+GENERATED_DIRS += classes
+
+export:: classes
+classes: $(call mkdir_deps,classes)
+endif #} JAVAFILES
+
+default_bootclasspath_jars := \
+ $(ANDROID_SDK)/android.jar \
+ $(NULL)
+
+default_classpath_jars := \
+ $(NULL)
+
+# Turn a possibly empty list of JAR files into a Java classpath, like a.jar:b.jar.
+# Arg 1: Possibly empty list of JAR files.
+define classpath_template
+$(subst $(NULL) ,:,$(strip $(1)))
+endef
+
+ifdef ANDROID_APK_NAME #{
+$(if $(ANDROID_APK_PACKAGE),,$(error Missing ANDROID_APK_PACKAGE with ANDROID_APK_NAME))
+
+android_res_dirs := $(or $(ANDROID_RES_DIRS),$(srcdir)/res)
+_ANDROID_RES_FLAG := $(addprefix -S ,$(android_res_dirs))
+_ANDROID_ASSETS_FLAG := $(if $(ANDROID_ASSETS_DIRS),$(addprefix -A ,$(ANDROID_ASSETS_DIRS)))
+android_manifest := $(or $(ANDROID_MANIFEST_FILE),AndroidManifest.xml)
+
+GENERATED_DIRS += classes generated
+
+generated_r_java := generated/$(subst .,/,$(ANDROID_APK_PACKAGE))/R.java
+
+classes.dex: $(call mkdir_deps,classes)
+classes.dex: $(generated_r_java)
+classes.dex: $(ANDROID_APK_NAME).ap_
+classes.dex: $(default_classpath_jars) $(ANDROID_CLASSPATH_JARS)
+classes.dex: $(default_bootclasspath_jars) $(ANDROID_BOOTCLASSPATH_JARS) $(ANDROID_EXTRA_JARS)
+classes.dex: $(JAVAFILES)
+ $(JAVAC) $(JAVAC_FLAGS) -d classes $(filter %.java,$^) \
+ $(addprefix -bootclasspath ,$(call classpath_template,$(default_bootclasspath_jars) $(ANDROID_BOOTCLASSPATH_JARS))) \
+ $(addprefix -classpath ,$(call classpath_template,$(default_classpath_jars) $(ANDROID_CLASSPATH_JARS) $(ANDROID_EXTRA_JARS)))
+ $(DX) --dex --output=$@ classes $(ANDROID_EXTRA_JARS)
+
+# R.java and $(ANDROID_APK_NAME).ap_ are both produced by aapt. To
+# save an aapt invocation, we produce them both at the same time. The
+# trailing semi-colon defines an empty recipe; defining no recipe at
+# all causes Make to treat the target differently, in a way that
+# defeats our dependencies.
+
+$(generated_r_java): .aapt.deps ;
+$(ANDROID_APK_NAME).ap_: .aapt.deps ;
+
+# This uses the fact that Android resource directories list all
+# resource files one subdirectory below the parent resource directory.
+android_res_files := $(wildcard $(addsuffix /*,$(wildcard $(addsuffix /*,$(android_res_dirs)))))
+
+# An extra package like org.example.app generates dependencies like:
+# generated/org/example/app/R.java: .aapt.deps ;
+# classes.dex: generated/org/example/app/R.java
+# GARBAGE: generated/org/example/app/R.java
+$(foreach extra_package,$(ANDROID_EXTRA_PACKAGES), \
+ $(eval generated/$(subst .,/,$(extra_package))/R.java: .aapt.deps ;) \
+ $(eval classes.dex: generated/$(subst .,/,$(extra_package))/R.java) \
+ $(eval GARBAGE: generated/$(subst .,/,$(extra_package))/R.java) \
+)
+
+# aapt flag -m: 'make package directories under location specified by -J'.
+# The --extra-package list is colon separated.
+.aapt.deps: $(android_manifest) $(android_res_files) $(wildcard $(ANDROID_ASSETS_DIRS))
+ @$(TOUCH) $@
+ $(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar $(_ANDROID_RES_FLAG) $(_ANDROID_ASSETS_FLAG) \
+ --custom-package $(ANDROID_APK_PACKAGE) \
+ --non-constant-id \
+ --auto-add-overlay \
+ $(if $(ANDROID_EXTRA_PACKAGES),--extra-packages $(subst $(NULL) ,:,$(strip $(ANDROID_EXTRA_PACKAGES)))) \
+ $(if $(ANDROID_EXTRA_RES_DIRS),$(addprefix -S ,$(ANDROID_EXTRA_RES_DIRS))) \
+ -m \
+ -J ${@D}/generated \
+ -F $(ANDROID_APK_NAME).ap_
+
+$(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
+ cp $< $@
+ $(ZIP) -0 $@ classes.dex
+
+$(ANDROID_APK_NAME)-unaligned.apk: $(ANDROID_APK_NAME)-unsigned-unaligned.apk
+ cp $< $@
+ $(DEBUG_JARSIGNER) $@
+
+$(ANDROID_APK_NAME).apk: $(ANDROID_APK_NAME)-unaligned.apk
+ $(ZIPALIGN) -f 4 $< $@
+
+GARBAGE += \
+ $(generated_r_java) \
+ classes.dex \
+ $(ANDROID_APK_NAME).ap_ \
+ $(ANDROID_APK_NAME)-unsigned-unaligned.apk \
+ $(ANDROID_APK_NAME)-unaligned.apk \
+ $(ANDROID_APK_NAME).apk \
+ $(NULL)
+
+# Include Android specific java flags, instead of what's in rules.mk.
+include $(topsrcdir)/config/android-common.mk
+endif #} ANDROID_APK_NAME
+
+
+ifdef JAVA_JAR_TARGETS #{
+# Arg 1: Output target name with .jar suffix, like jars/jarfile.jar.
+# Intermediate class files are generated in jars/jarfile-classes.
+# Arg 2: Java sources list. We use VPATH and $^ so sources can be
+# relative to $(srcdir) or $(CURDIR).
+# Arg 3: List of extra jars to link against. We do not use VPATH so
+# jars must be relative to $(CURDIR).
+# Arg 4: Additional JAVAC_FLAGS.
+
+# Note: Proguard fails when stale .class files corresponding to
+# removed inner classes are present in the object directory. These
+# stale class files get packaged into the .jar file, which then gets
+# processed by Proguard. To work around this, we always delete any
+# existing jarfile-classes directory and start fresh.
+
+define java_jar_template
+$(1): $(2) $(3) $(default_bootclasspath_jars) $(default_classpath_jars)
+ $$(REPORT_BUILD)
+ @$$(RM) -rf $(1:.jar=)-classes
+ @$$(NSINSTALL) -D $(1:.jar=)-classes
+ @$$(if $$(filter-out .,$$(@D)),$$(NSINSTALL) -D $$(@D))
+ $$(JAVAC) $$(JAVAC_FLAGS)\
+ $(4)\
+ -d $(1:.jar=)-classes\
+ $(addprefix -bootclasspath ,$(call classpath_template,$(default_bootclasspath_jars)))\
+ $(addprefix -classpath ,$(call classpath_template,$(default_classpath_jars) $(3)))\
+ $$(filter %.java,$$^)
+ $$(JAR) cMf $$@ -C $(1:.jar=)-classes .
+
+GARBAGE += $(1)
+
+GARBAGE_DIRS += $(1:.jar=)-classes
+endef
+
+$(foreach jar,$(JAVA_JAR_TARGETS),\
+ $(if $($(jar)_DEST),,$(error Missing $(jar)_DEST))\
+ $(if $($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),,$(error Must provide at least one of $(jar)_JAVAFILES and $(jar)_PP_JAVAFILES))\
+ $(eval $(call java_jar_template,$($(jar)_DEST),$($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),$($(jar)_EXTRA_JARS),$($(jar)_JAVAC_FLAGS)))\
+)
+endif #} JAVA_JAR_TARGETS
+
+
+INCLUDED_JAVA_BUILD_MK := 1
+
+endif #} INCLUDED_JAVA_BUILD_MK
diff --git a/config/makefiles/makeutils.mk b/config/makefiles/makeutils.mk
new file mode 100644
index 0000000000..95c7791a4b
--- /dev/null
+++ b/config/makefiles/makeutils.mk
@@ -0,0 +1,121 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+
+## Identify function argument types
+istype =$(if $(value ${1}),list,scalar)
+isval =$(if $(filter-out list,$(call istype,${1})),true)
+isvar =$(if $(filter-out scalar,$(call istype,${1})),true)
+
+# Access up to 9 arguments passed, option needed to emulate $*
+# Inline for function expansion, do not use $(call )
+argv =$(strip
+argv +=$(if $(1), $(1))$(if $(2), $(2))$(if $(3), $(3))$(if $(4), $(4))
+argv +=$(if $(5), $(5))$(if $(6), $(6))$(if $(7), $(7))$(if $(8), $(8))
+argv +=$(if $(9), $(9))
+argv +=$(if $(10), $(error makeutils.mk::argv can only handle 9 arguments))
+argv +=)
+
+###########################################################################
+## Access function args as a simple list, inline within user functions.
+## Usage: $(info ** $(call banner,$(getargv)))
+## $(call banner,scalar)
+## $(call banner,list0 list1 list2)
+## $(call banner,ref) ; ref=foo bar tans
+## getarglist() would be a more accurate name but is longer to type
+getargv = $(if $(call isvar,$(1)),$($(1)),$(argv))
+
+###########################################################################
+# Strip [n] leading options from an argument list. This will allow passing
+# extra args to user functions that will not propogate to sub-$(call )'s
+# Usage: $(call subargv,2)
+subargv =$(wordlist $(1),$(words $(getargv)),$(getargv))
+
+###########################################################################
+# Intent: Display a distinct banner heading in the output stream
+# Usage: $(call banner,BUILDING: foo bar tans)
+# Debug:
+# target-preqs = \
+# $(call banner,target-preqs-BEGIN) \
+# foo bar tans \
+# $(call banner,target-preqs-END) \
+# $(NULL)
+# target: $(target-preqs)
+
+banner = \
+$(info ) \
+$(info ***************************************************************************) \
+$(info ** $(getargv)) \
+$(info ***************************************************************************) \
+$(NULL)
+
+#####################################################################
+# Intent: Determine if a string or pattern is contained in a list
+# Usage: strcmp - $(call if_XinY,clean,$(MAKECMDGOALS))
+# : pattern - $(call if_XinY,clean%,$(MAKECMDGOALS))
+is_XinY =$(filter $(1),$(call subargv,3,$(getargv)))
+
+#####################################################################
+# Provide an alternate var to support testing
+ifdef MAKEUTILS_UNIT_TEST
+ mcg_goals=TEST_MAKECMDGOALS
+else
+ mcg_goals=MAKECMDGOALS
+endif
+
+# Intent: Conditionals for detecting common/tier target use
+isTargetStem = $(sort \
+ $(foreach var,$(getargv),\
+ $(foreach pat,$(var)% %$(var),\
+ $(call is_XinY,$(pat),${$(mcg_goals)})\
+ )))
+isTargetStemClean = $(call isTargetStem,clean)
+isTargetStemExport = $(call isTargetStem,export)
+isTargetStemLibs = $(call isTargetStem,libs)
+isTargetStemTools = $(call isTargetStem,tools)
+
+##################################################
+# Intent: Validation functions / unit test helpers
+
+errorifneq =$(if $(subst $(strip $(1)),$(NULL),$(strip $(2))),$(error expected [$(1)] but found [$(2)]))
+
+# Intent: verify function declaration exists
+requiredfunction =$(foreach func,$(1) $(2) $(3) $(4) $(5) $(6) $(7) $(8) $(9),$(if $(value $(func)),$(NULL),$(error required function [$(func)] is unavailable)))
+
+
+
+## http://www.gnu.org/software/make/manual/make.html#Call-Function
+## Usage: o = $(call map,origin,o map $(MAKE))
+map = $(foreach val,$(2),$(call $(1),$(val)))
+
+
+## Disable checking for clean targets
+ifeq (,$(filter %clean clean%,$(MAKECMDGOALS))) #{
+
+# Usage: $(call checkIfEmpty,[error|warning] foo NULL bar)
+checkIfEmpty =$(foreach var,$(wordlist 2,100,$(argv)),$(if $(strip $($(var))),$(NOP),$(call $(1),Variable $(var) does not contain a value)))
+
+# Usage: $(call errorIfEmpty,foo NULL bar)
+errorIfEmpty =$(call checkIfEmpty,error $(argv))
+warnIfEmpty =$(call checkIfEmpty,warning $(argv))
+
+endif #}
+
+###########################################################################
+## Common makefile library loader
+###########################################################################
+ifdef MOZILLA_DIR
+topORerr = $(MOZILLA_DIR)
+else
+topORerr = $(if $(topsrcdir),$(topsrcdir),$(error topsrcdir is not defined))
+endif
+
+ifdef USE_AUTOTARGETS_MK # mkdir_deps
+ include $(topORerr)/config/makefiles/autotargets.mk
+endif
+
+## copy(src, dst): recursive copy
+copy_dir = (cd $(1)/. && $(TAR) $(TAR_CREATE_FLAGS) - .) | (cd $(2)/. && tar -xf -)
diff --git a/config/makefiles/nonrecursive.mk b/config/makefiles/nonrecursive.mk
new file mode 100644
index 0000000000..498de568e7
--- /dev/null
+++ b/config/makefiles/nonrecursive.mk
@@ -0,0 +1,68 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+
+# The purpose of this file is to pull in non-recursive targets when performing
+# a partial tree (not top-level) build. This will allow people to continue to
+# build individual directories while some of the targets may not be normally
+# defined in that make file.
+#
+# Non-recursive targets are attached to existing make targets. The
+# NONRECURSIVE_TARGETS variable lists the make targets that modified. For
+# each target in this list, the NONRECURSIVE_TARGET_<target> variable will
+# contain a list of partial variable names. We will then look in variables
+# named NONRECURSIVE_TARGETS_<target>_<fragment>_* for information describing
+# how to evaluate non-recursive make targets.
+#
+# Targets are defined by the following variables:
+#
+# FILE - The make file to evaluate. This is equivalent to
+# |make -f <FILE>|
+# DIRECTORY - The directory whose Makefile to evaluate. This is
+# equivalent to |make -C <DIRECTORY>|.
+# TARGETS - Targets to evaluate in that make file.
+#
+# Only 1 of FILE or DIRECTORY may be defined.
+#
+# For example:
+#
+# NONRECURSIVE_TARGETS = export libs
+# NONRECURSIVE_TARGETS_export = headers
+# NONRECURSIVE_TARGETS_export_headers_FILE = /path/to/exports.mk
+# NONRECURSIVE_TARGETS_export_headers_TARGETS = $(DIST)/include/foo.h $(DIST)/include/bar.h
+# NONRECURSIVE_TARGETS_libs = cppsrcs
+# NONRECURSIVE_TARGETS_libs_cppsrcs_DIRECTORY = $(DEPTH)/foo
+# NONRECURSIVE_TARGETS_libs_cppsrcs_TARGETS = /path/to/foo.o /path/to/bar.o
+#
+# Will get turned into the following:
+#
+# exports::
+# $(MAKE) -C $(DEPTH) -f /path/to/exports.mk $(DIST)/include/foo.h $(DIST)/include/bar.h
+#
+# libs::
+# $(MAKE) -C $(DEPTH)/foo /path/to/foo.o /path/to/bar.o
+
+ifndef INCLUDED_NONRECURSIVE_MK
+
+define define_nonrecursive_target
+$(1)::
+ $$(MAKE) -C $(or $(4),$$(DEPTH)) $(addprefix -f ,$(3)) $(2)
+endef
+
+$(foreach target,$(NONRECURSIVE_TARGETS), \
+ $(foreach entry,$(NONRECURSIVE_TARGETS_$(target)), \
+ $(eval $(call define_nonrecursive_target, \
+ $(target), \
+ $(NONRECURSIVE_TARGETS_$(target)_$(entry)_TARGETS), \
+ $(NONRECURSIVE_TARGETS_$(target)_$(entry)_FILE), \
+ $(NONRECURSIVE_TARGETS_$(target)_$(entry)_DIRECTORY), \
+ )) \
+ ) \
+)
+
+INCLUDED_NONRECURSIVE_MK := 1
+endif
+
diff --git a/config/makefiles/target_binaries.mk b/config/makefiles/target_binaries.mk
new file mode 100644
index 0000000000..04999f8410
--- /dev/null
+++ b/config/makefiles/target_binaries.mk
@@ -0,0 +1,42 @@
+# -*- makefile -*-
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# 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/.
+
+ifndef NO_DIST_INSTALL
+
+ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
+PROGRAMS_EXECUTABLES = $(SIMPLE_PROGRAMS) $(PROGRAM)
+PROGRAMS_DEST ?= $(FINAL_TARGET)
+PROGRAMS_TARGET := target
+INSTALL_TARGETS += PROGRAMS
+endif
+
+ifdef LIBRARY
+ifdef DIST_INSTALL
+ifdef IS_COMPONENT
+$(error Shipping static component libs makes no sense.)
+endif
+endif # DIST_INSTALL
+endif # LIBRARY
+
+
+ifdef SHARED_LIBRARY
+SHARED_LIBRARY_FILES = $(SHARED_LIBRARY)
+SHARED_LIBRARY_DEST ?= $(FINAL_TARGET)$(if $(IS_COMPONENT),/components)
+SHARED_LIBRARY_TARGET = target
+INSTALL_TARGETS += SHARED_LIBRARY
+endif # SHARED_LIBRARY
+
+ifneq (,$(strip $(HOST_SIMPLE_PROGRAMS)$(HOST_PROGRAM)))
+HOST_PROGRAMS_EXECUTABLES = $(HOST_SIMPLE_PROGRAMS) $(HOST_PROGRAM)
+HOST_PROGRAMS_DEST ?= $(DIST)/host/bin
+HOST_PROGRAMS_TARGET = host
+INSTALL_TARGETS += HOST_PROGRAMS
+endif
+
+endif # !NO_DIST_INSTALL
+
+# EOF
diff --git a/config/makefiles/test/Makefile.in b/config/makefiles/test/Makefile.in
new file mode 100644
index 0000000000..6c66d820e9
--- /dev/null
+++ b/config/makefiles/test/Makefile.in
@@ -0,0 +1,98 @@
+# -*- makefile -*-
+#
+# 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/.
+
+STANDALONE_MAKEFILE := 1
+USE_AUTOTARGETS_MK = 1
+MAKEUTILS_UNIT_TEST = 1
+include $(topsrcdir)/config/makefiles/makeutils.mk
+
+dir-ts = .deps/test
+check-arglist = $(dir-ts)/arglist.ts
+check-autotargets = $(dir-ts)/autotargets_mk.ts
+check-XinY = $(dir-ts)/check_XinY_mk.ts
+check-tests =\
+ $(check-arglist) \
+ $(check-autotargets) \
+ $(check-XinY) \
+ $(NULL)
+
+
+##------------------_##
+##---] TARGETS [---##
+##------------------_##
+all::
+
+clean:
+ $(RM) $(check-tests)
+
+###########################################################################
+## Logic processed at compile time so be selective about when to test
+## $(MAKE) check VERBOSE=1
+ifneq ($(NULL),$(findstring check,$(MAKECMDGOALS))) #
+
+check-preqs =\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(check-tests) \
+ $(NULL)
+
+check:: $(check-preqs)
+ @true
+
+
+ifdef VERBOSE #{ gmake check VERBOSE=1
+ $(info ===========================================================================)
+ $(info Running test: $(MAKECMDGOALS): pwd=$(CURDIR))
+ $(info ===========================================================================)
+endif #}
+
+ifndef requiredfunction
+ $(error requiredfunction is not defined)
+endif
+
+
+##################
+check-XinY-preqs=\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(topsrcdir)/config/makefiles/makeutils.mk \
+ $(srcdir)/check_XinY.mk \
+ $(eval include $(srcdir)/check_XinY.mk) \
+ $(NULL)
+
+$(check-XinY): $(check-XinY-preqs)
+ @$(TOUCH) $@
+# </check-XinY.mk>
+
+
+###########################################################################
+## check-arglist.mk always invoked as a compile time test
+## maintain real file dependencies for use later on.
+check-arglist-preqs=\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(topsrcdir)/config/makefiles/makeutils.mk \
+ $(srcdir)/check-arglist.mk \
+ $(eval include $(srcdir)/check-arglist.mk) \
+ $(NULL)
+
+$(check-arglist): $(check-arglist-preqs)
+ @$(TOUCH) $@
+# </check-arglist.mk>
+
+
+###########################################################################
+# <CHECK: autotargets.mk>
+check-autotargets-preqs=\
+ $(call mkdir_deps,$(dir-ts)) \
+ $(topsrcdir)/config/makefiles/makeutils.mk \
+ $(topsrcdir)/config/makefiles/autotargets.mk \
+ $(srcdir)/check-autotargets.mk \
+ $(eval include $(srcdir)/check-autotargets.mk) \
+ $(NULL)
+
+$(check-autotargets): $(check-autotargets-preqs)
+ @$(TOUCH) $@
+# </CHECK: autotargets.mk>
+
+endif #} findstring MAKECMDGOAL
diff --git a/config/makefiles/test/check-arglist.mk b/config/makefiles/test/check-arglist.mk
new file mode 100644
index 0000000000..fb720ee42c
--- /dev/null
+++ b/config/makefiles/test/check-arglist.mk
@@ -0,0 +1,100 @@
+# -*- makefile -*-
+#
+# 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/.
+
+ifdef VERBOSE
+ $(warning loading test)
+endif
+
+
+$(call requiredfunction,getargv)
+$(call requiredfunction,subargv)
+$(call requiredfunction,istype isval isvar)
+
+# arg_scalar = [scalar|literal]
+arg_list = foo bar
+arg_ref = arg_list
+
+## Identify type of function argument(s)
+########################################
+ifneq (scalar,$(call istype,arg_scalar))
+ $(error istype(arg_scalar)=scalar, found [$(call istype,arg_scalar)])
+endif
+ifneq (list,$(call istype,arg_list))
+ $(error istype(arg_list)=list, found [$(call istype,arg_list)])
+endif
+ifneq (list,$(call istype,arg_ref))
+ $(error istype(arg_ref)=list, found [$(call istype,arg_ref)])
+endif
+
+## Type == scalar or a list of values
+#####################################
+ifneq (true,$(call isval,scalar))
+ $(error isval(scalar)=true, found [$(call isval,scalar)])
+endif
+ifneq ($(NULL),$(call isval,arg_list))
+ $(error isval(arg_list)=null, found [$(call isval,arg_list)])
+endif
+
+## type == reference: macro=>macro => $($(1))
+#############################################
+ifneq ($(NULL),$(call isvar,scalar))
+ $(error isvar(scalar)=$(NULL), found [$(call isvar,scalar)])
+endif
+ifneq (true,$(call isvar,arg_list))
+ $(error isvar(arg_list)=true, found [$(call isvar,arg_list)])
+endif
+ifneq (true,$(call isvar,arg_ref))
+ $(error isvar(arg_ref)=true, found [$(call isvar,arg_ref)])
+endif
+
+# Verify getargv expansion
+##########################
+ifneq (scalar,$(call getargv,scalar))
+ $(error getargv(scalar)=scalar, found [$(call getargv,scalar)])
+endif
+ifneq ($(arg_list),$(call getargv,arg_list))
+ $(error getargv(arg_list)=list, found [$(call getargv,arg_list)])
+endif
+ifneq (arg_list,$(call getargv,arg_ref))
+ $(error getargv(arg_ref)=list, found [$(call getargv,arg_ref)])
+endif
+
+###########################################################################
+##
+###########################################################################
+ifdef MANUAL_TEST #{
+ # For automated testing a callback is needed that can set an external status
+ # variable that can be tested. Syntax is tricky to get correct functionality.
+ ifdef VERBOSE
+ $(info )
+ $(info ===========================================================================)
+ $(info Running test: checkIfEmpty)
+ $(info ===========================================================================)
+ endif
+
+ #status =
+ #setTRUE =status=true
+ #setFALSE =status=$(NULL)
+ #$(call checkIfEmpty,setFALSE NULL)
+ #$(if $(status),$(error checkIfEmpty(xyz) failed))
+ #$(call checkIfEmpty,setTRUE xyz)
+ #$(if $(status),$(error checkIfEmpty(xyz) failed))
+ xyz=abc
+ $(info STATUS: warnIfEmpty - two vars)
+ $(call warnIfEmpty,foo xyz bar)
+ $(info STATUS: errorIfEmpty - on first var)
+ $(call errorIfEmpty,foo xyz bar)
+ $(error TEST FAILED: processing should not reach this point)
+endif #}
+
+# Verify subargv expansion
+##########################
+subargs=foo bar tans fans
+subargs_exp=tans fans
+subargs_found=$(call subargv,4,$(subargs))
+ifneq ($(subargs_exp),$(subargs_found))
+ $(error subargv(4,$(subargs)): expected [$(subargs_exp)] found [$(subargs_found)])
+endif
diff --git a/config/makefiles/test/check-autotargets.mk b/config/makefiles/test/check-autotargets.mk
new file mode 100644
index 0000000000..c103f1d02d
--- /dev/null
+++ b/config/makefiles/test/check-autotargets.mk
@@ -0,0 +1,84 @@
+# -*- makefile -*-
+#
+# 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/.
+
+ifdef VERBOSE
+ $(warning loading test)
+endif
+
+space=$(null) $(null)
+GENERATED_DIRS = bogus # test data
+
+undefine USE_AUTOTARGETS_MK
+undefine INCLUDED_AUTOTARGETS_MK
+include $(topsrcdir)/config/makefiles/autotargets.mk
+
+ifndef INCLUDED_AUTOTARGETS_MK
+ $(error autotargets.mk was not included
+endif
+
+$(call requiredfunction,mkdir_deps)
+
+
+# Verify test data populated makefile vars correctly
+vars = AUTO_DEPS GARBAGE_DIRS GENERATED_DIRS_DEPS
+$(foreach var,$(vars),$(call errorIfEmpty,$(var)))
+
+# Data should also be valid
+ifneq (bogus,$(findstring bogus,$(AUTO_DEPS)))
+ $(error AUTO_DEPS=[$(AUTO_DEPS)] is not set correctly)
+endif
+
+
+# relpath
+path := foo/bar.c
+exp := foo/.mkdir.done
+found := $(call mkdir_deps,$(dir $(path)))
+ifneq ($(exp),$(found))
+ $(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
+endif
+
+# abspath
+path := /foo//bar/
+exp := /foo/bar/.mkdir.done
+found := $(call mkdir_deps,$(path))
+ifneq ($(exp),$(found))
+ $(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
+endif
+
+
+## verify strip_slash
+#####################
+
+path := a/b//c///d////e/////
+exp := a/b/c/d/e/.mkdir.done
+found := $(call mkdir_deps,$(path))
+ifneq ($(exp),$(found))
+ $(error mkdir_deps($(path))=$(exp) not set correctly [$(found)])
+endif
+
+
+## verify mkdir_stem()
+######################
+path := verify/mkdir_stem
+pathD = $(call mkdir_deps,$(path))
+pathS = $(call mkdir_stem,$(pathD))
+exp := $(path)
+
+ifeq ($(pathD),$(pathS))
+ $(error mkdir_deps and mkdir_stem should not match [$(pathD)])
+endif
+ifneq ($(pathS),$(exp))
+ $(error mkdir_stem=[$(pathS)] != exp=[$(exp)])
+endif
+
+
+## Verify embedded whitespace has been protected
+path := a/b$(space)c//d
+exp := a/b$(space)c/d
+found := $(call slash_strip,$(path))
+ifneq ($(exp),$(found))
+ $(error slash_strip($(path))=$(exp) not set correctly [$(found)])
+endif
diff --git a/config/makefiles/test/check_XinY.mk b/config/makefiles/test/check_XinY.mk
new file mode 100644
index 0000000000..1e7a19f0e7
--- /dev/null
+++ b/config/makefiles/test/check_XinY.mk
@@ -0,0 +1,70 @@
+# -*- makefile -*-
+#
+# 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/.
+
+# Verify dependencies are available
+$(call requiredfunction,getargv subargv is_XinY errorifneq)
+
+ifdef VERBOSE
+ $(warning loading test)
+endif
+
+zero := 0
+one := 1
+
+# Verify 'invalid' is not matched
+val := invalid
+$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
+$(call errorifneq,$(zero),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(zero),$(words $(call is_XinY,clean%,$(val))))
+
+# verify strcmp('clean')
+val := clean
+$(call errorifneq,$(zero),$(words $(call is_XinY,foo,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean%,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,%clean,$(val))))
+
+# List match for 'clean'
+val := blah clean distclean FcleanG clean-level-1
+wanted := clean distclean clean-level-1
+$(call errorifneq,$(zero),$(words $(call is_XinY_debug,foo,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,clean,$(val))))
+$(call errorifneq,$(one),$(words $(call is_XinY,distclean,$(val))))
+
+# pattern match 'clean'
+# match: clean, distclean, clean-level-1
+# exclude: FcleanG
+TEST_MAKECMDGOALS := $(val)
+$(call errorifneq,3,$(words $(call isTargetStemClean)))
+
+TEST_MAKECMDGOALS := invalid
+$(call errorifneq,$(zero),$(words $(call isTargetStemClean)))
+
+
+#############################
+ifdef VERBOSE
+ $(call banner,Unit test: isTargetStem)
+endif
+
+# Verify list argument processing
+TEST_MAKECMDGOALS := echo
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := echo-123
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := show
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := show-123
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := show-123-echo
+$(call errorifneq,$(one),$(words $(call isTargetStem,echo,show)))
+
+TEST_MAKECMDGOALS := invalid
+$(call errorifneq,$(zero),$(words $(call isTargetStem,echo,show)))
+
diff --git a/config/makefiles/test/moz.build b/config/makefiles/test/moz.build
new file mode 100644
index 0000000000..28919c271d
--- /dev/null
+++ b/config/makefiles/test/moz.build
@@ -0,0 +1,6 @@
+# -*- Mode: python; 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/.
+
diff --git a/config/makefiles/xpidl/Makefile.in b/config/makefiles/xpidl/Makefile.in
new file mode 100644
index 0000000000..6329d34d1a
--- /dev/null
+++ b/config/makefiles/xpidl/Makefile.in
@@ -0,0 +1,93 @@
+# 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/.
+
+STANDALONE_MAKEFILE := 1
+
+include $(topsrcdir)/config/rules.mk
+
+# Building XPIDLs effectively consists of two steps:
+#
+# 1) Staging all .idl files to a common directory.
+# 2) Doing everything with the .idl files.
+#
+# Each .idl file is processed into a .h file and typelib information.
+# The .h file shares the same stem as the input file and is installed
+# in the common headers include directory.
+#
+# XPIDL files are logically grouped together by modules. The typelib
+# information for all XPIDLs in the same module is linked together into
+# an .xpt file having the name of the module.
+#
+# As an optimization to reduce overall CPU usage, we process all .idl
+# belonging to a module with a single command invocation. This prevents
+# redundant parsing of .idl files and significantly reduces CPU cycles.
+
+# For dependency files.
+idl_deps_dir := .deps
+
+dist_idl_dir := $(DIST)/idl
+dist_include_dir := $(DIST)/include
+process_py := $(topsrcdir)/python/mozbuild/mozbuild/action/xpidl-process.py
+
+# TODO we should use py_action, but that would require extra directories to be
+# in the virtualenv.
+%.xpt:
+ @echo "$(@F)"
+ $(PYTHON_PATH) $(PLY_INCLUDE) -I$(topsrcdir)/xpcom/idl-parser -I$(DEPTH)/xpcom/idl-parser/xpidl \
+ $(process_py) --cache-dir $(DEPTH)/xpcom/idl-parser/xpidl --depsdir $(idl_deps_dir) \
+ $(dist_idl_dir) $(dist_include_dir) $(@D) $(libxul_sdk_includes) \
+ $(basename $(notdir $@)) $($(basename $(notdir $@))_deps)
+# When some IDL is added or removed, if the actual IDL file was already, or
+# still is, in the tree, simple dependencies can't detect that the XPT needs
+# to be rebuilt.
+# Add the current value of $($(xpidl_module)_deps) in the depend file, such that
+# we can later check if the value has changed since last build, which will
+# indicate whether IDLs were added or removed.
+# Note that removing previously built files is not covered.
+ @echo $(basename $(notdir $@))_deps_built = $($(basename $(notdir $@))_deps) >> $(idl_deps_dir)/$(basename $(notdir $@)).pp
+
+# Chrome manifests may be written from several Makefiles at various times during
+# the build. The 'buildlist' action adds to the file if it already exists, but
+# if it does exist, make considers it to be up-to-date (as we have no inputs to
+# depend on). We use FORCE to ensure that we always add the interface manifest,
+# whether or not the chrome manifest already exists.
+%/chrome.manifest: FORCE
+ $(call py_action,buildlist,$@ 'manifest components/interfaces.manifest')
+
+chrome_manifests := @chrome_manifests@
+
+%/interfaces.manifest: Makefile
+ $(call py_action,buildlist,$@ $(foreach xpt,$(filter $*/%,$(registered_xpt_files)),'interfaces $(notdir $(xpt))'))
+
+interfaces_manifests := @interfaces_manifests@
+
+xpidl_modules := @xpidl_modules@
+registered_xpt_files := @registered_xpt_files@
+xpt_files := $(registered_xpt_files) @xpt_files@
+
+@xpidl_rules@
+
+depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
+
+GARBAGE += $(xpt_files) $(depends_files)
+
+ifdef COMPILE_ENVIRONMENT
+xpidl:: $(xpt_files) $(chrome_manifests) $(interfaces_manifests)
+endif
+
+$(xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir))
+
+-include $(depends_files)
+
+define xpt_deps
+$(1): $(call mkdir_deps,$(dir $(1)))
+$(1): $(addsuffix .idl,$(addprefix $(dist_idl_dir)/,$($(basename $(notdir $(1)))_deps)))
+ifneq ($($(basename $(notdir $(1)))_deps),$($(basename $(notdir $(1)))_deps_built))
+$(1): FORCE
+endif
+endef
+
+$(foreach xpt,$(xpt_files),$(eval $(call xpt_deps,$(xpt))))
+
+.PHONY: xpidl