]>
Commit | Line | Data |
---|---|---|
d4b033a0 MT |
1 | # ---------------------------------------------------------------------------- |
2 | # | |
3 | # GNU Make Standard Library (GMSL) | |
4 | # | |
5 | # A library of functions to be used with GNU Make's $(call) that | |
6 | # provides functionality not available in standard GNU Make. | |
7 | # | |
8 | # Copyright (c) 2005-2007 John Graham-Cumming | |
9 | # | |
10 | # This file is part of GMSL | |
11 | # | |
12 | # Redistribution and use in source and binary forms, with or without | |
13 | # modification, are permitted provided that the following conditions | |
14 | # are met: | |
15 | # | |
16 | # Redistributions of source code must retain the above copyright | |
17 | # notice, this list of conditions and the following disclaimer. | |
18 | # | |
19 | # Redistributions in binary form must reproduce the above copyright | |
20 | # notice, this list of conditions and the following disclaimer in the | |
21 | # documentation and/or other materials provided with the distribution. | |
22 | # | |
23 | # Neither the name of the John Graham-Cumming nor the names of its | |
24 | # contributors may be used to endorse or promote products derived from | |
25 | # this software without specific prior written permission. | |
26 | # | |
27 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
28 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
29 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
30 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
31 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
32 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
33 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
34 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
35 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
36 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
37 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
38 | # POSSIBILITY OF SUCH DAMAGE. | |
39 | # | |
40 | # ---------------------------------------------------------------------------- | |
41 | ||
42 | # This is the GNU Make Standard Library version number as a list with | |
43 | # three items: major, minor, revision | |
44 | ||
45 | gmsl_version := 1 0 11 | |
46 | ||
47 | # Used to output warnings and error from the library, it's possible to | |
48 | # disable any warnings or errors by overriding these definitions | |
49 | # manually or by setting GMSL_NO_WARNINGS or GMSL_NO_ERRORS | |
50 | ||
51 | __gmsl_name := GNU Make Standard Library | |
52 | __gmsl_warning = $(warning $(__gmsl_name): $1) | |
53 | __gmsl_error = $(error $(__gmsl_name): $1) | |
54 | ||
55 | ifdef GMSL_NO_WARNINGS | |
56 | __gmsl_warning := | |
57 | endif | |
58 | ifdef GMSL_NO_ERRORS | |
59 | __gmsl_error := | |
60 | endif | |
61 | ||
62 | # If GMSL_TRACE is enabled then calls to the library functions are | |
63 | # traced to stdout using warning messages with their arguments | |
64 | ||
65 | ifdef GMSL_TRACE | |
66 | __gmsl_tr1 = $(warning $0('$1')) | |
67 | __gmsl_tr2 = $(warning $0('$1','$2')) | |
68 | __gmsl_tr3 = $(warning $0('$1','$2','$3')) | |
69 | else | |
70 | __gmsl_tr1 := | |
71 | __gmsl_tr2 := | |
72 | __gmsl_tr3 := | |
73 | endif | |
74 | ||
75 | # Figure out whether we have $(eval) or not (GNU Make 3.80 and above) | |
76 | # if we do not then output a warning message, if we do then some | |
77 | # functions will be enabled. | |
78 | ||
79 | __gmsl_have_eval := $(false) | |
80 | __gmsl_ignore := $(eval __gmsl_have_eval := $(true)) | |
81 | ||
82 | # If this is being run with Electric Cloud's emake then warn that | |
83 | # their $(eval) support is incomplete. | |
84 | ||
85 | ifdef ECLOUD_BUILD_ID | |
86 | $(warning You are using Electric Cloud's emake which has incomplete $$(eval) support) | |
87 | __gmsl_have_eval := $(false) | |
88 | endif | |
89 | ||
90 | # See if we have $(lastword) (GNU Make 3.81 and above) | |
91 | ||
92 | __gmsl_have_lastword := $(lastword $(false) $(true)) | |
93 | ||
94 | # See if we have native or and and (GNU Make 3.81 and above) | |
95 | ||
96 | __gmsl_have_or := $(if $(filter-out undefined, \ | |
97 | $(origin or)),$(call or,$(true),$(false))) | |
98 | __gmsl_have_and := $(if $(filter-out undefined, \ | |
99 | $(origin and)),$(call and,$(true),$(true))) | |
100 | ||
101 | ifneq ($(__gmsl_have_eval),$(true)) | |
102 | $(call __gmsl_warning,GNU Make $(MAKE_VERSION) does not support $$$$(eval): some functions disabled) | |
103 | endif | |
104 | ||
105 | # ---------------------------------------------------------------------------- | |
106 | # Function: gmsl_compatible | |
107 | # Arguments: List containing the desired library version number (maj min rev) | |
108 | # Returns: $(true) if this version of the library is compatible | |
109 | # with the requested version number, otherwise $(false) | |
110 | # ---------------------------------------------------------------------------- | |
111 | gmsl_compatible = $(strip \ | |
112 | $(if $(call gt,$(word 1,$1),$(word 1,$(gmsl_version))), \ | |
113 | $(false), \ | |
114 | $(if $(call lt,$(word 1,$1),$(word 1,$(gmsl_version))), \ | |
115 | $(true), \ | |
116 | $(if $(call gt,$(word 2,$1),$(word 2,$(gmsl_version))), \ | |
117 | $(false), \ | |
118 | $(if $(call lt,$(word 2,$1),$(word 2,$(gmsl_version))), \ | |
119 | $(true), \ | |
120 | $(call lte,$(word 3,$1),$(word 3,$(gmsl_version)))))))) | |
121 | ||
122 | # ########################################################################### | |
123 | # LOGICAL OPERATORS | |
124 | # ########################################################################### | |
125 | ||
126 | # not is defined in gmsl | |
127 | ||
128 | # ---------------------------------------------------------------------------- | |
129 | # Function: and | |
130 | # Arguments: Two boolean values | |
131 | # Returns: Returns $(true) if both of the booleans are true | |
132 | # ---------------------------------------------------------------------------- | |
133 | ifneq ($(__gmsl_have_and),$(true)) | |
134 | and = $(__gmsl_tr2)$(if $1,$(if $2,$(true),$(false)),$(false)) | |
135 | endif | |
136 | ||
137 | # ---------------------------------------------------------------------------- | |
138 | # Function: or | |
139 | # Arguments: Two boolean values | |
140 | # Returns: Returns $(true) if either of the booleans is true | |
141 | # ---------------------------------------------------------------------------- | |
142 | ifneq ($(__gmsl_have_or),$(true)) | |
143 | or = $(__gmsl_tr2)$(if $1$2,$(true),$(false)) | |
144 | endif | |
145 | ||
146 | # ---------------------------------------------------------------------------- | |
147 | # Function: xor | |
148 | # Arguments: Two boolean values | |
149 | # Returns: Returns $(true) if exactly one of the booleans is true | |
150 | # ---------------------------------------------------------------------------- | |
151 | xor = $(__gmsl_tr2)$(if $1,$(if $2,$(false),$(true)),$(if $2,$(true),$(false))) | |
152 | ||
153 | # ---------------------------------------------------------------------------- | |
154 | # Function: nand | |
155 | # Arguments: Two boolean values | |
156 | # Returns: Returns value of 'not and' | |
157 | # ---------------------------------------------------------------------------- | |
158 | nand = $(__gmsl_tr2)$(if $1,$(if $2,$(false),$(true)),$(true)) | |
159 | ||
160 | # ---------------------------------------------------------------------------- | |
161 | # Function: nor | |
162 | # Arguments: Two boolean values | |
163 | # Returns: Returns value of 'not or' | |
164 | # ---------------------------------------------------------------------------- | |
165 | nor = $(__gmsl_tr2)$(if $1$2,$(false),$(true)) | |
166 | ||
167 | # ---------------------------------------------------------------------------- | |
168 | # Function: xnor | |
169 | # Arguments: Two boolean values | |
170 | # Returns: Returns value of 'not xor' | |
171 | # ---------------------------------------------------------------------------- | |
172 | xnor =$(__gmsl_tr2)$(if $1,$(if $2,$(true),$(false)),$(if $2,$(false),$(true))) | |
173 | ||
174 | # ########################################################################### | |
175 | # LIST MANIPULATION FUNCTIONS | |
176 | # ########################################################################### | |
177 | ||
178 | # ---------------------------------------------------------------------------- | |
179 | # Function: first (same as LISP's car, or head) | |
180 | # Arguments: 1: A list | |
181 | # Returns: Returns the first element of a list | |
182 | # ---------------------------------------------------------------------------- | |
183 | first = $(__gmsl_tr1)$(firstword $1) | |
184 | ||
185 | # ---------------------------------------------------------------------------- | |
186 | # Function: last | |
187 | # Arguments: 1: A list | |
188 | # Returns: Returns the last element of a list | |
189 | # ---------------------------------------------------------------------------- | |
190 | ifeq ($(__gmsl_have_lastword),$(true)) | |
191 | last = $(__gmsl_tr1)$(lastword $1) | |
192 | else | |
193 | last = $(__gmsl_tr1)$(if $1,$(word $(words $1),$1)) | |
194 | endif | |
195 | ||
196 | # ---------------------------------------------------------------------------- | |
197 | # Function: rest (same as LISP's cdr, or tail) | |
198 | # Arguments: 1: A list | |
199 | # Returns: Returns the list with the first element removed | |
200 | # ---------------------------------------------------------------------------- | |
201 | rest = $(__gmsl_tr1)$(wordlist 2,$(words $1),$1) | |
202 | ||
203 | # ---------------------------------------------------------------------------- | |
204 | # Function: chop | |
205 | # Arguments: 1: A list | |
206 | # Returns: Returns the list with the last element removed | |
207 | # ---------------------------------------------------------------------------- | |
208 | chop = $(__gmsl_tr1)$(wordlist 2,$(words $1),x $1) | |
209 | ||
210 | # ---------------------------------------------------------------------------- | |
211 | # Function: map | |
212 | # Arguments: 1: Name of function to $(call) for each element of list | |
213 | # 2: List to iterate over calling the function in 1 | |
214 | # Returns: The list after calling the function on each element | |
215 | # ---------------------------------------------------------------------------- | |
216 | map = $(__gmsl_tr2)$(strip $(foreach a,$2,$(call $1,$a))) | |
217 | ||
218 | # ---------------------------------------------------------------------------- | |
219 | # Function: pairmap | |
220 | # Arguments: 1: Name of function to $(call) for each pair of elements | |
221 | # 2: List to iterate over calling the function in 1 | |
222 | # 3: Second list to iterate over calling the function in 1 | |
223 | # Returns: The list after calling the function on each pair of elements | |
224 | # ---------------------------------------------------------------------------- | |
225 | pairmap = $(strip $(__gmsl_tr3)\ | |
226 | $(if $2$3,$(call $1,$(call first,$2),$(call first,$3)) \ | |
227 | $(call pairmap,$1,$(call rest,$2),$(call rest,$3)))) | |
228 | ||
229 | # ---------------------------------------------------------------------------- | |
230 | # Function: leq | |
231 | # Arguments: 1: A list to compare against... | |
232 | # 2: ...this list | |
233 | # Returns: Returns $(true) if the two lists are identical | |
234 | # ---------------------------------------------------------------------------- | |
235 | leq = $(__gmsl_tr2)$(strip $(if $(call seq,$(words $1),$(words $2)), \ | |
236 | $(call __gmsl_list_equal,$1,$2),$(false))) | |
237 | ||
238 | __gmsl_list_equal = $(if $(strip $1), \ | |
239 | $(if $(call seq,$(call first,$1),$(call first,$2)), \ | |
240 | $(call __gmsl_list_equal, \ | |
241 | $(call rest,$1), \ | |
242 | $(call rest,$2)), \ | |
243 | $(false)), \ | |
244 | $(true)) | |
245 | ||
246 | # ---------------------------------------------------------------------------- | |
247 | # Function: lne | |
248 | # Arguments: 1: A list to compare against... | |
249 | # 2: ...this list | |
250 | # Returns: Returns $(true) if the two lists are different | |
251 | # ---------------------------------------------------------------------------- | |
252 | lne = $(__gmsl_tr2)$(call not,$(call leq,$1,$2)) | |
253 | ||
254 | # ---------------------------------------------------------------------------- | |
255 | # Function: reverse | |
256 | # Arguments: 1: A list to reverse | |
257 | # Returns: The list with its elements in reverse order | |
258 | # ---------------------------------------------------------------------------- | |
259 | reverse =$(__gmsl_tr1)$(strip $(if $1,$(call reverse,$(call rest,$1)) \ | |
260 | $(call first,$1))) | |
261 | ||
262 | # ---------------------------------------------------------------------------- | |
263 | # Function: uniq | |
264 | # Arguments: 1: A list from which to remove repeated elements | |
265 | # Returns: The list with duplicate elements removed without reordering | |
266 | # ---------------------------------------------------------------------------- | |
267 | uniq = $(strip $(__gmsl_tr1)$(if $1,$(call uniq,$(call chop,$1)) \ | |
268 | $(if $(filter $(call last,$1),$(call chop,$1)),,$(call last,$1)))) | |
269 | ||
270 | # ---------------------------------------------------------------------------- | |
271 | # Function: length | |
272 | # Arguments: 1: A list | |
273 | # Returns: The number of elements in the list | |
274 | # ---------------------------------------------------------------------------- | |
275 | length = $(__gmsl_tr1)$(words $1) | |
276 | ||
277 | # ########################################################################### | |
278 | # STRING MANIPULATION FUNCTIONS | |
279 | # ########################################################################### | |
280 | ||
281 | # Helper function that translates any GNU Make 'true' value (i.e. a | |
282 | # non-empty string) to our $(true) | |
283 | ||
284 | __gmsl_make_bool = $(if $(strip $1),$(true),$(false)) | |
285 | ||
286 | # ---------------------------------------------------------------------------- | |
287 | # Function: seq | |
288 | # Arguments: 1: A string to compare against... | |
289 | # 2: ...this string | |
290 | # Returns: Returns $(true) if the two strings are identical | |
291 | # ---------------------------------------------------------------------------- | |
292 | seq = $(__gmsl_tr2)$(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),$(false),$(true)) | |
293 | ||
294 | # ---------------------------------------------------------------------------- | |
295 | # Function: sne | |
296 | # Arguments: 1: A string to compare against... | |
297 | # 2: ...this string | |
298 | # Returns: Returns $(true) if the two strings are not the same | |
299 | # ---------------------------------------------------------------------------- | |
300 | sne = $(__gmsl_tr2)$(call not,$(call seq,$1,$2)) | |
301 | ||
302 | # ---------------------------------------------------------------------------- | |
303 | # Function: split | |
304 | # Arguments: 1: The character to split on | |
305 | # 2: A string to split | |
306 | # Returns: Splits a string into a list separated by spaces at the split | |
307 | # character in the first argument | |
308 | # ---------------------------------------------------------------------------- | |
309 | split = $(__gmsl_tr2)$(strip $(subst $1, ,$2)) | |
310 | ||
311 | # ---------------------------------------------------------------------------- | |
312 | # Function: merge | |
313 | # Arguments: 1: The character to put between fields | |
314 | # 2: A list to merge into a string | |
315 | # Returns: Merges a list into a single string, list elements are separated | |
316 | # by the character in the first argument | |
317 | # ---------------------------------------------------------------------------- | |
318 | merge = $(__gmsl_tr2)$(strip $(if $2, \ | |
319 | $(if $(call seq,1,$(words $2)), \ | |
320 | $2,$(call first,$2)$1$(call merge,$1,$(call rest,$2))))) | |
321 | ||
322 | ifdef __gmsl_have_eval | |
323 | # ---------------------------------------------------------------------------- | |
324 | # Function: tr | |
325 | # Arguments: 1: The list of characters to translate from | |
326 | # 2: The list of characters to translate to | |
327 | # 3: The text to translate | |
328 | # Returns: Returns the text after translating characters | |
329 | # ---------------------------------------------------------------------------- | |
330 | tr = $(strip $(__gmsl_tr3)$(call assert_no_dollar,$0,$1$2$3) \ | |
331 | $(eval __gmsl_t := $3) \ | |
332 | $(foreach c, \ | |
333 | $(join $(addsuffix :,$1),$2), \ | |
334 | $(eval __gmsl_t := \ | |
335 | $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)), \ | |
336 | $(__gmsl_t))))$(__gmsl_t)) | |
337 | ||
338 | # Common character classes for use with the tr function. Each of | |
339 | # these is actually a variable declaration and must be wrapped with | |
340 | # $() or ${} to be used. | |
341 | ||
342 | [A-Z] := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z # | |
343 | [a-z] := a b c d e f g h i j k l m n o p q r s t u v w x y z # | |
344 | [0-9] := 0 1 2 3 4 5 6 7 8 9 # | |
345 | [A-F] := A B C D E F # | |
346 | ||
347 | # ---------------------------------------------------------------------------- | |
348 | # Function: uc | |
349 | # Arguments: 1: Text to upper case | |
350 | # Returns: Returns the text in upper case | |
351 | # ---------------------------------------------------------------------------- | |
352 | uc = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(call tr,$([a-z]),$([A-Z]),$1) | |
353 | ||
354 | # ---------------------------------------------------------------------------- | |
355 | # Function: lc | |
356 | # Arguments: 1: Text to lower case | |
357 | # Returns: Returns the text in lower case | |
358 | # ---------------------------------------------------------------------------- | |
359 | lc = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(call tr,$([A-Z]),$([a-z]),$1) | |
360 | ||
361 | # ---------------------------------------------------------------------------- | |
362 | # Function: strlen | |
363 | # Arguments: 1: A string | |
364 | # Returns: Returns the length of the string | |
365 | # ---------------------------------------------------------------------------- | |
366 | __gmsl_characters := A B C D E F G H I J K L M N O P Q R S T U V W X Y Z | |
367 | __gmsl_characters += a b c d e f g h i j k l m n o p q r s t u v w x y z | |
368 | __gmsl_characters += 0 1 2 3 4 5 6 7 8 9 | |
369 | __gmsl_characters += ` ~ ! @ \# $$ % ^ & * ( ) - _ = + | |
370 | __gmsl_characters += { } [ ] \ : ; ' " < > , . / ? | | |
371 | ||
372 | # Aside: if you read the above you might think that the lower-case | |
373 | # letter x is missing, and that that's an error. It is missing, but | |
374 | # it's not an error. __gmsl_characters is used by the strlen | |
375 | # function. strlen works by transforming every character and space | |
376 | # into the letter x and then counting the x's. Since there's no need | |
377 | # to transform x into x I omitted it. | |
378 | ||
379 | # This results in __gmsl_space containing just a space | |
380 | ||
381 | __gmsl_space := | |
382 | __gmsl_space += | |
383 | ||
384 | strlen = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(strip $(eval __temp := $(subst $(__gmsl_space),x,$1))$(foreach a,$(__gmsl_characters),$(eval __temp := $$(subst $$a,x,$(__temp))))$(eval __temp := $(subst x,x ,$(__temp)))$(words $(__temp))) | |
385 | ||
386 | # This results in __gmsl_newline containing just a newline | |
387 | ||
388 | define __gmsl_newline | |
389 | ||
390 | ||
391 | endef | |
392 | ||
393 | # This results in __gmsl_tab containing a tab | |
394 | ||
395 | __gmsl_tab := # | |
396 | ||
397 | # ---------------------------------------------------------------------------- | |
398 | # Function: substr | |
399 | # Arguments: 1: A string | |
400 | # 2: Start position (first character is 1) | |
401 | # 3: End position (inclusive) | |
402 | # Returns: A substring. | |
403 |