• 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# 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