You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
274 lines
8.3 KiB
274 lines
8.3 KiB
4 months ago
|
#
|
||
|
# 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.
|
||
|
#
|
||
|
define uniq-word
|
||
|
$(strip \
|
||
|
$(if $(filter-out 0 1,$(words $(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 node variable names
|
||
|
# $(4): list of single value variable names (subset of $(3))
|
||
|
#
|
||
|
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)) \
|
||
|
)))) \
|
||
|
$(eval ### "Whether this variable should only take a single value") \
|
||
|
$(eval _eiv_sv := $(filter $(v),$(4))) \
|
||
|
$(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 ### "The expanded value, empty if we want a single value and have one") \
|
||
|
$(eval _eiv_ev := \
|
||
|
$(if $(and $(_eiv_sv),$(filter-out $(INHERIT_TAG)%,$($(_eiv_tv)))),,\
|
||
|
$($(1).$(i).$(v)) \
|
||
|
) \
|
||
|
) \
|
||
|
$(eval ### "Expand the inherit tag") \
|
||
|
$(eval $(_eiv_tv) := \
|
||
|
$(strip $(patsubst $(INHERIT_TAG)$(i),$(_eiv_ev),$($(_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
|
||
|
# $(4): list of single value variable names (subset of $(3))
|
||
|
#
|
||
|
# _include_stack contains the list of included files, with the most recent files first.
|
||
|
define _import-node
|
||
|
$(eval _include_stack := $(2) $$(_include_stack))
|
||
|
$(call clear-var-list, $(3))
|
||
|
$(eval LOCAL_PATH := $(patsubst %/,%,$(dir $(2))))
|
||
|
$(eval MAKEFILE_LIST :=)
|
||
|
$(call dump-import-start,$(_include_stack))
|
||
|
$(call dump-config-vals,$(2),before)
|
||
|
$(eval include $(2))
|
||
|
$(call dump-import-done,$(_include_stack))
|
||
|
$(call dump-config-vals,$(2),after)
|
||
|
$(eval _included := $(filter-out $(2),$(MAKEFILE_LIST)))
|
||
|
$(eval MAKEFILE_LIST :=)
|
||
|
$(eval LOCAL_PATH :=)
|
||
|
$(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),$(4))
|
||
|
|
||
|
$(eval $(1).$(2).inherited :=)
|
||
|
$(eval _include_stack := $(wordlist 2,9999,$$(_include_stack)))
|
||
|
endef
|
||
|
|
||
|
#
|
||
|
# This will generate a warning for _included above
|
||
|
# $(if $(_included), \
|
||
|
# $(eval $(warning product spec file: $(2)))\
|
||
|
# $(foreach _inc,$(_included),$(eval $(warning $(space)$(space)$(space)includes: $(_inc)))),)
|
||
|
#
|
||
|
|
||
|
#
|
||
|
# $(1): context prefix
|
||
|
# $(2): list of makefiles representing nodes to import
|
||
|
# $(3): list of node variable names
|
||
|
# $(4): list of single value variable names (subset of $(3))
|
||
|
#
|
||
|
#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),$(4)) \
|
||
|
) \
|
||
|
, \
|
||
|
$(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
|
||
|
# $(4): list with subset of variable names that take only a single value, instead
|
||
|
# of the default list semantics
|
||
|
#
|
||
|
define import-nodes
|
||
|
$(call dump-phase-start,$(1),$(2),$(3),$(4),build/make/core/node_fns.mk) \
|
||
|
$(if \
|
||
|
$(foreach _in,$(2), \
|
||
|
$(eval _node_import_context := _nic.$(1).[[$(_in)]]) \
|
||
|
$(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \
|
||
|
should be empty here: $(_include_stack))),) \
|
||
|
$(eval _include_stack := ) \
|
||
|
$(call _import-nodes-inner,$(_node_import_context),$(_in),$(3),$(4)) \
|
||
|
$(call move-var-list,$(_node_import_context).$(_in),$(1).$(_in),$(3)) \
|
||
|
$(eval _node_import_context :=) \
|
||
|
$(eval $(1) := $($(1)) $(_in)) \
|
||
|
$(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \
|
||
|
should be empty here: $(_include_stack))),) \
|
||
|
) \
|
||
|
,) \
|
||
|
$(call dump-phase-end,build/make/core/node_fns.mk)
|
||
|
endef
|