1# 2# Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved. 3# 4# SPDX-License-Identifier: BSD-3-Clause 5# 6 7space := 8space := $(space) $(space) 9comma := , 10 11null := � 12 13lparen := ( 14rparen := ) 15 16compat-path = $(subst $(space),$(null),$(1)) 17decompat-path = $(subst $(null), ,$(1)) 18 19absolute-path = $(call decompat-path,$(abspath $(call compat-path,$(1)))) 20real-path = $(call decompat-path,$(realpath $(call compat-path,$(1)))) 21 22file-name = $(call decompat-path,$(notdir $(call compat-path,$(1)))) 23directory-name = $(call decompat-path,$(dir $(call compat-path,$(1)))) 24 25escape-shell = '$(subst ','\'',$(1))' 26 27# 28# The grouped-target symbol. Grouped targets are not supported on versions of 29# GNU Make <= 4.2, which was most recently packaged with Ubuntu 20.04. 30# 31 32& := $(if $(filter grouped-target,$(.FEATURES)),&) 33 34# 35# Upper-case a string value. 36# 37# Parameters: 38# 39# - $(1): The string to upper-case. 40# 41# Example usage: 42# 43# $(call uppercase,HeLlO wOrLd) # "HELLO WORLD" 44# 45 46uppercase = $(shell echo $(call escape-shell,$(1)) | tr '[:lower:]' '[:upper:]') 47 48# 49# Lower-case a string value. 50# 51# Parameters: 52# 53# - $(1): The string to lower-case. 54# 55# Example usage: 56# 57# $(call lowercase,HeLlO wOrLd) # "hello world" 58# 59 60lowercase = $(shell echo $(call escape-shell,$(1)) | tr '[:upper:]' '[:lower:]') 61 62# 63# Determine the "truthiness" of a value. 64# 65# Parameters: 66# 67# - $(1): The value to determine the truthiness of. 68# 69# A value is considered to be falsy if it is: 70# 71# - empty, or 72# - equal to "0", "N", "NO", "F" or "FALSE" after upper-casing. 73# 74# If the value is truthy then the value is returned as-is, otherwise no value 75# is returned. 76# 77# Example usage: 78# 79# truthy := y 80# truthy-bool := $(call bool,$(truthy)) # "y" 81# 82# falsy := n 83# falsy-bool := $(call bool,$(falsy)) # <empty> 84# 85 86bool = $(filter-out 0 n no f false,$(call lowercase,$(1))) 87 88# 89# Determine the "truthiness" of a value, returning 0 or 1. 90# 91# Parameters: 92# 93# - $(1): The value to determine the truthiness of. 94# 95# A value is considered to be falsy if it is: 96# 97# - empty, or 98# - equal to "0", "N", "NO", "F" or "FALSE" after upper-casing. 99# 100# If the value is truthy then the value is returned as-is, otherwise no value 101# is returned. 102# 103# Example usage: 104# 105# truthy := y 106# truthy-bool := $(call bool,$(truthy)) # "1" 107# 108# falsy := n 109# falsy-bool := $(call bool,$(falsy)) # "0" 110# 111 112bool-01 = $(if $(call bool,$(1)),1,0) 113 114# 115# Determine whether a variable is defined or not. 116# 117# Parameters: 118# 119# - $(1): The variable to check. 120# 121# Example usage: 122# 123# xyz-defined := $(call defined,xyz) # <empty> 124# 125# xyz := 126# xyz-defined := $(call defined,xyz) # <non-empty> 127# 128# xyz := hello 129# xyz-defined := $(call defined,xyz) # <non-empty> 130# 131 132defined = $(call bool,$(filter-out undefined,$(origin $(1)))) 133 134# 135# Extract include directories from compiler flags and convert them to absolute 136# paths. 137# 138# Parameters: 139# 140# - $(1): A list of C compiler flags. 141# 142# Example: 143# 144# includes := $(call include-dirs, -nostdlib -Iinclude-dir) # /absolute/path/to/include-dir 145# 146 147include-dirs-pattern := $(call escape-shell,-I\s*("[^"]*"|'[^']*'|\S+)) 148include-dirs = $(shell \ 149 printf '%s' $(call escape-shell,$1) | \ 150 perl -nle 'print $$1 while /'$(include-dirs-pattern)'/g' | \ 151 xargs realpath \ 152) 153 154# 155# Determine the path to a program. 156# 157# Parameters: 158# 159# - $(1): The program to search for. 160# 161# Example usage: 162# 163# path-to-gcc := $(call which,gcc) # "/usr/bin/gcc" 164# 165 166which = $(shell command -v $(call escape-shell,$(1)) 2>/dev/null) 167 168# 169# Temporarily bind variables while expanding text (scoped "with"). 170# 171# Creates temporary variable bindings, expands a body of text with those 172# bindings in effect, then restores all affected variables to their previous 173# values and flavors (or undefines them if they did not exist). This provides a 174# "let"-style scope for variable assignments during text expansion. 175# 176# This function is modelled on the `let` function introduced in GNU Make 4.4: 177# 178# https://www.gnu.org/software/make/manual/html_node/Let-Function.html 179# 180# Binding specifiers (space-separated in `$(1)`): 181# 182# - l:name Bind from the word list in `$(2)`. Bindings are applied 183# left-to-right; the last `l` binding receives all remaining words 184# (which may be empty). If there are more `l` names than words, the 185# excess names are bound to empty values. 186# 187# - p:name Bind from subsequent call arguments (`$(2)`, `$(3)`, `$(4)`, ...), 188# in left-to-right order. If `l` bindings are present, these 189# arguments instead start from `$(3)`, following the word list. 190# 191# - name Treated as `l:name`. 192# 193# Parameters: 194# 195# - $(1): Space-separated binding specifiers. 196# - $(2): The list value used by `l` bindings, if present. 197# - $(2|3..N-1): Values for `p` bindings, in order (optional). 198# - $(N): The text to expand with the temporary bindings active. 199# 200# Evaluation and restoration: 201# 202# - All function arguments in Make are expanded at the call site. The text 203# must therefore be escaped (write `$$` to produce a literal `$`), or 204# supplied via `$(value ...)` to avoid premature expansion. 205# 206# - Whitespace in `l`-style bindings is processed in terms of Make words; if 207# you need to preserve whitespace then prefer `p` bindings. 208# 209# - Variables are assigned as simple (`:=`) during the text expansion. After 210# the text is expanded, each variable is restored to its previous state with 211# its original flavor (simple or recursive), or undefined if it did not 212# exist. Origins (e.g., command line, environment) are not preserved. 213# 214# Examples: 215# 216# # Basic list destructuring (two names from a list): 217# $(call with,foo bar,10 20,$$(foo) $$(bar)) # "10 20" 218# 219# # Last list binding receives the remainder: 220# $(call with,head tail,1 2 3 4,[$$(head)] [$$(tail)]) # "[1] [2 3 4]" 221# 222# # Extra list names bind to empty values: 223# $(call with,x y,9,x=<$$(x)> y=<$$(y)>) # "x=<9> y=<>" 224# 225# # Parameter-only bindings start in `$(2)`: 226# $(call with,p:x p:y,foo,bar,$$(x)-$$(y)) # "foo-bar" 227# 228# # Parameter bindings start in `$(3)` when list bindings are specified: 229# $(call with,l:lhs p:op l:rhs,10 20,+,$$(lhs) $$(op) $$(rhs)) # "10 + 20" 230# 231# # Variables are restored after expansion, with flavor preserved: 232# 233# x := outer-x 234# y = outer-y 235# 236# $(info $(call with,x y,inner-x inner-y,$$(x) $$(y))) # "inner-x inner-y" 237# 238# $(info $(x) ($(flavor x))) # "outer-x (simple)" 239# $(info $(y) ($(flavor y))) # "outer-y (recursive)" 240# 241# # Passing the text via `$(value ...)` to avoid `$$` escaping: 242# 243# text = [$(head)] [$(tail)] 244# $(call with,head tail,1 2 3 4,$(value text)) # "[1] [2 3 4]" 245# 246# # Nested usage: 247# 248# $(call with,a b,foo bar, \ 249# $$(call with,c d,baz qux,$$$$(a) $$$$(b) $$$$(c) $$$$(d))) 250# # "foo bar baz qux" 251# 252 253with = $(with.ns.push)$(eval $(value with.core))$(with.ns.pop) 254 255with.ns = with.ns.$(with.ns.stack.head) 256 257with.ns.stack := 258with.ns.stack.head = $(words $(with.ns.stack)) 259 260with.ns.push = $(eval with.ns.stack += $(with.ns.stack.head)) 261with.ns.pop = $($(with.ns).result)$(eval $(value with.ns.pop.1)) 262 263define with.ns.pop.1 = 264 $(foreach variable,$(filter $(with.ns).%,$(.VARIABLES)),$\ 265 $(eval undefine $(variable))) 266 267 with.ns.stack := $(wordlist 2,$(with.ns.stack.head),$(with.ns.stack)) 268endef 269 270with.bind.norm = $\ 271 $(if $(findstring :,$(1)),$\ 272 $(or $(filter l: p:,$(firstword $(subst :,: ,$(1)))),$\ 273 $(error invalid binding specifier: $(1)))$\ 274 $(or $(filter-out %:,$(word 2,$(subst :,: ,$(1)))),$\ 275 $(error invalid binding specifier: $(1))),$\ 276 l:$(1)) 277 278with.bind.kind = $(word 1,$(subst :, ,$(call with.bind.norm,$(1)))) 279with.bind.name = $(word 2,$(subst :, ,$(call with.bind.norm,$(1)))) 280 281define with.core = 282 # Parse and record binding list/kinds/names from `$(1)` 283 $(with.ns).bind.list := $(foreach b,$(1),$(call with.bind.norm,$(b))) 284 $(with.ns).bind.names := $(foreach b,$(1),$(call with.bind.name,$(b))) 285 $(with.ns).bind.kinds := $(foreach b,$(1),$(call with.bind.kind,$(b))) 286 287 # Create a 1..=(N_bindings) list of binding indices 288 $(with.ns).bind.idx := 289 $(with.ns).bind.next = $(words 0 $($(with.ns).bind.idx)) 290 291 $(foreach bind,$($(with.ns).bind.list),$\ 292 $(eval $(with.ns).bind.idx += $($(with.ns).bind.next))) 293 294 # Create a 2..=(N_arguments) list pointing to the text argument 295 $(with.ns).text.idx := 296 $(with.ns).text.next = $(words 1 2 $($(with.ns).text.idx)) 297 $(with.ns).text = $($($(with.ns).text.next)) 298 299 # Snapshot original flavors/values of all variables to be overwritten 300 $(foreach bind.name,$($(with.ns).bind.names),$\ 301 $(foreach bind.name.ns,$(with.ns).bind.names[$(bind.name)],$\ 302 $(eval $(bind.name.ns).flavor := $(flavor $(bind.name))$\ 303 $(eval $(bind.name.ns).value = $(value $(bind.name)))))) 304 305 # Initialize per-kind buckets (e.g., `l`, `p`) 306 $(foreach bind.kind,$(sort $($(with.ns).bind.kinds)),$\ 307 $(eval $(with.ns).bind.kind[$(bind.kind)] := )) 308 309 # Distribute binding indices into kind buckets 310 $(foreach bind.i,$($(with.ns).bind.idx),$\ 311 $(foreach bind.kind,$(word $(bind.i),$($(with.ns).bind.kinds)),$\ 312 $(eval $(with.ns).bind.kind[$(bind.kind)] += $(bind.i)))) 313 314 # Per-kind setup (e.g., to set up index vectors before binding) 315 $(foreach bind.kind,$(sort $($(with.ns).bind.kinds)),$\ 316 $(foreach bind.kind.ns,$(with.ns).bind.kind[$(bind.kind)],$\ 317 $(eval $(value with.core.$(bind.kind))))) 318 319 # Perform binding from left to right 320 $(foreach bind.i,$($(with.ns).bind.idx),$\ 321 $(foreach bind.name,$(word $(bind.i),$($(with.ns).bind.names)),$\ 322 $(foreach bind.kind,$(word $(bind.i),$($(with.ns).bind.kinds)),$\ 323 $(foreach bind.kind.ns,$(with.ns).bind.kind[$(bind.kind)],$\ 324 $(eval $(value with.core.$(bind.kind).bind)))))) 325 326 # Capture the expansion result from the current text pointer 327 $(eval $(with.ns).result := $($(with.ns).text)) 328 329 # Restore originals (flavor/value) or undefine if previously absent 330 $(foreach bind.name,$($(with.ns).bind.names),$\ 331 $(foreach bind.name.ns,$(with.ns).bind.names[$(bind.name)],$\ 332 $(eval $(value with.core.restore)))) 333endef 334 335define with.core.l = 336 # Create a 1..=(N_largs) list capturing the unbound `l` words 337 $(bind.kind.ns).words.idx := 338 $(bind.kind.ns).words.next = $(words 1 $($(bind.kind.ns).words.idx)) 339 $(bind.kind.ns).words = $\ 340 $(wordlist $($(bind.kind.ns).words.next),$(words $(2)),$(2)) 341 342 # Increment the text pointer 343 $(with.ns).text.idx += $($(with.ns).text.next) 344endef 345 346define with.core.l.bind = 347 # Bind this name to the next unbound word 348 $(bind.name) := $(firstword $($(bind.kind.ns).words)) 349 350 # If this is the last `l` binding, absorb the remaining words 351 ifeq ($($(bind.kind.ns).words.next),$(words $($(bind.kind.ns)))) 352 $(bind.name) := $($(bind.kind.ns).words) 353 endif 354 355 # Nudge the word pointer forward 356 $(bind.kind.ns).words.idx += $($(bind.kind.ns).words.next) 357endef 358 359define with.core.p = 360 # Compute the parameter index that `p` bindings start at 361 $(bind.kind.ns).param.offset := 1 2 362 363 # When `l` bindings are present, `p` values shift right 364 ifneq ($(filter l,$($(with.ns).bind.kinds)),) 365 $(bind.kind.ns).param.offset += 3 366 endif 367 368 # Create an N_poff..=N_pargs list capturing the unbound `p` arguments 369 $(bind.kind.ns).param.idx := 370 $(bind.kind.ns).param.next = $\ 371 $(words $($(bind.kind.ns).param.offset) $\ 372 $($(bind.kind.ns).param.idx)) 373 $(bind.kind.ns).param = $($(lastword $($(bind.kind.ns).param.idx))) 374endef 375 376define with.core.p.bind = 377 # Mark the next parameter as bound 378 $(bind.kind.ns).param.idx += $($(bind.kind.ns).param.next) 379 380 # Bind this name to the next unbound argument 381 $(bind.name) := $($(bind.kind.ns).param) 382 383 # Increment the text pointer 384 $(with.ns).text.idx += $($(with.ns).text.next) 385endef 386 387define with.core.restore = 388 ifeq ($($(bind.name.ns).flavor),simple) 389 $(eval $(bind.name) := $(value $(bind.name.ns).value)) 390 else ifeq ($($(bind.name.ns).flavor),recursive) 391 $(eval $(bind.name) = $(value $(bind.name.ns).value)) 392 else ifeq ($($(bind.name.ns).flavor),undefined) 393 undefine $(bind.name) 394 endif 395endef 396 397# 398# Quote a string for safe use as a shell word. 399# 400# Takes the input string `$(1)` and escapes any single quotes it contains so 401# that the result can be safely used as a literal shell argument. The output is 402# wrapped in single quotes to ensure that whitespace and special characters are 403# preserved exactly when passed to the shell. 404# 405# This function is useful when constructing shell commands dynamically, since it 406# guarantees that arbitrary values are quoted correctly and will not be 407# misinterpreted by the shell. 408# 409# Parameters: 410# 411# - $(1): The string to quote for safe shell usage. 412# 413# Examples: 414# 415# $(call shell-quote,foo) # "'foo'" 416# $(call shell-quote,bar baz) # "'bar baz'" 417# $(call shell-quote,foo 'bar baz' qux) # "'foo '\''bar baz'\'' qux'" 418# 419 420shell-quote = '$(subst ','\'',$(1))' 421 422# 423# Parse a shell fragment and extract the N-th word. 424# 425# Parses the shell fragment given by `$(2)` using the shell's word-splitting and 426# quoting rules, then prints the `$(1)`-th shell word in the result. If the 427# index is out of range then this function evaluates to an empty string. 428# 429# This function is useful when working with lists that may contain whitespace or 430# quoted values, since it relies on the shell to do the parsing rather than 431# Make's own word functions. Whitespace is preserved in the return value. 432# 433# Parameters: 434# 435# - $(1): The 1-based index of the word to extract. 436# - $(2): The shell fragment to parse. 437# 438# Example usage: 439# 440# $(call shell-word,1,foo 'bar baz' qux) # "foo" 441# $(call shell-word,2,foo 'bar baz' qux) # "bar baz" 442# $(call shell-word,3,foo 'bar baz' qux) # "qux" 443# $(call shell-word,4,foo 'bar baz' qux) # <empty> 444# 445 446shell-word = $(shell $(shell-word.sh)) 447 448define shell-word.sh = 449 set -Cefu -- '' $(2); 450 451 n=$(call shell-quote,$(1)); 452 453 shift "$${n}"; 454 printf '%s' "$${1:-}"; 455endef 456 457# 458# Parse a shell fragment and count the number of shell words. 459# 460# Parses the shell fragment given by `$(1)` using the shell's word-splitting and 461# quoting rules, then prints the total number of words in the result. 462# 463# This function is useful when working with lists that may contain whitespace or 464# quoted values, since it relies on the shell to do the parsing rather than 465# Make's own word functions. 466# 467# Parameters: 468# 469# - $(1): The shell fragment to parse. 470# 471# Example usage: 472# 473# $(call shell-words,) # "0" 474# $(call shell-words,foo) # "1" 475# $(call shell-words,foo bar baz) # "3" 476# $(call shell-words,foo 'bar baz' qux) # "3" 477# 478 479shell-words = $(shell $(shell-words.sh)) 480shell-words.sh = set -Cefu -- $(1); printf '%s' "$$\#"; 481 482# 483# Parse a shell fragment and extract a sequence of shell words. 484# 485# Parses the shell fragment given by `$(1)` using the shell's word-splitting and 486# quoting rules, then extracts the words from index `$(2)` up to but not 487# including index `$(3)`. Each extracted shell word is returned sanitized for 488# safe use in the shell. 489# 490# If `$(3)` is omitted, it defaults to one past the total number of words in the 491# string, allowing you to express "all words starting from `$(2)`". 492# 493# This function is useful for safely selecting and passing subsequences of 494# shell-parsed arguments into other shell commands, ensuring correct handling 495# of whitespace and special characters. 496# 497# Parameters: 498# 499# - $(1): The shell fragment to parse. 500# - $(2): The 1-based start index of the slice (default: 1). 501# - $(3): The 1-based end index of the slice (exclusive, optional). 502# 503# Example usage: 504# 505# $(call shell-slice,foo 'bar baz' qux) # "'foo' 'bar baz' 'qux'" 506# $(call shell-slice,foo 'bar baz' qux,1,3) # "'foo' 'bar baz'" 507# $(call shell-slice,foo 'bar baz' qux,2) # "'bar baz' 'qux'" 508# $(call shell-slice,foo 'bar baz' qux,2,4) # "'bar baz' 'qux'" 509# $(call shell-slice,foo 'bar baz' qux,2,5) # "'bar baz' 'qux'" 510# 511 512shell-slice = $(shell $(shell-slice.sh)) 513 514define shell-slice.sh = 515 set -Cefu -- $(1); 516 517 n=$(if $(2),$(call shell-quote,$(2)),1); 518 m=$(if $(3),$(call shell-quote,$(3)),$$(($$# + 1))); 519 520 printf '%s\n' "$$@" $\ 521 | sed -n "$${n},$${m}{ $${m}!p }; $${m}q" $\ 522 | sed "s/'/'\\\\''/g; s/^/'/; s/\$$/'/"; 523endef 524 525# 526# Join shell words with a custom delimiter. 527# 528# Parses the shell fragment given by `$(1)` using the shell's word-splitting and 529# quoting rules, then joins the resulting words together with the delimiter 530# specified by `$(2)`. If no delimiter is provided, no delimiter is used. 531# 532# This function is useful for safely rejoining a sequence of shell-parsed 533# arguments into a single string with controlled separators, ensuring that 534# whitespace and quoting are preserved correctly. 535# 536# Parameters: 537# 538# - $(1): The shell fragment to parse and join. 539# - $(2): The delimiter to insert between words (optional). 540# 541# Example usage: 542# 543# $(call shell-join,foo 'bar baz' qux) # "foobar bazqux" 544# $(call shell-join,foo 'bar baz' qux,:) # "foo:bar baz:qux" 545# $(call shell-join,foo 'bar baz' qux,;) # "foo;bar baz;qux" 546# 547 548shell-join = $(shell $(shell-join.sh)) 549 550define shell-join.sh = 551 set -Cefu -- $(1); 552 553 delimiter=$(call shell-quote,$(2)); 554 555 printf '%s' "$${1:-}"; 556 shift 1; 557 558 while [ "$$#" -gt 0 ]; do 559 printf '%s%s' "$${delimiter}" "$${1}"; 560 shift 1; 561 done 562endef 563 564# 565# Apply a function to each shell word in a fragment. 566# 567# Parses the shell fragment given by `$(2)` into words using the shell's 568# word-splitting and quoting rules. For each word, the function `$(1)` is 569# invoked with the word as its first argument and the 1-based index of the word 570# as its second argument. The results are concatenated and returned, separated 571# by whitespace. 572# 573# This function is useful when you want to process each shell word from a 574# fragment through another function, while preserving correct handling of 575# whitespace and quoting. 576# 577# Parameters: 578# 579# - $(1): The function to apply to each word. 580# - $(2): The shell fragment to parse into words. 581# 582# Example usage: 583# 584# $(call shell-map,words,foo 'bar baz' qux) # "1 2 1" 585# $(call shell-map,uppercase,foo 'bar baz' qux) # "FOO BAR BAZ QUX" 586# 587# shout = $(1)! 588# $(call shell-map,shout,foo 'bar baz' qux) # "foo! bar baz! qux!" 589# 590# make-binary = /bin/$(1) 591# $(call shell-map,make-binary,cp "ls" 'sh') # "/bin/cp /bin/ls /bin/sh" 592# 593# index-label = $(1):$(2) 594# $(call shell-map,index-label,foo 'bar baz') # "foo:1 bar baz:2" 595# 596 597shell-map = $(call with,,$(shell $(shell-map.sh))) 598 599define shell-map.sh = 600 set -Cefu -- $(2); 601 602 function=$(call shell-quote,$(1)); 603 index=1; 604 605 for argument in "$$@"; do 606 sanitized=$$(printf '%s' "$${argument}" $\ 607 | sed -e 's/[$$]/$$$$/g; s/,/$${comma}/g' $\ 608 -e 's/(/$${lparen}/g; s/)/$${rparen}/g'); 609 610 printf '$$(call %s,%s,%s)\n' $\ 611 "$${function}" "$${sanitized}" "$${index}"; 612 613 index=$$((index + 1)); 614 done 615endef 616 617# 618# Resolve a program name or shell fragment to a safely quoted shell command. 619# 620# Attempts to locate the program given by `$(1)` on the system `PATH`. If the 621# program is found, its name is returned wrapped in single quotes so it can be 622# used safely in a shell command. If the program cannot be found, then the 623# argument is instead parsed as a shell fragment and returned as a sanitized 624# sequence of words, ensuring whitespace and quoting are preserved correctly. 625# 626# This function is useful when dynamically constructing shell command lines 627# that may include either well-known executables or arbitrary user-supplied 628# fragments. It guarantees that the result is safe to embed in shell commands, 629# regardless of whether it resolves to a `PATH` entry or a literal fragment. 630# 631# Parameters: 632# 633# - $(1): The program name or shell fragment to resolve. 634# 635# Example usage: 636# 637# $(call shell-program,sh) # "'sh'" 638# $(call shell-program,sh -c) # "'sh' '-c'" 639# 640# # If the program exists and is executable: 641# 642# $(call shell-program,/foo bar/sh) # "'/foo bar/sh'" 643# $(call shell-program,"/foo bar/sh" -c) # "'/foo bar/sh' '-c'" 644# 645# # If the program does not exist or is not executable: 646# 647# $(call shell-program,/foo bar/sh) # "'/foo' 'bar/sh'" 648# $(call shell-program,/foo bar/sh -c) # "'/foo' 'bar/sh' '-c'" 649# 650 651shell-program = $\ 652 $(if $(call which,$(1)),$\ 653 $(call shell-quote,$(1)),$\ 654 $(call shell-slice,$(1))) 655