summaryrefslogtreecommitdiffstats
path: root/core/node_fns.mk
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitb6c1cf6de79035f58b512f4400db458c8401379a (patch)
tree68979db37c85b499bc384e4ac337ed1424baab51 /core/node_fns.mk
downloadbuild-b6c1cf6de79035f58b512f4400db458c8401379a.zip
build-b6c1cf6de79035f58b512f4400db458c8401379a.tar.gz
build-b6c1cf6de79035f58b512f4400db458c8401379a.tar.bz2
Initial Contribution
Diffstat (limited to 'core/node_fns.mk')
-rw-r--r--core/node_fns.mk238
1 files changed, 238 insertions, 0 deletions
diff --git a/core/node_fns.mk b/core/node_fns.mk
new file mode 100644
index 0000000..202bb0d
--- /dev/null
+++ b/core/node_fns.mk
@@ -0,0 +1,238 @@
+#
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Clears a list of variables using ":=".
+#
+# E.g.,
+# $(call clear-var-list,A B C)
+# would be the same as:
+# A :=
+# B :=
+# C :=
+#
+# $(1): list of variable names to clear
+#
+define clear-var-list
+$(foreach v,$(1),$(eval $(v):=))
+endef
+
+#
+# Copies a list of variables into another list of variables.
+# The target list is the same as the source list, but has
+# a dotted prefix affixed to it.
+#
+# E.g.,
+# $(call copy-var-list, PREFIX, A B)
+# would be the same as:
+# PREFIX.A := $(A)
+# PREFIX.B := $(B)
+#
+# $(1): destination prefix
+# $(2): list of variable names to copy
+#
+define copy-var-list
+$(foreach v,$(2),$(eval $(strip $(1)).$(v):=$($(v))))
+endef
+
+#
+# Moves a list of variables into another list of variables.
+# The variable names differ by a prefix. After moving, the
+# source variable is cleared.
+#
+# NOTE: Spaces are not allowed around the prefixes.
+#
+# E.g.,
+# $(call move-var-list,SRC,DST,A B)
+# would be the same as:
+# DST.A := $(SRC.A)
+# SRC.A :=
+# DST.B := $(SRC.B)
+# SRC.B :=
+#
+# $(1): source prefix
+# $(2): destination prefix
+# $(3): list of variable names to move
+#
+define move-var-list
+$(foreach v,$(3), \
+ $(eval $(2).$(v) := $($(1).$(v))) \
+ $(eval $(1).$(v) :=) \
+ )
+endef
+
+#
+# $(1): haystack
+# $(2): needle
+#
+# Guarantees that needle appears at most once in haystack,
+# without changing the order of other elements in haystack.
+# If needle appears multiple times, only the first occurrance
+# will survive.
+#
+# How it works:
+#
+# - Stick everything in haystack into a single word,
+# with "|||" separating the words.
+# - Replace occurrances of "|||$(needle)|||" with "||| |||",
+# breaking haystack back into multiple words, with spaces
+# where needle appeared.
+# - Add needle between the first and second words of haystack.
+# - Replace "|||" with spaces, breaking haystack back into
+# individual words.
+#
+empty :=
+space := $(empty) $(empty)
+define uniq-word
+$(strip \
+ $(if $(filter $(2),$(1)), \
+ $(eval h := |||$(subst $(space),|||,$(strip $(1)))|||) \
+ $(eval h := $(subst |||$(strip $(2))|||,|||$(space)|||,$(h))) \
+ $(eval h := $(word 1,$(h)) $(2) $(wordlist 2,9999,$(h))) \
+ $(subst |||,$(space),$(h)) \
+ , \
+ $(1) \
+ ))
+endef
+
+INHERIT_TAG := @inherit:
+
+#
+# Walks through the list of variables, each qualified by the prefix,
+# and finds instances of words beginning with INHERIT_TAG. Scrape
+# off INHERIT_TAG from each matching word, and return the sorted,
+# unique set of those words.
+#
+# E.g., given
+# PREFIX.A := A $(INHERIT_TAG)aaa B C
+# PREFIX.B := B $(INHERIT_TAG)aaa C $(INHERIT_TAG)bbb D E
+# Then
+# $(call get-inherited-nodes,PREFIX,A B)
+# returns
+# aaa bbb
+#
+# $(1): variable prefix
+# $(2): list of variables to check
+#
+define get-inherited-nodes
+$(sort \
+ $(subst $(INHERIT_TAG),, \
+ $(filter $(INHERIT_TAG)%, \
+ $(foreach v,$(2),$($(1).$(v))) \
+ )))
+endef
+
+#
+# for each variable ( (prefix + name) * vars ):
+# get list of inherited words; if not empty:
+# for each inherit:
+# replace the first occurrence with (prefix + inherited + var)
+# clear the source var so we can't inherit the value twice
+#
+# $(1): context prefix
+# $(2): name of this node
+# $(3): list of variable names
+#
+define _expand-inherited-values
+ $(foreach v,$(3), \
+ $(eval ### "Shorthand for the name of the target variable") \
+ $(eval _eiv_tv := $(1).$(2).$(v)) \
+ $(eval ### "Get the list of nodes that this variable inherits") \
+ $(eval _eiv_i := \
+ $(sort \
+ $(patsubst $(INHERIT_TAG)%,%, \
+ $(filter $(INHERIT_TAG)%, $($(_eiv_tv)) \
+ )))) \
+ $(foreach i,$(_eiv_i), \
+ $(eval ### "Make sure that this inherit appears only once") \
+ $(eval $(_eiv_tv) := \
+ $(call uniq-word,$($(_eiv_tv)),$(INHERIT_TAG)$(i))) \
+ $(eval ### "Expand the inherit tag") \
+ $(eval $(_eiv_tv) := \
+ $(patsubst $(INHERIT_TAG)$(i),$($(1).$(i).$(v)), \
+ $($(_eiv_tv)))) \
+ $(eval ### "Clear the child so DAGs don't create duplicate entries" ) \
+ $(eval $(1).$(i).$(v) :=) \
+ $(eval ### "If we just inherited ourselves, it's a cycle.") \
+ $(if $(filter $(INHERIT_TAG)$(2),$($(_eiv_tv))), \
+ $(warning Cycle detected between "$(2)" and "$(i)" for context "$(1)") \
+ $(error import of "$(2)" failed) \
+ ) \
+ ) \
+ ) \
+ $(eval _eiv_tv :=) \
+ $(eval _eiv_i :=)
+endef
+
+#
+# $(1): context prefix
+# $(2): makefile representing this node
+# $(3): list of node variable names
+#
+#TODO: keep a debug stack to make error messages more helpful
+define _import-node
+ $(call clear-var-list, $(3))
+ $(eval include $(2))
+ $(call copy-var-list, $(1).$(2), $(3))
+ $(call clear-var-list, $(3))
+
+ $(eval $(1).$(2).inherited := \
+ $(call get-inherited-nodes,$(1).$(2),$(3)))
+ $(call _import-nodes-inner,$(1),$($(1).$(2).inherited),$(3))
+
+ $(call _expand-inherited-values,$(1),$(2),$(3))
+
+ $(eval $(1).$(2).inherited :=)
+endef
+
+#
+# $(1): context prefix
+# $(2): list of makefiles representing nodes to import
+# $(3): list of node variable names
+#
+#TODO: Make the "does not exist" message more helpful;
+# should print out the name of the file trying to include it.
+define _import-nodes-inner
+ $(foreach _in,$(2), \
+ $(if $(wildcard $(_in)), \
+ $(if $($(1).$(_in).seen), \
+ $(eval ### "skipping already-imported $(_in)") \
+ , \
+ $(eval $(1).$(_in).seen := true) \
+ $(call _import-node,$(1),$(strip $(_in)),$(3)) \
+ ) \
+ , \
+ $(error $(1): "$(_in)" does not exist) \
+ ) \
+ )
+endef
+
+#
+# $(1): output list variable name, like "PRODUCTS" or "DEVICES"
+# $(2): list of makefiles representing nodes to import
+# $(3): list of node variable names
+#
+define import-nodes
+$(if \
+ $(foreach _in,$(2), \
+ $(eval _node_import_context := _nic.$(1).[[$(_in)]]) \
+ $(call _import-nodes-inner,$(_node_import_context),$(_in),$(3)) \
+ $(call move-var-list,$(_node_import_context).$(_in),$(1).$(_in),$(3)) \
+ $(eval _node_import_context :=) \
+ $(eval $(1) := $($(1)) $(_in)) \
+ ) \
+,)
+endef