• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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# 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# -----------------------------------------------------------------------------
55remove-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# -----------------------------------------------------------------------------
78clear-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# -----------------------------------------------------------------------------
88filter-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# -----------------------------------------------------------------------------
112filter-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# -----------------------------------------------------------------------------
134find-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# -----------------------------------------------------------------------------
152parent-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# -----------------------------------------------------------------------------
168strip-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# -----------------------------------------------------------------------------
188left-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