xref: /xnu-12377.1.9/makedefs/MakeInc.cmd (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
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_function_filter_out_vmapple_sptm_build_config = $(if \
378										$(and \
379											$(filter SPTM,$(call function_extract_kernel_config_from_build_config,$(1))), \
380											$(filter VMAPPLE,$(call function_extract_machine_config_from_build_config,$(1))) \
381										) \
382										,,$(1) \
383									)
384
385# $(1) is an expanded kernel config from a TARGET_CONFIGS_UC tuple
386# $(2) is an expanded arch config from a TARGET_CONFIGS_UC tuple
387# $(3) is an expanded machine config from a TARGET_CONFIGS_UC tuple
388_function_create_build_configs_join = $(strip $(1))^$(strip $(2))^$(strip $(3))
389
390# $(1) is an un-expanded kernel config from a TARGET_CONFIGS_UC tuple
391# $(2) is an un-expanded arch config from a TARGET_CONFIGS_UC tuple
392# $(3) is an un-expanded machine config from a TARGET_CONFIGS_UC tuple
393_function_create_build_configs_do_expand =          $(call _function_create_build_configs_join, \
394							   $(if $(filter DEFAULT,$(1)), \
395								$(DEFAULT_KERNEL_CONFIG), \
396								$(1) \
397							    ), \
398							   $(if $(filter DEFAULT,$(2)), \
399								$(DEFAULT_ARCH_CONFIG), \
400								$(2) \
401							    ), \
402							   $(if $(filter DEFAULT,$(3)), \
403								$(if $(filter DEFAULT,$(2)), \
404								     $(DEFAULT_$(DEFAULT_ARCH_CONFIG)_MACHINE_CONFIG), \
405								     $(DEFAULT_$(strip $(2))_MACHINE_CONFIG) \
406								), \
407								$(3) \
408							    ) \
409						     )
410
411# $(1) is an un-expanded kernel config from a TARGET_CONFIGS_UC tuple
412# $(2) is an un-expanded arch config from a TARGET_CONFIGS_UC tuple
413# $(3) is an un-expanded machine config from a TARGET_CONFIGS_UC tuple, that may be multiplexed (e.g. ConfigA&ConfigB)
414# This function splits any multiplexed machine configs into separate items.
415_function_create_build_configs_do_expand_with_muxed_machine_config = $(foreach machine_config, $(subst &, ,$(3)), \
416												$(call _function_filter_out_vmapple_sptm_build_config,\
417													$(call _function_create_build_configs_do_expand,$(1),$(2),$(machine_config)) \
418												) \
419											)
420
421# $(1) is an un-expanded TARGET_CONFIGS_UC list, which must be consumed
422#      3 elements at a time
423function_create_build_configs = $(sort \
424					$(strip \
425						 $(call _function_create_build_configs_do_expand_with_muxed_machine_config, \
426							$(word 1,$(1)), \
427							$(word 2,$(1)), \
428							$(word 3,$(1)), \
429						  ) \
430						 $(if $(word 4,$(1)), \
431						      $(call function_create_build_configs, \
432							     $(wordlist 4,$(words $(1)),$(1)) \
433						       ), \
434						  ) \
435					  ) \
436				   )
437
438# Similar to build configs, but alias configs are a 4-tuple
439
440# $(1) is an expanded kernel config from a TARGET_CONFIGS_ALIASES_UC tuple
441# $(2) is an expanded arch config from a TARGET_CONFIGS_ALIASES_UC tuple
442# $(3) is an expanded kernel machine config from a TARGET_CONFIGS_ALIASES_UC tuple
443# $(4) is an expanded SoC platform config from a TARGET_CONFIGS_ALIASES_UC tuple,
444#      which should be an alias of $(3)
445_function_create_alias_configs_join = $(strip $(1))^$(strip $(2))^$(strip $(3))^$(strip $(4))
446
447_function_create_alias_configs_do_expand =	    $(call _function_create_alias_configs_join, \
448							   $(if $(filter DEFAULT,$(1)), \
449							        $(DEFAULT_KERNEL_CONFIG), \
450								$(1) \
451							    ), \
452							   $(if $(filter DEFAULT,$(2)), \
453								$(DEFAULT_ARCH_CONFIG), \
454								$(2) \
455							    ), \
456							   $(3), \
457							   $(4) \
458						     )
459
460# $(1) is an un-expanded kernel config from a TARGET_CONFIGS_UC tuple
461# $(2) is an un-expanded arch config from a TARGET_CONFIGS_UC tuple
462# $(3) is an un-expanded machine config from a TARGET_CONFIGS_UC tuple, that may be multiplexed (e.g. ConfigA&ConfigB)
463# $(4) is an expanded SoC platform config from a TARGET_CONFIGS_ALIASES_UC tuple,
464#      which should be an alias of $(3)
465# This function splits any multiplexed machine configs into separate items.
466_function_create_alias_configs_do_expand_with_muxed_machine_config = $(foreach machine_config, $(subst &, ,$(3)), \
467												$(call _function_filter_out_vmapple_sptm_build_config,\
468													$(call _function_create_alias_configs_do_expand,$(1),$(2),$(machine_config),$(4)) \
469												) \
470											)
471
472function_create_alias_configs = $(sort \
473					$(strip \
474						 $(call _function_create_alias_configs_do_expand_with_muxed_machine_config, \
475							$(word 1,$(1)), \
476							$(word 2,$(1)), \
477							$(word 3,$(1)), \
478							$(word 4,$(1)), \
479						  ) \
480						 $(if $(word 5,$(1)), \
481						      $(call function_create_alias_configs, \
482							     $(wordlist 5,$(words $(1)),$(1)) \
483						       ), \
484						  ) \
485					 ) \
486				 )
487
488# $(1) is a fully-expanded kernel config
489# $(2) is a fully-expanded arch config
490# $(3) is a fully-expanded machine config. "NONE" is not represented in the objdir path
491function_convert_target_config_uc_to_objdir = $(if $(filter NONE,$(3)),$(strip $(1))_$(strip $(2)),$(strip $(1))_$(strip $(2))_$(strip $(3)))
492
493# $(1) is a fully-expanded build config (like "RELEASE^X86_64^NONE")
494function_convert_build_config_to_objdir = $(call function_convert_target_config_uc_to_objdir, \
495						 $(word 1,$(subst ^, ,$(1))), \
496						 $(word 2,$(subst ^, ,$(1))), \
497						 $(word 3,$(subst ^, ,$(1))) \
498					   )
499
500# $(1) is a fully-expanded build config (like "RELEASE^X86_64^NONE")
501function_extract_kernel_config_from_build_config  = $(word 1,$(subst ^, ,$(1)))
502function_extract_arch_config_from_build_config    = $(word 2,$(subst ^, ,$(1)))
503function_extract_machine_config_from_build_config = $(word 3,$(subst ^, ,$(1)))
504
505#
506# Returns build config if both architecture and kernel configuration match.
507#
508#   $(1) - list of build configs
509#   $(1) - architecture
510#   $(2) - kernel configuration
511
512function_match_build_config_for_architecture_and_kernel_config = $(strip \
513			    $(foreach build_config, $(1), \
514			      $(if \
515				$(and \
516				  $(filter $(2), $(call function_extract_arch_config_from_build_config, $(build_config))), \
517				  $(filter $(3), $(call function_extract_kernel_config_from_build_config, $(build_config)))), \
518			      $(build_config), )))
519
520#
521# Returns build config if kernel configuration matches.
522#
523#   $(1) - list of build configs
524#   $(2) - kernel configuration
525
526function_match_build_config_for_kernel_config = $(strip \
527			    $(foreach build_config, $(1), \
528			      $(if \
529				  $(filter $(2), $(call function_extract_kernel_config_from_build_config, $(build_config))), \
530			      $(build_config), )))
531
532# $(1) is an input word
533# $(2) is a list of colon-separate potential substitutions like "FOO:BAR BAZ:QUX"
534# $(3) is a fallback if no substitutions were made
535function_substitute_word_with_replacement = $(strip $(if $(2),								\
536							 $(if $(filter $(word 1,$(subst :, ,$(word 1,$(2)))),$(1)),	\
537							      $(word 2,$(subst :, ,$(word 1,$(2)))),		\
538							      $(call function_substitute_word_with_replacement,$(1),$(wordlist 2,$(words $(2)),$(2)),$(3))), \
539							 $(3)								\
540						     )									\
541					     )
542
543# $(1) is a string of form "arch;platform(&platform)*", where multiple platforms are separated by the "&" delimiter.
544# Output is the arch.
545function_get_arch = $(word 1,$(subst ;, ,$(1)))
546
547# $(1) is a string of form "arch;platform(&platform)*", where multiple platforms are separated by the "&" delimiter.
548# Output is a space separated list of the platforms.
549function_get_platforms = $(subst &, ,$(word 2,$(subst ;, ,$(1))))
550
551# $(1) is a string of form "arch;platform(&platform)*", where multiple platforms are separated by the "&" delimiter.
552function_parse_product_configs = $(foreach platform,$(call function_get_platforms,$(1)),$(call function_get_arch,$(1));$(platform);)
553
554# You can't assign a variable to an empty space without these
555# shenanigans
556empty :=
557space := $(empty) $(empty)
558
559# Arithmetic
560# $(1) is the number to increment
561NUM32 = 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
562increment = $(words x $(wordlist 1,$(1),$(NUM32)))
563decrement = $(words $(wordlist 2,$(1),$(NUM32)))
564
565# Create a sequence from 1 to $(1)
566# F(N) = if N > 0: return F(N-1) + "N" else: return ""
567sequence = $(if $(wordlist 1,$(1),$(NUM32)),$(call sequence,$(call decrement,$(1))) $(1),)
568
569# Reverse a list of words in $(1)
570reverse = $(if $(word 2,$(1)),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(word 1,$(1))
571
572# vim: set ft=make:
573