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