xref: /xnu-11417.140.69/makedefs/MakeInc.cmd (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1# -*- mode: makefile;-*-
2#
3# Copyright (C) 1999-2020 Apple Inc. All rights reserved.
4#
5# MakeInc.cmd contains command paths for use during
6# the build, as well as make fragments and text
7# strings that may be evaluated as utility functions.
8#
9
10#
11# Commands for the build environment
12#
13
14#
15# Build Logging and Verbosity
16#
17
18ifeq ($(RC_XBS),YES)
19	VERBOSE = YES
20else
21	VERBOSE = NO
22endif
23
24BASH = bash
25
26ECHO = echo
27
28ERR = $(ECHO) > /dev/stderr
29PRINTF = printf
30
31QUIET ?= 0
32ifneq ($(QUIET),0)
33	PRINTF = printf > /dev/null
34	ifeq ($(VERBOSE),YES)
35		override VERBOSE = NO
36	endif
37endif
38
39# Helper functions for logging operations.
40LOG_PFX_LEN = 15
41LOG_PFX_LEN_ADJ = $(LOG_PFX_LEN)
42LOG = $(PRINTF) "$2%$4s$(Color0) $3%s$(Color0)\n" "$1"
43
44CONCISE ?= 0
45ifneq ($(CONCISE),0)
46	# Concise logging puts all logs on the same line (CSI K to clear and
47	# carriage return).
48	LOG = $(PRINTF) "$2%$4s$(Color0) $3%s$(Color0)\033[K\r" "$1"
49endif
50
51_LOG_COMP = $(call LOG,$1,$(ColorC),$(ColorF),$(LOG_PFX_LEN_ADJ))
52_LOG_HOST = $(call LOG,$1,$(ColorH),$(ColorF),$(LOG_PFX_LEN))
53_LOG_HOST_LINK = $(call LOG,$1,$(ColorH),$(ColorLF),$(LOG_PFX_LEN))
54
55# Special operations.
56LOG_LDFILELIST = $(call LOG,LDFILELIST,$(ColorL),$(ColorLF),$(LOG_PFX_LEN_ADJ))
57LOG_MIG = $(call LOG,MIG,$(ColorM),$(ColorF),$(LOG_PFX_LEN_ADJ))
58LOG_LD = $(call LOG,LD,$(ColorL),$(ColorF),$(LOG_PFX_LEN_ADJ))
59LOG_ALIGN = $(call LOG,--------->,$(Color0),$(Color0),$(LOG_PFX_LEN))
60
61# Compiling/machine-specific operations.
62LOG_CC = $(call _LOG_COMP,CC)
63LOG_CXX = $(call _LOG_COMP,C++)
64LOG_AS = $(call _LOG_COMP,AS)
65LOG_LTO = $(call _LOG_COMP,LTO)
66LOG_SYMBOLSET = $(call _LOG_COMP,SYMSET)
67LOG_SYMBOLSETPLIST = $(call _LOG_COMP,SYMSETPLIST)
68LOG_VERIFIER = $(call _LOG_COMP,VERIFIER)
69
70# Host-side operations.
71LOG_TIGHTBEAMC = $(call _LOG_HOST,TIGHTBEAMC)
72LOG_IIG = $(call _LOG_HOST,IIG)
73LOG_HOST_CC = $(call _LOG_HOST,CC)
74LOG_HOST_LD = $(call _LOG_HOST,LD)
75LOG_HOST_CODESIGN = $(call _LOG_HOST,CODESIGN)
76LOG_HOST_BISON = $(call _LOG_HOST,BISON)
77LOG_HOST_FLEX = $(call _LOG_HOST,FLEX)
78LOG_INSTALL = $(call _LOG_HOST,INSTALL)
79LOG_INSTALLVARIANT = $(call _LOG_HOST,INSTALLVARIANT)
80LOG_INSTALLSYM = $(call _LOG_HOST,INSTALLSYM)
81LOG_INSTALLHDR = $(call _LOG_HOST,INSTALLHDR)
82LOG_INSTALLMACROS = $(call _LOG_HOST,INSTALLMACROS)
83LOG_INSTALLPY = $(call _LOG_HOST,INSTALLPY)
84LOG_MAN = $(call _LOG_HOST,MAN)
85LOG_MANLINK = $(call _LOG_HOST,MANLINK)
86LOG_ALIAS = $(call _LOG_HOST,ALIAS)
87LOG_STRIP = $(call _LOG_HOST,STRIP)
88LOG_DSYMUTIL = $(call _LOG_HOST,DSYMUTIL)
89LOG_LIBTOOL = $(call _LOG_HOST,LIBTOOL)
90LOG_FILEPREP = $(call _LOG_HOST,FILEPREP)
91
92# Host-side linking operations.
93LOG_GENASSYM = $(call _LOG_HOST_LINK,GENASSYM)
94LOG_GENERATE= $(call _LOG_HOST_LINK,GENERATE)
95LOG_CTFCONVERT = $(call _LOG_HOST_LINK,CTFCONVERT)
96LOG_CTFMERGE = $(call _LOG_HOST_LINK,CTFMERGE)
97LOG_CTFINSERT = $(call _LOG_HOST_LINK,CTFINSERT)
98LOG_DSYMUTIL = $(call _LOG_HOST_LINK,DSYMUTIL)
99LOG_SUPPORTED_KPI = $(call _LOG_HOST_LINK,SUPPORTED_KPI)
100
101
102ifeq ($(VERBOSE),YES)
103	_v =
104	_vstdout =
105	_vstderr =
106	XCRUN = /usr/bin/xcrun -verbose
107else
108	_v = @
109	_vstdout = > /dev/null
110	_vstderr = 2> /dev/null
111	XCRUN = /usr/bin/xcrun
112endif
113
114VERBOSE_GENERATED_MAKE_FRAGMENTS = NO
115
116#
117# Defaults
118#
119
120SDKROOT ?= macosx
121HOST_SDKROOT ?= macosx
122
123# SDKROOT may be passed as a shorthand like "iphoneos.internal". We
124# must resolve these to a full path and override SDKROOT.
125
126ifeq ($(origin SDKROOT_RESOLVED),undefined)
127export SDKROOT_RESOLVED := $(shell $(XCRUN) -sdk $(SDKROOT) -show-sdk-path)
128ifeq ($(strip $(SDKROOT)_$(SDKROOT_RESOLVED)),/_)
129export SDKROOT_RESOLVED := /
130endif
131endif
132override SDKROOT = $(SDKROOT_RESOLVED)
133
134ifeq ($(origin HOST_SDKROOT_RESOLVED),undefined)
135export HOST_SDKROOT_RESOLVED := $(shell $(XCRUN) -sdk $(HOST_SDKROOT) -show-sdk-path)
136ifeq ($(strip $(HOST_SDKROOT_RESOLVED)),)
137export HOST_SDKROOT_RESOLVED := /
138endif
139endif
140override HOST_SDKROOT = $(HOST_SDKROOT_RESOLVED)
141
142ifeq ($(origin SDKVERSION),undefined)
143     export SDKVERSION := $(shell $(XCRUN) -sdk $(SDKROOT) -show-sdk-version)
144endif
145
146ifeq ($(origin PLATFORM),undefined)
147	export PLATFORMPATH := $(shell $(XCRUN) -sdk $(SDKROOT) -show-sdk-platform-path)
148	export PLATFORM := $(shell echo $(PLATFORMPATH) | sed 's,^.*/\([^/]*\)\.platform$$,\1,' | sed 's,\.[^.]*$$,,')
149	ifeq ($(PLATFORM),)
150		export PLATFORM := MacOSX
151	else ifeq ($(shell echo $(PLATFORM) | tr A-Z a-z),watchos)
152		export PLATFORM := WatchOS
153	endif
154endif
155
156ifeq ($(PLATFORM),DriverKit)
157	ifeq ($(origin COHORT_SDKROOT_RESOLVED),undefined)
158		SDK_NAME = $(notdir $(SDKROOT))
159		export COHORT_NAME := $(shell echo $(SDK_NAME) | sed -e 's|DriverKit.\([a-zA-Z]*\)$(SDKVERSION)\([.Internal]*\).sdk|\1\2|g' | tr A-Z a-z)
160		export COHORT_SDKROOT_RESOLVED := $(shell $(XCRUN) -sdk $(COHORT_NAME) -show-sdk-path)
161		ifeq ($(strip $(COHORT_SDKROOT_RESOLVED)),)
162		export COHORT_SDKROOT_RESOLVED := $(SDKROOT_RESOLVED)
163		endif
164	endif
165	override COHORT_SDKROOT = $(COHORT_SDKROOT_RESOLVED)
166	export PLATFORMPATH = $(shell $(XCRUN) -sdk $(COHORT_SDKROOT) -show-sdk-platform-path)
167	export PLATFORM := DriverKit
168	export DRIVERKIT ?= 1
169	export DRIVERKITROOT ?= /System/DriverKit
170	export DRIVERKITRUNTIMEROOT = $(DRIVERKITROOT)/Runtime
171else
172	override COHORT_SDKROOT = $(SDKROOT)
173endif
174
175ifeq ($(PLATFORM),MacOSX)
176	ifeq (DriverKit,$(shell echo $(SDKROOT_RESOLVED) | sed 's|^.*/\([^./1-9]*\)\(\.[^./1-9]*\)\{0,1\}[1-9][^/]*\.sdk$$|\1|'))
177		export PLATFORM := DriverKit
178		export DRIVERKIT ?= 1
179		export DRIVERKITROOT ?= /System/DriverKit
180		export DRIVERKITRUNTIMEROOT = $(DRIVERKITROOT)/Runtime
181	endif
182endif
183
184ifeq ($(PLATFORM),ExclaveKit)
185	ifeq ($(origin COHORT_SDKROOT_RESOLVED),undefined)
186		SDK_NAME = $(notdir $(SDKROOT))
187		export COHORT_NAME := $(shell echo $(SDK_NAME) | sed -e 's|ExclaveKit.\([a-zA-Z]*\)$(SDKVERSION)\([.Internal]*\).sdk|\1\2|g' | tr A-Z a-z)
188		export COHORT_SDKROOT_RESOLVED := $(shell $(XCRUN) -sdk $(COHORT_NAME) -show-sdk-path)
189		ifeq ($(strip $(COHORT_SDKROOT_RESOLVED)),)
190		export COHORT_SDKROOT_RESOLVED := $(SDKROOT_RESOLVED)
191		endif
192	endif
193	override COHORT_SDKROOT = $(COHORT_SDKROOT_RESOLVED)
194	export PLATFORMPATH = $(shell $(XCRUN) -sdk $(COHORT_SDKROOT) -show-sdk-platform-path)
195	export PLATFORM := ExclaveKit
196	export EXCLAVEKIT ?= 1
197	export EXCLAVEKITROOT ?= /System/ExclaveKit
198endif
199
200ifeq ($(PLATFORM),ExclaveCore)
201	ifeq ($(origin COHORT_SDKROOT_RESOLVED),undefined)
202		SDK_NAME = $(notdir $(SDKROOT))
203		export COHORT_NAME := $(shell echo $(SDK_NAME) | sed -e 's|ExclaveCore.\([a-zA-Z]*\)$(SDKVERSION)\([.Internal]*\).sdk|\1\2|g' | tr A-Z a-z)
204		export COHORT_SDKROOT_RESOLVED := $(shell $(XCRUN) -sdk $(COHORT_NAME) -show-sdk-path)
205		ifeq ($(strip $(COHORT_SDKROOT_RESOLVED)),)
206		export COHORT_SDKROOT_RESOLVED := $(SDKROOT_RESOLVED)
207		endif
208	endif
209	override COHORT_SDKROOT = $(COHORT_SDKROOT_RESOLVED)
210	export PLATFORMPATH = $(shell $(XCRUN) -sdk $(COHORT_SDKROOT) -show-sdk-platform-path)
211	export PLATFORM := ExclaveCore
212	export EXCLAVECORE ?= 1
213	export EXCLAVECOREROOT ?= /System/ExclaveCore
214endif
215
216# CC/CXX get defined by make(1) by default, so we can't check them
217# against the empty string to see if they haven't been set
218ifeq ($(origin CC),default)
219	export CC := $(shell $(XCRUN) -sdk $(SDKROOT) -find clang)
220endif
221ifeq ($(origin CXX),default)
222	export CXX := $(shell $(XCRUN) -sdk $(SDKROOT) -find clang++)
223endif
224ifeq ($(origin MIG),undefined)
225	export MIG := $(shell $(XCRUN) -sdk $(SDKROOT) -find mig)
226endif
227ifeq ($(origin MIGCOM),undefined)
228	export MIGCOM := $(shell $(XCRUN) -sdk $(SDKROOT) -find migcom)
229endif
230ifeq ($(origin MIGCC),undefined)
231	export MIGCC := $(CC)
232endif
233ifeq ($(origin IIG),undefined)
234	export IIG := $(shell $(XCRUN) -sdk $(SDKROOT) -find iig)
235endif
236ifeq ($(origin STRIP),undefined)
237	export STRIP := $(shell $(XCRUN) -sdk $(SDKROOT) -find strip)
238endif
239ifeq ($(origin LIPO),undefined)
240	export LIPO := $(shell $(XCRUN) -sdk $(SDKROOT) -find lipo)
241endif
242ifeq ($(origin LIBTOOL),undefined)
243	export LIBTOOL := $(shell $(XCRUN) -sdk $(SDKROOT) -find libtool)
244endif
245ifeq ($(origin OTOOL),undefined)
246	export OTOOL := $(shell $(XCRUN) -sdk $(SDKROOT) -find otool)
247endif
248ifeq ($(origin NM),undefined)
249	export NM := $(shell $(XCRUN) -sdk $(SDKROOT) -find nm)
250endif
251ifeq ($(origin UNIFDEF),undefined)
252	export UNIFDEF := $(shell $(XCRUN) -sdk $(SDKROOT) -find unifdef)
253endif
254ifeq ($(origin DSYMUTIL),undefined)
255	export DSYMUTIL := $(shell $(XCRUN) -sdk $(SDKROOT) -find dsymutil)
256endif
257ifeq ($(origin NMEDIT),undefined)
258	export NMEDIT := $(shell $(XCRUN) -sdk $(SDKROOT) -find nmedit)
259endif
260ifeq ($(origin GIT),undefined)
261	export GIT := $(shell $(XCRUN) -sdk $(SDKROOT) -find git)
262endif
263ifeq ($(origin SCAN_BUILD),undefined)
264	export SCAN_BUILD := $(shell $(XCRUN) -sdk $(SDKROOT) -find scan-build 2> /dev/null)
265endif
266ifeq ($(origin CTFINSERT),undefined)
267	export CTFINSERT := $(shell $(XCRUN) -sdk $(SDKROOT) -find ctf_insert 2> /dev/null)
268endif
269ifeq ($(origin CTFCONVERT),undefined)
270	export CTFCONVERT := $(shell $(XCRUN) -sdk $(SDKROOT) -find ctfconvert 2> /dev/null)
271endif
272ifeq ($(origin CTFMERGE),undefined)
273	export CTFMERGE := $(shell $(XCRUN) -sdk $(SDKROOT) -find ctfmerge 2> /dev/null)
274	ifeq (,$(wildcard $(CTFMERGE)))
275		export DO_CTFMERGE := 0
276	endif
277endif
278ifeq ($(origin CTFDUMP),undefined)
279	export CTFDUMP := $(shell $(XCRUN) -sdk $(SDKROOT) -find ctfdump 2> /dev/null)
280endif
281ifeq ($(origin DOCC),undefined)
282	export DOCC := $(shell $(XCRUN) -sdk $(SDKROOT) -find docc 2> /dev/null)
283endif
284ifeq ($(origin PYTHON),undefined)
285	export PYTHON := $(shell $(XCRUN) -sdk $(SDKROOT) -find python3 2> /dev/null)
286endif
287ifeq ($(origin OBJDUMP),undefined)
288	export OBJDUMP := $(shell $(XCRUN) -sdk $(SDKROOT) -find objdump 2> /dev/null)
289endif
290
291#
292# Platform options
293#
294SUPPORTED_EMBEDDED_PLATFORMS := iPhoneOS iPhoneOSNano tvOS AppleTVOS WatchOS BridgeOS
295SUPPORTED_SIMULATOR_PLATFORMS := iPhoneSimulator iPhoneNanoSimulator tvSimulator AppleTVSimulator WatchSimulator
296
297
298SUPPORTED_PLATFORMS := MacOSX DriverKit ExclaveKit ExclaveCore $(SUPPORTED_SIMULATOR_PLATFORMS) $(SUPPORTED_EMBEDDED_PLATFORMS)
299
300# Platform-specific tools
301EDM_DBPATH ?= $(PLATFORMPATH)/usr/local/standalone/firmware/device_map.db
302
303# Scripts or tools we build ourselves
304#
305# setsegname - Rename segments in a Mach-O object file
306# kextsymboltool - Create kext pseudo-kext Mach-O kexts binaries
307# decomment - Strip out comments to detect whether a file is comments-only
308# installfile - Atomically copy files, esp. when multiple architectures
309#               are trying to install the same target header
310# replacecontents - Write contents to a file and update modtime *only* if
311#                   contents differ
312# vm_sanitize_enforcement - Reject MIG files that use types that do not enforce
313#                           sanitization for VM inputs
314#
315SEG_HACK = $(OBJROOT)/SETUP/setsegname/setsegname
316KEXT_CREATE_SYMBOL_SET = $(OBJROOT)/SETUP/kextsymboltool/kextsymboltool
317DECOMMENT = $(OBJROOT)/SETUP/decomment/decomment
318NEWVERS = $(SRCROOT)/config/newvers.pl
319INSTALL = $(OBJROOT)/SETUP/installfile/installfile
320REPLACECONTENTS = $(OBJROOT)/SETUP/replacecontents/replacecontents
321VM_SANITIZE_ADOPTION_CHECK = $(SRCROOT)/tools/vm_sanitize_enforcement.py
322
323# Standard BSD tools
324RM = /bin/rm -f
325RMDIR = /bin/rmdir
326CP = /bin/cp
327MV = /bin/mv
328LN = /bin/ln -fs
329CAT = /bin/cat
330MKDIR = /bin/mkdir -p
331CHMOD = /bin/chmod
332FIND = /usr/bin/find
333XARGS = /usr/bin/xargs
334PAX = /bin/pax
335BASENAME = /usr/bin/basename
336DIRNAME = /usr/bin/dirname
337TR = /usr/bin/tr
338TOUCH = /usr/bin/touch
339SLEEP = /bin/sleep
340AWK = /usr/bin/awk
341SED = /usr/bin/sed
342PLUTIL = /usr/bin/plutil
343PATCH = /usr/bin/patch
344GREP = /usr/bin/grep
345
346#
347# Command to generate host binaries. Intentionally not
348# $(CC), which controls the target compiler
349#
350ifeq ($(origin HOST_OS_VERSION),undefined)
351	export HOST_OS_VERSION	:= $(shell sw_vers -productVersion)
352endif
353ifeq ($(origin HOST_CC),undefined)
354	export HOST_CC		:= $(shell $(XCRUN) -sdk $(HOST_SDKROOT) -find clang)
355endif
356ifeq ($(origin HOST_FLEX),undefined)
357	export HOST_FLEX	:= $(shell $(XCRUN) -sdk $(HOST_SDKROOT) -find flex)
358endif
359ifeq ($(origin HOST_BISON),undefined)
360	export HOST_BISON	:= $(shell $(XCRUN) -sdk $(HOST_SDKROOT) -find bison)
361endif
362ifeq ($(origin HOST_GM4),undefined)
363	export HOST_GM4		:= $(shell $(XCRUN) -sdk $(HOST_SDKROOT) -find gm4)
364endif
365ifeq ($(origin HOST_CODESIGN),undefined)
366	export HOST_CODESIGN	:= /usr/bin/codesign
367endif
368ifeq ($(origin HOST_CODESIGN_ALLOCATE),undefined)
369	export HOST_CODESIGN_ALLOCATE	:= $(shell $(XCRUN) -sdk $(HOST_SDKROOT) -find codesign_allocate)
370endif
371
372#
373# The following variables are functions invoked with "call", and thus
374# behave similarly to externally compiled commands
375#
376
377# $(1) is an expanded kernel config from a TARGET_CONFIGS_UC tuple
378# $(2) is an expanded arch config from a TARGET_CONFIGS_UC tuple
379# $(3) is an expanded machine config from a TARGET_CONFIGS_UC tuple
380_function_create_build_configs_join = $(strip $(1))^$(strip $(2))^$(strip $(3))
381
382# $(1) is an un-expanded kernel config from a TARGET_CONFIGS_UC tuple
383# $(2) is an un-expanded arch config from a TARGET_CONFIGS_UC tuple
384# $(3) is an un-expanded machine config from a TARGET_CONFIGS_UC tuple
385_function_create_build_configs_do_expand =          $(call _function_create_build_configs_join, \
386							   $(if $(filter DEFAULT,$(1)), \
387								$(DEFAULT_KERNEL_CONFIG), \
388								$(1) \
389							    ), \
390							   $(if $(filter DEFAULT,$(2)), \
391								$(DEFAULT_ARCH_CONFIG), \
392								$(2) \
393							    ), \
394							   $(if $(filter DEFAULT,$(3)), \
395								$(if $(filter DEFAULT,$(2)), \
396								     $(DEFAULT_$(DEFAULT_ARCH_CONFIG)_MACHINE_CONFIG), \
397								     $(DEFAULT_$(strip $(2))_MACHINE_CONFIG) \
398								), \
399								$(3) \
400							    ) \
401						     )
402
403# $(1) is an un-expanded TARGET_CONFIGS_UC list, which must be consumed
404#      3 elements at a time
405function_create_build_configs = $(sort \
406					$(strip \
407						 $(call _function_create_build_configs_do_expand, \
408							$(word 1,$(1)), \
409							$(word 2,$(1)), \
410							$(word 3,$(1)), \
411						  ) \
412						 $(if $(word 4,$(1)), \
413						      $(call function_create_build_configs, \
414							     $(wordlist 4,$(words $(1)),$(1)) \
415						       ), \
416						  ) \
417					  ) \
418				   )
419
420# Similar to build configs, but alias configs are a 4-tuple
421
422# $(1) is an expanded kernel config from a TARGET_CONFIGS_ALIASES_UC tuple
423# $(2) is an expanded arch config from a TARGET_CONFIGS_ALIASES_UC tuple
424# $(3) is an expanded kernel machine config from a TARGET_CONFIGS_ALIASES_UC tuple
425# $(4) is an expanded SoC platform config from a TARGET_CONFIGS_ALIASES_UC tuple,
426#      which should be an alias of $(3)
427_function_create_alias_configs_join = $(strip $(1))^$(strip $(2))^$(strip $(3))^$(strip $(4))
428
429_function_create_alias_configs_do_expand =	    $(call _function_create_alias_configs_join, \
430							   $(if $(filter DEFAULT,$(1)), \
431							        $(DEFAULT_KERNEL_CONFIG), \
432								$(1) \
433							    ), \
434							   $(if $(filter DEFAULT,$(2)), \
435								$(DEFAULT_ARCH_CONFIG), \
436								$(2) \
437							    ), \
438							   $(3), \
439							   $(4) \
440						     )
441
442function_create_alias_configs = $(sort \
443					$(strip \
444						 $(call _function_create_alias_configs_do_expand, \
445							$(word 1,$(1)), \
446							$(word 2,$(1)), \
447							$(word 3,$(1)), \
448							$(word 4,$(1)), \
449						  ) \
450						 $(if $(word 5,$(1)), \
451						      $(call function_create_alias_configs, \
452							     $(wordlist 5,$(words $(1)),$(1)) \
453						       ), \
454						  ) \
455					 ) \
456				 )
457
458# $(1) is a fully-expanded kernel config
459# $(2) is a fully-expanded arch config
460# $(3) is a fully-expanded machine config. "NONE" is not represented in the objdir path
461function_convert_target_config_uc_to_objdir = $(if $(filter NONE,$(3)),$(strip $(1))_$(strip $(2)),$(strip $(1))_$(strip $(2))_$(strip $(3)))
462
463# $(1) is a fully-expanded build config (like "RELEASE^X86_64^NONE")
464function_convert_build_config_to_objdir = $(call function_convert_target_config_uc_to_objdir, \
465						 $(word 1,$(subst ^, ,$(1))), \
466						 $(word 2,$(subst ^, ,$(1))), \
467						 $(word 3,$(subst ^, ,$(1))) \
468					   )
469
470# $(1) is a fully-expanded build config (like "RELEASE^X86_64^NONE")
471function_extract_kernel_config_from_build_config  = $(word 1,$(subst ^, ,$(1)))
472function_extract_arch_config_from_build_config    = $(word 2,$(subst ^, ,$(1)))
473function_extract_machine_config_from_build_config = $(word 3,$(subst ^, ,$(1)))
474
475#
476# Returns build config if both architecture and kernel configuration match.
477#
478#   $(1) - list of build configs
479#   $(1) - architecture
480#   $(2) - kernel configuration
481
482function_match_build_config_for_architecture_and_kernel_config = $(strip \
483			    $(foreach build_config, $(1), \
484			      $(if \
485				$(and \
486				  $(filter $(2), $(call function_extract_arch_config_from_build_config, $(build_config))), \
487				  $(filter $(3), $(call function_extract_kernel_config_from_build_config, $(build_config)))), \
488			      $(build_config), )))
489
490#
491# Returns build config if kernel configuration matches.
492#
493#   $(1) - list of build configs
494#   $(2) - kernel configuration
495
496function_match_build_config_for_kernel_config = $(strip \
497			    $(foreach build_config, $(1), \
498			      $(if \
499				  $(filter $(2), $(call function_extract_kernel_config_from_build_config, $(build_config))), \
500			      $(build_config), )))
501
502# $(1) is an input word
503# $(2) is a list of colon-separate potential substitutions like "FOO:BAR BAZ:QUX"
504# $(3) is a fallback if no substitutions were made
505function_substitute_word_with_replacement = $(strip $(if $(2),								\
506							 $(if $(filter $(word 1,$(subst :, ,$(word 1,$(2)))),$(1)),	\
507							      $(word 2,$(subst :, ,$(word 1,$(2)))),		\
508							      $(call function_substitute_word_with_replacement,$(1),$(wordlist 2,$(words $(2)),$(2)),$(3))), \
509							 $(3)								\
510						     )									\
511					     )
512
513# You can't assign a variable to an empty space without these
514# shenanigans
515empty :=
516space := $(empty) $(empty)
517
518# Arithmetic
519# $(1) is the number to increment
520NUM32 = x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
521increment = $(words x $(wordlist 1,$(1),$(NUM32)))
522decrement = $(words $(wordlist 2,$(1),$(NUM32)))
523
524# Create a sequence from 1 to $(1)
525# F(N) = if N > 0: return F(N-1) + "N" else: return ""
526sequence = $(if $(wordlist 1,$(1),$(NUM32)),$(call sequence,$(call decrement,$(1))) $(1),)
527
528# Reverse a list of words in $(1)
529reverse = $(if $(word 2,$(1)),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(word 1,$(1))
530
531# vim: set ft=make:
532