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