1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# This allows us to work with the newline character:
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengdefine newline
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengendef
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengnewline := $(newline)
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# nl-escape
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: escape = $(call nl-escape[,escape])
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# This is used as the common way to specify
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# what should replace a newline when escaping
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# newlines; the default is a bizarre string.
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengnl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n)
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# escape-nl
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: escaped-text = $(call escape-nl,text[,escape])
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# GNU make's $(shell ...) function converts to a
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# single space each newline character in the output
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# produced during the expansion; this may not be
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# desirable.
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# The only solution is to change each newline into
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# something that won't be converted, so that the
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# information can be recovered later with
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# $(call unescape-nl...)
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengescape-nl = $(subst $(newline),$(call nl-escape,$(2)),$(1))
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# unescape-nl
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: text = $(call unescape-nl,escaped-text[,escape])
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# See escape-nl.
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengunescape-nl = $(subst $(call nl-escape,$(2)),$(newline),$(1))
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# shell-escape-nl
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: $(shell some-command | $(call shell-escape-nl[,escape]))
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Use this to escape newlines from within a shell call;
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# the default escape is a bizarre string.
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# NOTE: The escape is used directly as a string constant
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#       in an `awk' program that is delimited by shell
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#       single-quotes, so be wary of the characters
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#       that are chosen.
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengdefine shell-escape-nl
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengawk 'NR==1 {t=$$0} NR>1 {t=t "$(nl-escape)" $$0} END {printf t}'
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengendef
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# shell-unescape-nl
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: $(shell some-command | $(call shell-unescape-nl[,escape]))
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Use this to unescape newlines from within a shell call;
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# the default escape is a bizarre string.
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# NOTE: The escape is used directly as an extended regular
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#       expression constant in an `awk' program that is
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#       delimited by shell single-quotes, so be wary
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#       of the characters that are chosen.
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# (The bash shell has a bug where `{gsub(...),...}' is
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  misinterpreted as a brace expansion; this can be
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  overcome by putting a space between `{' and `gsub').
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengdefine shell-unescape-nl
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengawk 'NR==1 {t=$$0} NR>1 {t=t "\n" $$0} END { gsub(/$(nl-escape)/,"\n",t); printf t }'
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengendef
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# escape-for-shell-sq
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: embeddable-text = $(call escape-for-shell-sq,text)
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# This function produces text that is suitable for
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# embedding in a shell string that is delimited by
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# single-quotes.
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengescape-for-shell-sq =  $(subst ','\'',$(1))
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# shell-sq
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: single-quoted-and-escaped-text = $(call shell-sq,text)
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengshell-sq = '$(escape-for-shell-sq)'
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# shell-wordify
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: wordified-text = $(call shell-wordify,text)
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# For instance:
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  |define text
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  |hello
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  |world
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  |endef
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  |
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  |target:
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  |	echo $(call shell-wordify,$(text))
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# At least GNU make gets confused by expanding a newline
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# within the context of a command line of a makefile rule
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# (this is in constrast to a `$(shell ...)' function call,
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# which can handle it just fine).
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# This function avoids the problem by producing a string
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# that works as a shell word, regardless of whether or
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# not it contains a newline.
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# If the text to be wordified contains a newline, then
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# an intrictate shell command substitution is constructed
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# to render the text as a single line; when the shell
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# processes the resulting escaped text, it transforms
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# it into the original unescaped text.
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# If the text does not contain a newline, then this function
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# produces the same results as the `$(shell-sq)' function.
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengshell-wordify = $(if $(findstring $(newline),$(1)),$(_sw-esc-nl),$(shell-sq))
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengdefine _sw-esc-nl
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng"$$(echo $(call escape-nl,$(shell-sq),$(2)) | $(call shell-unescape-nl,$(2)))"
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengendef
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# is-absolute
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: bool-value = $(call is-absolute,path)
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengis-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y)
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# lookup
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: absolute-executable-path-or-empty = $(call lookup,path)
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# (It's necessary to use `sh -c' because GNU make messes up by
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  trying too hard and getting things wrong).
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chenglookup = $(call unescape-nl,$(shell sh -c $(_l-sh)))
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng_l-sh = $(call shell-sq,command -v $(shell-sq) | $(call shell-escape-nl,))
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# is-executable
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: bool-value = $(call is-executable,path)
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# (It's necessary to use `sh -c' because GNU make messes up by
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#  trying too hard and getting things wrong).
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengis-executable = $(call _is-executable-helper,$(shell-sq))
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng_is-executable-helper = $(shell sh -c $(_is-executable-sh))
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng_is-executable-sh = $(call shell-sq,test -f $(1) -a -x $(1) && echo y)
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# get-executable
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: absolute-executable-path-or-empty = $(call get-executable,path)
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# The goal is to get an absolute path for an executable;
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# the `command -v' is defined by POSIX, but it's not
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# necessarily very portable, so it's only used if
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# relative path resolution is requested, as determined
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# by the presence of a leading `/'.
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengget-executable = $(if $(1),$(if $(is-absolute),$(_ge-abspath),$(lookup)))
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng_ge-abspath = $(if $(is-executable),$(1))
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# get-supplied-or-default-executable
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengdefine get-executable-or-default
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengendef
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng_ge_attempt = $(or $(get-executable),$(_gea_warn),$(call _gea_err,$(2)))
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng_gea_warn = $(warning The path '$(1)' is not executable.)
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng_gea_err  = $(if $(1),$(error Please set '$(1)' appropriately))
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# try-cc
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng# Usage: option = $(call try-cc, source-to-build, cc-options)
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengtry-cc = $(shell sh -c						  \
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	'TMP="$(OUTPUT)$(TMPOUT).$$$$";				  \
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 echo "$(1)" |						  \
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	 rm -f "$$TMP"')
189