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 # ----------------------------------------------------------------------------- 27 empty := 28 29 # ----------------------------------------------------------------------------- 30 # Macro : space 31 # Returns : a single space 32 # Usage : $(space) 33 # ----------------------------------------------------------------------------- 34 space := $(empty) $(empty) 35 36 space4 := $(space)$(space)$(space)$(space) 37 38 # ----------------------------------------------------------------------------- 39 # Macro : comma 40 # Returns : a single comma 41 # Usage : $(comma) 42 # ----------------------------------------------------------------------------- 43 comma := , 44 45 # ----------------------------------------------------------------------------- 46 # Function : remove-duplicates 47 # Arguments: a list 48 # Returns : the list with duplicate items removed, order is preserved. 49 # Usage : $(call remove-duplicates, <LIST>) 50 # Note : This is equivalent to the 'uniq' function provided by GMSL, 51 # however this implementation is non-recursive and *much* 52 # faster. It will also not explode the stack with a lot of 53 # items like 'uniq' does. 54 # ----------------------------------------------------------------------------- 55 remove-duplicates = $(strip \ 56 $(eval __uniq_ret :=) \ 57 $(foreach __uniq_item,$1,\ 58 $(if $(findstring $(__uniq_item),$(__uniq_ret)),,\ 59 $(eval __uniq_ret += $(__uniq_item))\ 60 )\ 61 )\ 62 $(__uniq_ret)) 63 64 -test-remove-duplicates = \ 65 $(call test-expect,,$(call remove-duplicates))\ 66 $(call test-expect,foo bar,$(call remove-duplicates,foo bar))\ 67 $(call test-expect,foo bar,$(call remove-duplicates,foo bar foo bar))\ 68 $(call test-expect,foo bar,$(call remove-duplicates,foo foo bar bar bar)) 69 70 # ----------------------------------------------------------------------------- 71 # Function : clear-vars 72 # Arguments: 1: list of variable names 73 # 2: file where the variable should be defined 74 # Returns : None 75 # Usage : $(call clear-vars, VAR1 VAR2 VAR3...) 76 # Rationale: Clears/undefines all variables in argument list 77 # ----------------------------------------------------------------------------- 78 clear-vars = $(foreach __varname,$1,$(eval $(__varname) := $(empty))) 79 80 # ----------------------------------------------------------------------------- 81 # Function : filter-by 82 # Arguments: 1: list 83 # 2: predicate function, will be called as $(call $2,<name>) 84 # and it this returns a non-empty value, then <name> 85 # will be appended to the result. 86 # Returns : elements of $1 that satisfy the predicate function $2 87 # ----------------------------------------------------------------------------- 88 filter-by = $(strip \ 89 $(foreach __filter_by_n,$1,\ 90 $(if $(call $2,$(__filter_by_n)),$(__filter_by_n)))) 91 92 -test-filter-by = \ 93 $(eval -local-func = $$(call seq,foo,$$1))\ 94 $(call test-expect,,$(call filter-by,,-local-func))\ 95 $(call test-expect,foo,$(call filter-by,foo,-local-func))\ 96 $(call test-expect,foo,$(call filter-by,foo bar,-local-func))\ 97 $(call test-expect,foo foo,$(call filter-by,aaa foo bar foo,-local-func))\ 98 $(eval -local-func = $$(call sne,foo,$$1))\ 99 $(call test-expect,,$(call filter-by,,-local-func))\ 100 $(call test-expect,,$(call filter-by,foo,-local-func))\ 101 $(call test-expect,bar,$(call filter-by,foo bar,-local-func))\ 102 $(call test-expect,aaa bar,$(call filter-by,aaa foo bar,-local-func)) 103 104 # ----------------------------------------------------------------------------- 105 # Function : filter-out-by 106 # Arguments: 1: list 107 # 2: predicate function, will be called as $(call $2,<name>) 108 # and it this returns an empty value, then <name> 109 # will be appended to the result. 110 # Returns : elements of $1 that do not satisfy the predicate function $2 111 # ----------------------------------------------------------------------------- 112 filter-out-by = $(strip \ 113 $(foreach __filter_out_by_n,$1,\ 114 $(if $(call $2,$(__filter_out_by_n)),,$(__filter_out_by_n)))) 115 116 -test-filter-out-by = \ 117 $(eval -local-func = $$(call seq,foo,$$1))\ 118 $(call test-expect,,$(call filter-out-by,,-local-func))\ 119 $(call test-expect,,$(call filter-out-by,foo,-local-func))\ 120 $(call test-expect,bar,$(call filter-out-by,foo bar,-local-func))\ 121 $(call test-expect,aaa bar,$(call filter-out-by,aaa foo bar foo,-local-func))\ 122 $(eval -local-func = $$(call sne,foo,$$1))\ 123 $(call test-expect,,$(call filter-out-by,,-local-func))\ 124 $(call test-expect,foo,$(call filter-out-by,foo,-local-func))\ 125 $(call test-expect,foo,$(call filter-out-by,foo bar,-local-func))\ 126 $(call test-expect,foo foo,$(call filter-out-by,aaa foo bar foo,-local-func)) 127 128 # ----------------------------------------------------------------------------- 129 # Function : find-first 130 # Arguments: 1: list 131 # 2: predicate function, will be called as $(call $2,<name>). 132 # Returns : the first item of $1 that satisfies the predicate. 133 # ----------------------------------------------------------------------------- 134 find-first = $(firstword $(call filter-by,$1,$2)) 135 136 -test-find-first.empty = \ 137 $(eval -local-pred = $$(call seq,foo,$$1))\ 138 $(call test-expect,,$(call find-first,,-local-pred))\ 139 $(call test-expect,,$(call find-first,bar,-local-pred)) 140 141 -test-find-first.simple = \ 142 $(eval -local-pred = $$(call seq,foo,$$1))\ 143 $(call test-expect,foo,$(call find-first,foo,-local-pred))\ 144 $(call test-expect,foo,$(call find-first,aaa foo bar,-local-pred))\ 145 $(call test-expect,foo,$(call find-first,aaa foo foo bar,-local-pred)) 146 147 # ----------------------------------------------------------------------------- 148 # Function : parent-dir 149 # Arguments: 1: path 150 # Returns : Parent dir or path of $1, with final separator removed. 151 # ----------------------------------------------------------------------------- 152 parent-dir = $(patsubst %/,%,$(dir $(1:%/=%))) 153 154 -test-parent-dir = \ 155 $(call test-expect,,$(call parent-dir))\ 156 $(call test-expect,.,$(call parent-dir,foo))\ 157 $(call test-expect,foo,$(call parent-dir,foo/bar))\ 158 $(call test-expect,foo,$(call parent-dir,foo/bar/)) 159 160 # ----------------------------------------------------------------------------- 161 # Strip any 'lib' prefix in front of a given string. 162 # 163 # Function : strip-lib-prefix 164 # Arguments: 1: module name 165 # Returns : module name, without any 'lib' prefix if any 166 # Usage : $(call strip-lib-prefix,$(LOCAL_MODULE)) 167 # ----------------------------------------------------------------------------- 168 strip-lib-prefix = $(1:lib%=%) 169 170 -test-strip-lib-prefix = \ 171 $(call test-expect,,$(call strip-lib-prefix,))\ 172 $(call test-expect,foo,$(call strip-lib-prefix,foo))\ 173 $(call test-expect,foo,$(call strip-lib-prefix,libfoo))\ 174 $(call test-expect,nolibfoo,$(call strip-lib-prefix,nolibfoo))\ 175 $(call test-expect,foolib,$(call strip-lib-prefix,foolib))\ 176 $(call test-expect,foo bar,$(call strip-lib-prefix,libfoo libbar)) 177 178 # ----------------------------------------------------------------------------- 179 # Left-justify input string with spaces to fill a width of 15. 180 # Function: left-justify-quoted-15 181 # Arguments: 1: Input text 182 # Returns: A quoted string that can be used in command scripts to print 183 # the left-justified input with host-echo. 184 # 185 # Usage: ---->@$(call host-echo, $(call left-justify-quoted-15,$(_TEXT)): Do stuff) 186 # Where ----> is a TAB character. 187 # ----------------------------------------------------------------------------- 188 left-justify-quoted-15 = $(call -left-justify,$1,xxxxxxxxxxxxxxx) 189 190 -test-left-justify-quoted-15 = \ 191 $(call test-expect," ",$(call left-justify-quoted-15,))\ 192 $(call test-expect,"Foo Bar ",$(call left-justify-quoted-15,Foo Bar))\ 193 $(call test-expect,"Very long string over 15 characters wide",$(strip \ 194 $(call left-justify-quoted-15,Very long string over 15 characters wide))) 195 196 # Used internally to compute a quoted left-justified text string. 197 # $1: Input string. 198 # $2: A series of contiguous x's, its length determines the full width to justify to. 199 # Return: A quoted string with the input text left-justified appropriately. 200 -left-justify = $(strip \ 201 $(eval __lj_temp := $(subst $(space),x,$1))\ 202 $(foreach __lj_a,$(__gmsl_characters),$(eval __lj_temp := $$(subst $$(__lj_a),x,$(__lj_temp))))\ 203 $(eval __lj_margin := $$(call -justification-margin,$(__lj_temp),$2)))"$1$(subst x,$(space),$(__lj_margin))" 204 205 -test-left-justify = \ 206 $(call test-expect,"",$(call -left-justify,,))\ 207 $(call test-expect,"foo",$(call -left-justify,foo,xxx))\ 208 $(call test-expect,"foo ",$(call -left-justify,foo,xxxx))\ 209 $(call test-expect,"foo ",$(call -left-justify,foo,xxxxxx))\ 210 $(call test-expect,"foo ",$(call -left-justify,foo,xxxxxxxxxxxx))\ 211 $(call test-expect,"very long string",$(call -left-justify,very long string,xxx))\ 212 213 # Used internally to compute a justification margin. 214 # Expects $1 to be defined to a string of consecutive x's (e.g. 'xxxx') 215 # Expects $2 to be defined to a maximum string of x's (e.g. 'xxxxxxxxx') 216 # Returns a string of x's such as $1 + $(result) is equal to $2 217 # If $1 is larger than $2, return empty string.. 218 -justification-margin = $(strip \ 219 $(if $2,\ 220 $(if $1,\ 221 $(call -justification-margin-inner,$1,$2),\ 222 $2\ 223 ),\ 224 $1)) 225 226 -justification-margin-inner = $(if $(findstring $2,$1),,x$(call -justification-margin-inner,x$1,$2)) 227 228 -test-justification-margin = \ 229 $(call test-expect,,$(call -justification-margin,,))\ 230 $(call test-expect,,$(call -justification-margin,xxx,xxx))\ 231 $(call test-expect,xxxxxx,$(call -justification-margin,,xxxxxx))\ 232 $(call test-expect,xxxxx,$(call -justification-margin,x,xxxxxx))\ 233 $(call test-expect,xxxx,$(call -justification-margin,xx,xxxxxx))\ 234 $(call test-expect,xxx,$(call -justification-margin,xxx,xxxxxx))\ 235 $(call test-expect,xx,$(call -justification-margin,xxxx,xxxxxx))\ 236 $(call test-expect,x,$(call -justification-margin,xxxxx,xxxxxx))\ 237 $(call test-expect,,$(call -justification-margin,xxxxxx,xxxxxx))\ 238 $(call test-expect,,$(call -justification-margin,xxxxxxxxxxx,xxxxxx))\ 239 240