1# Copyright (C) 2009 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15 16# Common utility functions. 17# 18# NOTE: All the functions here should be purely functional, i.e. avoid 19# using global variables or depend on the file system / environment 20# variables. This makes testing easier. 21 22# ----------------------------------------------------------------------------- 23# Macro : empty 24# Returns : an empty macro 25# Usage : $(empty) 26# ----------------------------------------------------------------------------- 27empty := 28 29# ----------------------------------------------------------------------------- 30# Macro : space 31# Returns : a single space 32# Usage : $(space) 33# ----------------------------------------------------------------------------- 34space := $(empty) $(empty) 35 36space4 := $(space)$(space)$(space)$(space) 37 38# ----------------------------------------------------------------------------- 39# Macro : comma 40# Returns : a single comma 41# Usage : $(comma) 42# ----------------------------------------------------------------------------- 43comma := , 44 45# ----------------------------------------------------------------------------- 46# Macro : colon 47# Returns : a single colon 48# Usage : $(colon) 49# ----------------------------------------------------------------------------- 50colon := : 51 52# ----------------------------------------------------------------------------- 53# Function : remove-duplicates 54# Arguments: a list 55# Returns : the list with duplicate items removed, order is preserved. 56# Usage : $(call remove-duplicates, <LIST>) 57# Note : This is equivalent to the 'uniq' function provided by GMSL, 58# however this implementation is non-recursive and *much* 59# faster. It will also not explode the stack with a lot of 60# items like 'uniq' does. 61# ----------------------------------------------------------------------------- 62remove-duplicates = $(strip \ 63 $(eval __uniq_ret :=) \ 64 $(foreach __uniq_item,$1,\ 65 $(if $(findstring $(__uniq_item),$(__uniq_ret)),,\ 66 $(eval __uniq_ret += $(__uniq_item))\ 67 )\ 68 )\ 69 $(__uniq_ret)) 70 71-test-remove-duplicates = \ 72 $(call test-expect,,$(call remove-duplicates))\ 73 $(call test-expect,foo bar,$(call remove-duplicates,foo bar))\ 74 $(call test-expect,foo bar,$(call remove-duplicates,foo bar foo bar))\ 75 $(call test-expect,foo bar,$(call remove-duplicates,foo foo bar bar bar)) 76 77# ----------------------------------------------------------------------------- 78# Function : clear-vars 79# Arguments: 1: list of variable names 80# 2: file where the variable should be defined 81# Returns : None 82# Usage : $(call clear-vars, VAR1 VAR2 VAR3...) 83# Rationale: Clears/undefines all variables in argument list 84# ----------------------------------------------------------------------------- 85clear-vars = $(foreach __varname,$1,$(eval $(__varname) := $(empty))) 86 87# ----------------------------------------------------------------------------- 88# Function : filter-by 89# Arguments: 1: list 90# 2: predicate function, will be called as $(call $2,<name>) 91# and it this returns a non-empty value, then <name> 92# will be appended to the result. 93# Returns : elements of $1 that satisfy the predicate function $2 94# ----------------------------------------------------------------------------- 95filter-by = $(strip \ 96 $(foreach __filter_by_n,$1,\ 97 $(if $(call $2,$(__filter_by_n)),$(__filter_by_n)))) 98 99-test-filter-by = \ 100 $(eval -local-func = $$(call seq,foo,$$1))\ 101 $(call test-expect,,$(call filter-by,,-local-func))\ 102 $(call test-expect,foo,$(call filter-by,foo,-local-func))\ 103 $(call test-expect,foo,$(call filter-by,foo bar,-local-func))\ 104 $(call test-expect,foo foo,$(call filter-by,aaa foo bar foo,-local-func))\ 105 $(eval -local-func = $$(call sne,foo,$$1))\ 106 $(call test-expect,,$(call filter-by,,-local-func))\ 107 $(call test-expect,,$(call filter-by,foo,-local-func))\ 108 $(call test-expect,bar,$(call filter-by,foo bar,-local-func))\ 109 $(call test-expect,aaa bar,$(call filter-by,aaa foo bar,-local-func)) 110 111# ----------------------------------------------------------------------------- 112# Function : filter-out-by 113# Arguments: 1: list 114# 2: predicate function, will be called as $(call $2,<name>) 115# and it this returns an empty value, then <name> 116# will be appended to the result. 117# Returns : elements of $1 that do not satisfy the predicate function $2 118# ----------------------------------------------------------------------------- 119filter-out-by = $(strip \ 120 $(foreach __filter_out_by_n,$1,\ 121 $(if $(call $2,$(__filter_out_by_n)),,$(__filter_out_by_n)))) 122 123-test-filter-out-by = \ 124 $(eval -local-func = $$(call seq,foo,$$1))\ 125 $(call test-expect,,$(call filter-out-by,,-local-func))\ 126 $(call test-expect,,$(call filter-out-by,foo,-local-func))\ 127 $(call test-expect,bar,$(call filter-out-by,foo bar,-local-func))\ 128 $(call test-expect,aaa bar,$(call filter-out-by,aaa foo bar foo,-local-func))\ 129 $(eval -local-func = $$(call sne,foo,$$1))\ 130 $(call test-expect,,$(call filter-out-by,,-local-func))\ 131 $(call test-expect,foo,$(call filter-out-by,foo,-local-func))\ 132 $(call test-expect,foo,$(call filter-out-by,foo bar,-local-func))\ 133 $(call test-expect,foo foo,$(call filter-out-by,aaa foo bar foo,-local-func)) 134 135# ----------------------------------------------------------------------------- 136# Function : find-first 137# Arguments: 1: list 138# 2: predicate function, will be called as $(call $2,<name>). 139# Returns : the first item of $1 that satisfies the predicate. 140# ----------------------------------------------------------------------------- 141find-first = $(firstword $(call filter-by,$1,$2)) 142 143-test-find-first.empty = \ 144 $(eval -local-pred = $$(call seq,foo,$$1))\ 145 $(call test-expect,,$(call find-first,,-local-pred))\ 146 $(call test-expect,,$(call find-first,bar,-local-pred)) 147 148-test-find-first.simple = \ 149 $(eval -local-pred = $$(call seq,foo,$$1))\ 150 $(call test-expect,foo,$(call find-first,foo,-local-pred))\ 151 $(call test-expect,foo,$(call find-first,aaa foo bar,-local-pred))\ 152 $(call test-expect,foo,$(call find-first,aaa foo foo bar,-local-pred)) 153 154# ----------------------------------------------------------------------------- 155# Function : parent-dir 156# Arguments: 1: path 157# Returns : Parent dir or path of $1, with final separator removed. 158# ----------------------------------------------------------------------------- 159ifeq ($(HOST_OS),windows) 160# On Windows, defining parent-dir is a bit more tricky because the 161# GNU Make $(dir ...) function doesn't return an empty string when it 162# reaches the top of the directory tree, and we want to enforce this to 163# avoid infinite loops. 164# 165# $(dir C:) -> C: (empty expected) 166# $(dir C:/) -> C:/ (empty expected) 167# $(dir C:\) -> C:\ (empty expected) 168# $(dir C:/foo) -> C:/ (correct) 169# $(dir C:\foo) -> C:\ (correct) 170# 171parent-dir = $(patsubst %/,%,$(strip \ 172 $(eval __dir_node := $(patsubst %/,%,$(subst \,/,$1)))\ 173 $(eval __dir_parent := $(dir $(__dir_node)))\ 174 $(filter-out $1,$(__dir_parent))\ 175 )) 176else 177parent-dir = $(patsubst %/,%,$(dir $(1:%/=%))) 178endif 179 180-test-parent-dir = \ 181 $(call test-expect,,$(call parent-dir))\ 182 $(call test-expect,.,$(call parent-dir,foo))\ 183 $(call test-expect,foo,$(call parent-dir,foo/bar))\ 184 $(call test-expect,foo,$(call parent-dir,foo/bar/)) 185 186# ----------------------------------------------------------------------------- 187# Strip any 'lib' prefix in front of a given string. 188# 189# Function : strip-lib-prefix 190# Arguments: 1: module name 191# Returns : module name, without any 'lib' prefix if any 192# Usage : $(call strip-lib-prefix,$(LOCAL_MODULE)) 193# ----------------------------------------------------------------------------- 194strip-lib-prefix = $(1:lib%=%) 195 196-test-strip-lib-prefix = \ 197 $(call test-expect,,$(call strip-lib-prefix,))\ 198 $(call test-expect,foo,$(call strip-lib-prefix,foo))\ 199 $(call test-expect,foo,$(call strip-lib-prefix,libfoo))\ 200 $(call test-expect,nolibfoo,$(call strip-lib-prefix,nolibfoo))\ 201 $(call test-expect,foolib,$(call strip-lib-prefix,foolib))\ 202 $(call test-expect,foo bar,$(call strip-lib-prefix,libfoo libbar)) 203 204# ----------------------------------------------------------------------------- 205# Left-justify input string with spaces to fill a width of 15. 206# Function: left-justify-quoted-15 207# Arguments: 1: Input text 208# Returns: A quoted string that can be used in command scripts to print 209# the left-justified input with host-echo. 210# 211# Usage: ---->@$(call host-echo, $(call left-justify-quoted-15,$(_TEXT)): Do stuff) 212# Where ----> is a TAB character. 213# ----------------------------------------------------------------------------- 214left-justify-quoted-15 = $(call -left-justify,$1,xxxxxxxxxxxxxxx) 215 216-test-left-justify-quoted-15 = \ 217 $(call test-expect," ",$(call left-justify-quoted-15,))\ 218 $(call test-expect,"Foo Bar ",$(call left-justify-quoted-15,Foo Bar))\ 219 $(call test-expect,"Very long string over 15 characters wide",$(strip \ 220 $(call left-justify-quoted-15,Very long string over 15 characters wide))) 221 222# Used internally to compute a quoted left-justified text string. 223# $1: Input string. 224# $2: A series of contiguous x's, its length determines the full width to justify to. 225# Return: A quoted string with the input text left-justified appropriately. 226-left-justify = $(strip \ 227 $(eval __lj_temp := $(subst $(space),x,$1))\ 228 $(foreach __lj_a,$(__gmsl_characters),$(eval __lj_temp := $$(subst $$(__lj_a),x,$(__lj_temp))))\ 229 $(eval __lj_margin := $$(call -justification-margin,$(__lj_temp),$2)))"$1$(subst x,$(space),$(__lj_margin))" 230 231-test-left-justify = \ 232 $(call test-expect,"",$(call -left-justify,,))\ 233 $(call test-expect,"foo",$(call -left-justify,foo,xxx))\ 234 $(call test-expect,"foo ",$(call -left-justify,foo,xxxx))\ 235 $(call test-expect,"foo ",$(call -left-justify,foo,xxxxxx))\ 236 $(call test-expect,"foo ",$(call -left-justify,foo,xxxxxxxxxxxx))\ 237 $(call test-expect,"very long string",$(call -left-justify,very long string,xxx))\ 238 239# Used internally to compute a justification margin. 240# Expects $1 to be defined to a string of consecutive x's (e.g. 'xxxx') 241# Expects $2 to be defined to a maximum string of x's (e.g. 'xxxxxxxxx') 242# Returns a string of x's such as $1 + $(result) is equal to $2 243# If $1 is larger than $2, return empty string.. 244-justification-margin = $(strip \ 245 $(if $2,\ 246 $(if $1,\ 247 $(call -justification-margin-inner,$1,$2),\ 248 $2\ 249 ),\ 250 $1)) 251 252-justification-margin-inner = $(if $(findstring $2,$1),,x$(call -justification-margin-inner,x$1,$2)) 253 254-test-justification-margin = \ 255 $(call test-expect,,$(call -justification-margin,,))\ 256 $(call test-expect,,$(call -justification-margin,xxx,xxx))\ 257 $(call test-expect,xxxxxx,$(call -justification-margin,,xxxxxx))\ 258 $(call test-expect,xxxxx,$(call -justification-margin,x,xxxxxx))\ 259 $(call test-expect,xxxx,$(call -justification-margin,xx,xxxxxx))\ 260 $(call test-expect,xxx,$(call -justification-margin,xxx,xxxxxx))\ 261 $(call test-expect,xx,$(call -justification-margin,xxxx,xxxxxx))\ 262 $(call test-expect,x,$(call -justification-margin,xxxxx,xxxxxx))\ 263 $(call test-expect,,$(call -justification-margin,xxxxxx,xxxxxx))\ 264 $(call test-expect,,$(call -justification-margin,xxxxxxxxxxx,xxxxxx))\ 265 266