@@ -169,41 +169,38 @@ EOF
169
169
# Done with temporary Makefile construction.
170
170
# ::::::::::::::::::::::::::::::::::::::::::
171
171
172
- # Handle positional command arguments if any were provided :
172
+ # Runfile command argument handling :
173
173
if [[ " $* " != *' --print-makefile '* ]] \
174
174
&& [[ " $* " != *' --create-makefile '* ]] \
175
175
&& [[ " $* " != *' --overwrite-makefile '* ]]
176
+ # If outputting makefile, skip this section.
176
177
then
177
- buffer="$( cat " ${makefile} " ) "
178
- # Cases where no named or positional arguments were provided:
179
- # Replace $( var) $( @) $( 1) $( 2) etc. in script with empty backtick expression ` ` .
180
- # This seems odd, but it allows tasks like: [[ -n $( 1) ]] && echo "$1 "
181
- # to work whether or not $1 positional arg was provided. Without it, make will
182
- # error out due to the script being interpreted as [[ -n ]]. With standard
183
- # quotes instead of backticks, expressions like echo "$1 " will inadvertently
184
- # print the quotes.
185
- if ! (( ${# cmd_args[@]} ))
186
- then
187
- # Case where no named arguments were provided: replace $( abc) $( xyz) etc.
188
- # Note: There must be at least one lowercase letter [a-z] in these matches,
189
- # because otherwise we'd replace built in Make vars like $( MAKEFILE_LIST)
190
- # which we want to leave alone.
191
- buffer="$( echo " ${buffer} " | sed -E ' s!\$\([a-zA-Z0-9_]*[a-z][a-zA-Z0-9_]*\)!``!g' ) "
192
- fi
193
- if ! (( ${# pos_args[@]} ))
194
- then
195
- # Case where no positional arguments were provided: replace $( @) $( 1) $( 2) etc.
196
- buffer="${buffer// \$ ([0-9@])/ \`\` } "
197
- else
198
- # Replace $( @) in script with concatenation of all positional args:
199
- buffer="${buffer// \$ (@ )/ ${pos_args[*]} } "
200
- # Replace $( 1) $( 2) etc. in script with each individual positional arg:
201
- for arg in "${pos_args[@]} "
202
- do
203
- (( pos_arg_idx++ )) || true
204
- buffer="${buffer// \$ (${pos_arg_idx} )/ ${arg} } "
205
- done
206
- fi
178
+ buffer="$(
179
+ sed -E ' s!(\$\((@|[0-9]+|[a-zA-Z][a-zA-Z0-9_]*)\))!\`printf ' " '%s' '\1'" ' \`!g' \
180
+ " ${makefile} "
181
+ ) "
182
+ # Wrap all Runfile argument patterns in printf, eg. $( @) -> ` printf ' %s' ' $(@)' `
183
+ # This resolves issues with Make arg-handling behavior when args are omitted.
184
+ # For example: [[ -n $( arg) ]] && echo "${arg} "
185
+ # This will error if $( arg) is not specified, because Make executes: [[ -n ]]
186
+ # With printf-wrapping: [[ -n ` printf ' %s' ' $(arg)' ` ]] && echo "${arg} "
187
+ # Now if $( arg) is not specified, Make executes: [[ -n ` printf ' %s' ' ' ` ]]
188
+ # which is perfectly valid. We can't simply wrap args in quotes, because then
189
+ # the quotes would be included when args are interpolated within strings. eg.
190
+ # "hello: $( world) " -> "hello: '$( world) '" -> "hello: ''" (unwanted quotes)
191
+
192
+ # Replace $( @) in script with concatenation of all positional args:
193
+ buffer="${buffer// \$ (@ )/ ${pos_args[*]} } "
194
+ # Note: Perform this replacement even if no positional args were provided,
195
+ # because otherwise default Make behavior interpolates ${cmd} in place of $( @) .
196
+
197
+ # Replace $( 1) $( 2) etc. in script with each individual positional arg:
198
+ for arg in "${pos_args[@]} "
199
+ do
200
+ (( pos_arg_idx++ )) || true
201
+ buffer="${buffer// \$ (${pos_arg_idx} )/ ${arg} } "
202
+ done
203
+
207
204
# Write buffer back to temporary makefile:
208
205
echo "${buffer} " > "${makefile} "
209
206
fi
0 commit comments