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