1# -*- mode: makefile;-*- 2# 3# Copyright (C) 2010-2012 Apple Inc. All rights reserved. 4# 5# MakeInc.top is the top-level makefile for the xnu 6# build system. All the main XBS targets 7# (like "installhdrs") are defined here, as 8# well as globals that can be overridden on 9# the command-line by the user. 10# 11# This makefile's main purpose is to bootstrap 12# the user's intent ("build these 3 kernels") 13# into 3 single-architecture builds that each 14# invoke the recursive make build system. 15# As such, we have no knowledge of how to build 16# a kernel or perform actions other than 17# invoking a sub-make with a different 18# current directory, makefile, and target. One 19# side effect of this is that each 20# single-architecture build is responsible for 21# inserting its build products into the final 22# multi-architecture output files. To avoid 23# races, these aggregating stages for 24# "primary" build configs are done in serial. 25# 26 27export MakeInc_cmd=${VERSDIR}/makedefs/MakeInc.cmd 28 29include $(MakeInc_cmd) 30 31 32# 33# Architecture Configuration options 34# 35 36# Default to current kernel architecture 37ifeq ($(PLATFORM),iPhoneOS) 38 override DEFAULT_ARCH_CONFIG := ARM 39else ifeq ($(PLATFORM),iPhoneSimulator) 40 override DEFAULT_ARCH_CONFIG := X86_64 41else 42 override DEFAULT_ARCH_CONFIG := X86_64 43endif 44 45 46# Accept either explicit ARCH_CONFIGS or XBS-style RC_ARCHS 47ifndef ARCH_CONFIGS 48ifdef RC_ARCHS 49ARCH_CONFIGS := $(shell printf "%s" "$(RC_ARCHS)" | $(TR) a-z A-Z | sed -E 's/ARMV[0-9][A-Z]?/ARM/g' | $(TR) " " "\n" | sort -u | $(TR) "\n" " ") 50else 51ARCH_CONFIGS := DEFAULT 52endif 53endif 54 55# 56# Kernel Configuration options 57# 58 59ifeq ($(RC_ProjectName),xnu_debug) 60override DEFAULT_KERNEL_CONFIG := DEBUG 61else ifeq ($(PLATFORM),iPhoneOS) 62override DEFAULT_KERNEL_CONFIG := DEVELOPMENT 63else 64override DEFAULT_KERNEL_CONFIG := RELEASE 65endif 66 67# If KERNEL_CONFIGS is specified it should override default 68ifndef KERNEL_CONFIGS 69KERNEL_CONFIGS := DEFAULT 70endif 71 72# 73# Machine Configuration options 74# 75 76override DEFAULT_I386_MACHINE_CONFIG := NONE 77override DEFAULT_X86_64_MACHINE_CONFIG := NONE 78 79 80# This is typically never specified (TARGET_CONFIGS is used) 81ifndef MACHINE_CONFIGS 82MACHINE_CONFIGS := DEFAULT 83endif 84 85# 86# Target configuration options. NOTE - target configurations will 87# override ARCH_CONFIGS and KERNEL_CONFIGS and MACHINE_CONFIGS. 88# 89# Target configs come in groups of three parameters. The first is the 90# kernel configuration, the second is the architecture configuration, 91# and the third is the machine configuration. You may pass in as 92# many groups of configurations as you wish. Each item passed in is 93# seperated by whitespace. 94# 95# Example: 96# TARGET_CONFIGS="release ppc default debug i386 default release arm MX31ADS" 97# Parameters may be in upper or lower case (they are converted to upper). 98# 99# "default" parameter is a special case. It means use the default value for 100# that parameter. Here are the default values for each configuration: 101# 102# default kernel configuration = DEFAULT_KERNEL_CONFIG 103# default architecture configuration = system architecture where you are running make. 104 105 106ifndef TARGET_CONFIGS 107ifneq ($(PRODUCT_CONFIGS),) 108# generate TARGET_CONFIGS using KERNEL_CONFIGS and PRODUCT_CONFIGS 109TARGET_CONFIGS := $(foreach my_kernel_config,$(KERNEL_CONFIGS),$(foreach my_product_config,$(shell printf "%s" "$(PRODUCT_CONFIGS)" | $(TR) A-Z a-z),$(my_kernel_config) $(subst ;, ,$(call function_lookup_product,$(my_product_config))))) 110else ifneq ($(filter %_embedded,$(MAKECMDGOALS)),) 111# generate TARGET_CONFIGS for all kernel configs and products in the device map 112TARGET_CONFIGS := $(foreach my_kernel_config,$(KERNEL_CONFIGS_EMBEDDED),$(foreach my_arch_config,$(ARCH_CONFIGS_EMBEDDED),$(foreach my_product_config,$(DEVICEMAP_PRODUCTS_$(my_arch_config)),$(my_kernel_config) $(subst ;, ,$(call function_lookup_product,$(my_product_config)))))) 113else 114# generate TARGET_CONFIGS using KERNEL_CONFIGS and ARCH_CONFIGS and MACHINE_CONFIGS (which defaults to "DEFAULT") 115TARGET_CONFIGS := $(foreach my_kern_config, $(KERNEL_CONFIGS), $(foreach my_arch_config, $(ARCH_CONFIGS), $(foreach my_machine_config, $(MACHINE_CONFIGS), $(my_kern_config) $(my_arch_config) $(my_machine_config)))) 116endif 117endif 118 119ifeq ($(TARGET_CONFIGS),) 120$(error No TARGET_CONFIGS specified) 121endif 122 123TARGET_CONFIGS_UC := $(strip $(shell printf "%s" "$(TARGET_CONFIGS)" | $(TR) a-z A-Z)) 124 125# 126# Build Configurations 127# 128# TARGET_CONFIGS is unwieldy for use in Makefiles. Convert them to 129# "build configurations" which are tuples joined by "^". For 130# example, "RELEASE I386 DEFAULT DEVELOPMENT ARM DEFAULT" becomes 131# "RELEASE^I386^NONE DEVELOPMENT^ARM^S5L8920X", which can be looped 132# over trivially. PRIMARY_BUILD_CONFIGS is the first config 133# for each architecture, used primarily for machine-dependent recursion. 134 135BUILD_CONFIGS = $(call function_create_build_configs, $(TARGET_CONFIGS_UC)) 136 137PRIMARY_ARCHS = $(strip $(sort $(foreach build_config, $(BUILD_CONFIGS), $(call function_extract_arch_config_from_build_config, $(build_config))))) 138PRIMARY_BUILD_CONFIGS = $(strip $(foreach arch, $(PRIMARY_ARCHS), $(firstword $(foreach build_config, $(BUILD_CONFIGS), $(if $(filter $(arch),$(call function_extract_arch_config_from_build_config, $(build_config))), $(build_config), ))))) 139NON_PRIMARY_BUILD_CONFIGS = $(strip $(filter-out $(PRIMARY_BUILD_CONFIGS), $(BUILD_CONFIGS))) 140FIRST_BUILD_CONFIG = $(firstword $(BUILD_CONFIGS)) 141 142# $(warning PRIMARY_ARCHS is $(PRIMARY_ARCHS)) 143# $(warning TARGET_CONFIGS is $(TARGET_CONFIGS)) 144# $(warning BUILD_CONFIGS is $(BUILD_CONFIGS)) 145# $(warning PRIMARY_BUILD_CONFIGS is $(PRIMARY_BUILD_CONFIGS)) 146# $(warning NON_PRIMARY_BUILD_CONFIGS is $(NON_PRIMARY_BUILD_CONFIGS)) 147 148MEMORY_SIZE := $(shell /usr/sbin/sysctl -n hw.memsize) 149 150# Embedded kernels use LTO by default. 151ifeq ($(PLATFORM),iPhoneOS) 152export BUILD_LTO := 1 153endif 154 155LARGE_BUILD_FOOTPRINT := $(BUILD_LTO) 156 157ifeq ($(LARGE_BUILD_FOOTPRINT),1) 158RAM_PER_KERNEL_BUILD := 8589934592 159FLOCK_SIZE := $(shell if [ $(MEMORY_SIZE) -le $$((1 * $(RAM_PER_KERNEL_BUILD))) ]; then echo 1; elif [ $(MEMORY_SIZE) -gt $$((8 * $(RAM_PER_KERNEL_BUILD))) ]; then echo 8; else expr $(MEMORY_SIZE) / $(RAM_PER_KERNEL_BUILD); fi ) 160else 161RAM_PER_KERNEL_BUILD := 268435456 162FLOCK_SIZE := $(shell if [ $(MEMORY_SIZE) -le $$((2 * $(RAM_PER_KERNEL_BUILD))) ]; then echo 2; elif [ $(MEMORY_SIZE) -gt $$((8 * $(RAM_PER_KERNEL_BUILD))) ]; then echo 8; else expr $(MEMORY_SIZE) / $(RAM_PER_KERNEL_BUILD); fi ) 163endif 164 165# $(warning Building $(FLOCK_SIZE) kernels in parallel) 166 167# 168# TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template 169# 170# $(1) is the name of the makefile target to invoke for the each build config 171# after setting up the parallel hierarchy in the TARGET directory 172# $(2) is an optional suffix on the TARGET directory, which might even be 173# "/.." 174# $(3) are any dependencies for the bootstrap target 175# $(4) are any dependencies that are expanded per-build config to another bootstrap target 176# $(5) is how many build configurations to build in parallel 177# $(6) is which build configs to build in parallel 178# 179# Since building many configurations in parallel may overwhelm the system, 180# we try to throttle behavior into more managable "flocks" of N configurations 181# at once, by creating a dependency on all members of the previous flock. 182 183define TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template 184 185# Create a list of synthesized targets for each build config 186$(1)_bootstrap_target_list = $$(addprefix $(1)_bootstrap_,$(6)) 187 188.PHONY: $$($(1)_bootstrap_target_list) 189 190$$(eval $$(call _function_generate_flock_groupings,$(1),$$(wordlist 1,$(5),$(6)),$$(wordlist $(call increment,$(5)),$$(words $(6)),$(6)),,$(5))) 191 192$$($(1)_bootstrap_target_list): $(1)_bootstrap_% : $(1)_flock_dep_for_% $$(addsuffix _bootstrap_%,$(4)) $(3) 193 $$(_v)$$(MKDIR) $${OBJROOT}/$$(call function_convert_build_config_to_objdir,$$(patsubst $(1)_bootstrap_%,%,$$@))$(2) 194 $$(_v)$${MAKE} \ 195 -C $${OBJROOT}/$$(call function_convert_build_config_to_objdir,$$(patsubst $(1)_bootstrap_%,%,$$@))$(2) \ 196 -f $${SRCROOT}/Makefile \ 197 CURRENT_KERNEL_CONFIG=$$(call function_extract_kernel_config_from_build_config,$$(patsubst $(1)_bootstrap_%,%,$$@)) \ 198 CURRENT_ARCH_CONFIG=$$(call function_extract_arch_config_from_build_config,$$(patsubst $(1)_bootstrap_%,%,$$@)) \ 199 CURRENT_MACHINE_CONFIG=$$(call function_extract_machine_config_from_build_config,$$(patsubst $(1)_bootstrap_%,%,$$@)) \ 200 CURRENT_BUILD_CONFIG=$$(patsubst $(1)_bootstrap_%,%,$$@) \ 201 PRIMARY_BUILD_CONFIGS="$(PRIMARY_BUILD_CONFIGS)" \ 202 SOURCE=$${SRCROOT}/ \ 203 RELATIVE_SOURCE_PATH=. \ 204 TARGET=$${OBJROOT}/$$(call function_convert_build_config_to_objdir,$$(patsubst $(1)_bootstrap_%,%,$$@))$(2)/ \ 205 OBJPATH=$${OBJROOT}/$$(call function_convert_build_config_to_objdir,$$(patsubst $(1)_bootstrap_%,%,$$@)) \ 206 $(1) 207 208.PHONY: $(1)_bootstrap 209 210$(1)_bootstrap: $$($(1)_bootstrap_target_list) 211endef 212 213# 214# TOP_LEVEL_FLOCK_DEPENDENCY_template 215# 216# $(1) is the Makefile target we are building for 217# $(2) are the members of the current flock 218# $(3) is what the flock depends on. None of the build 219# configs in $(2) will start building until all of 220# $(3) are done building 221 222define TOP_LEVEL_FLOCK_DEPENDENCY_template 223 224.PHONY: $(addprefix $(1)_flock_dep_for_,$(2)) 225 226$(addprefix $(1)_flock_dep_for_,$(2)): $(addprefix $(1)_bootstrap_,$(3)) 227 228endef 229 230# $(1) is the Makefile target we are building for 231# $(2) is the first flock (5 build configs) 232# $(3) is the rest of the build configs 233# $(4) is the build configs that the first flock depends on 234# $(5) is the flock size 235_function_generate_flock_groupings = $(if $(3), $(call _function_generate_flock_groupings,$(1),$(wordlist 1,$(5),$(3)),$(wordlist $(call increment,$(5)),$(words $(3)),$(3)),$(2),$(5))) $(call TOP_LEVEL_FLOCK_DEPENDENCY_template,$(1),$(2),$(4)) 236 237# 238# Setup pass for build system tools 239# 240 241generated_top_level_build_setup = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_setup,/..,,,$(FLOCK_SIZE),$(FIRST_BUILD_CONFIG)) 242ifeq ($(VERBOSE),YES) 243$(warning Generate makefile fragment: $(generated_top_level_build_setup)) 244endif 245$(eval $(generated_top_level_build_setup)) 246 247.PHONY: setup 248 249setup: build_setup_bootstrap 250 251# 252# Install kernel header files 253# 254.PHONY: exporthdrs exporthdrs_mi exporthdrs_md 255 256exporthdrs: exporthdrs_mi exporthdrs_md 257 258# 259# Install machine independent kernel header files 260# 261 262generated_top_level_build_exporthdrs_mi = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_exporthdrs_mi,,setup,,1,$(FIRST_BUILD_CONFIG)) 263ifeq ($(VERBOSE),YES) 264$(warning Generate makefile fragment: $(generated_top_level_build_exporthdrs_mi)) 265endif 266$(eval $(generated_top_level_build_exporthdrs_mi)) 267 268exporthdrs_mi: build_exporthdrs_mi_bootstrap 269 270# 271# Install machine dependent kernel header files 272# 273 274generated_top_level_build_exporthdrs_md = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_exporthdrs_md,,setup,,$(FLOCK_SIZE),$(PRIMARY_BUILD_CONFIGS)) 275ifeq ($(VERBOSE),YES) 276$(warning Generate makefile fragment: $(generated_top_level_build_exporthdrs_md)) 277endif 278$(eval $(generated_top_level_build_exporthdrs_md)) 279 280exporthdrs_md: build_exporthdrs_md_bootstrap 281 282# 283# Install kernel header files 284# 285 286.PHONY: installhdrs installhdrs_mi installhdrs_md 287 288ifeq ($(RC_ProjectName),xnu_debug) 289installhdrs: 290 @: 291else 292 293installhdrs: installhdrs_mi installhdrs_md 294endif 295 296.PHONY: installhdrs_embedded 297 298installhdrs_embedded: installhdrs 299 300# 301# Install machine independent header files 302# 303 304generated_top_level_build_installhdrs_mi = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_installhdrs_mi,,setup exporthdrs_mi,,1,$(FIRST_BUILD_CONFIG)) 305ifeq ($(VERBOSE),YES) 306$(warning Generate makefile fragment: $(generated_top_level_build_installhdrs_mi)) 307endif 308$(eval $(generated_top_level_build_installhdrs_mi)) 309 310installhdrs_mi: exporthdrs_mi build_installhdrs_mi_bootstrap 311 312# 313# Install machine dependent kernel header files 314# 315 316generated_top_level_build_installhdrs_md = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_installhdrs_md,,setup exporthdrs_md,,$(FLOCK_SIZE),$(PRIMARY_BUILD_CONFIGS)) 317ifeq ($(VERBOSE),YES) 318$(warning Generate makefile fragment: $(generated_top_level_build_installhdrs_md)) 319endif 320$(eval $(generated_top_level_build_installhdrs_md)) 321 322installhdrs_md: exporthdrs_md build_installhdrs_md_bootstrap 323 324# 325# Build all architectures for all Configuration/Architecture options 326# 327 328generated_top_level_build_all = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_all,,setup exporthdrs,,$(FLOCK_SIZE),$(BUILD_CONFIGS)) 329ifeq ($(VERBOSE),YES) 330$(warning Generate makefile fragment: $(generated_top_level_build_all)) 331endif 332$(eval $(generated_top_level_build_all)) 333 334.PHONY: build 335 336build: build_all_bootstrap 337 338# 339# Post-process build results 340# 341 342generated_top_level_config_all = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,config_all,,setup,build_all,$(FLOCK_SIZE),$(BUILD_CONFIGS)) 343ifeq ($(VERBOSE),YES) 344$(warning Generate makefile fragment: $(generated_top_level_config_all)) 345endif 346$(eval $(generated_top_level_config_all)) 347 348.PHONY: all 349 350all: config_all_bootstrap 351 352.PHONY: all_embedded 353 354all_embedded: all 355 356# 357# Install kernel and header files 358# 359 360generated_top_level_build_install_primary = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_install_primary,,setup,config_all,1,$(PRIMARY_BUILD_CONFIGS)) 361ifeq ($(VERBOSE),YES) 362$(warning Generate makefile fragment: $(generated_top_level_build_install_primary)) 363endif 364$(eval $(generated_top_level_build_install_primary)) 365 366generated_top_level_build_install_non_primary = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_install_non_primary,,setup,config_all,$(FLOCK_SIZE),$(NON_PRIMARY_BUILD_CONFIGS)) 367ifeq ($(VERBOSE),YES) 368$(warning Generate makefile fragment: $(generated_top_level_build_install_non_primary)) 369endif 370$(eval $(generated_top_level_build_install_non_primary)) 371 372 373.PHONY: install 374 375ifeq ($(RC_ProjectName),xnu_debug) 376 377install: build_install_primary_bootstrap build_install_non_primary_bootstrap 378else ifeq ($(RC_ProjectName),xnu_headers_Sim) 379install: installhdrs 380else 381 382install: all installhdrs installman build_install_primary_bootstrap build_install_non_primary_bootstrap 383endif 384 385.PHONY: install_embedded 386 387install_embedded: install 388 389# 390# Install man pages 391# 392 393generated_top_level_build_installman = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,build_installman,,setup,,1,$(FIRST_BUILD_CONFIG)) 394ifeq ($(VERBOSE),YES) 395$(warning Generate makefile fragment: $(generated_top_level_build_installman)) 396endif 397$(eval $(generated_top_level_build_installman)) 398 399.PHONY: installman 400 401installman: setup build_installman_bootstrap 402 403# 404# Install source tree 405# 406.PHONY: installsrc 407 408installsrc: 409 @echo INSTALLSRC $(SRCROOT) 410 $(_v)$(MKDIR) $(SRCROOT) 411 $(_v)($(TAR) -c --mode go=r,+X --no-ignore-case --exclude .git --exclude .svn --exclude cscope.\* --exclude BUILD --exclude \*~ -f - .) | (cd $(SRCROOT) && $(TAR) --no-same-owner -xf -) 412 413 414# 415# Clean up source tree 416# 417.PHONY: clean 418 419clean: 420 @: 421 422# 423# Build source file list for cscope database and tags 424# 425cscope.files: 426 @echo "Building file list for cscope and tags" 427 @find . -name '*.h' -type f | grep -v ^..BUILD > _cscope.files 2> /dev/null 428 @find . -name '*.defs' -type f | grep -v ^..BUILD >> _cscope.files 2> /dev/null 429 @find . -name '*.c' -type f | grep -v ^..BUILD >> _cscope.files 2> /dev/null 430 @find . -name '*.cpp' -type f | grep -v ^..BUILD >> _cscope.files 2> /dev/null 431 @find . -name '*.s' -type f | grep -v ^..BUILD >> _cscope.files 2> /dev/null 432 @find . -name '*.h.template' -type f | grep -v ^..BUILD >> _cscope.files 2> /dev/null 433 @echo -k -q -c > cscope.files 2> /dev/null 434 @sort -u < _cscope.files >> cscope.files 2> /dev/null 435 @rm -f _cscope.files _cscope.files2 2> /dev/null 436 437# 438# Build cscope database 439# 440cscope: cscope.files 441 @echo "Building cscope database" 442 @cscope -bvU 2> /dev/null 443 444# 445# Build tags 446# 447tags: cscope.files 448 @echo "Building ctags" 449 @-sed 1d cscope.files | xargs ctags -dtw 2> /dev/null || \ 450 echo "Phantom files detected!" 2>&1 > /dev/null 451 @-[ -f TAGS ] || ${MAKE} -f $(firstword $(MAKEFILE_LIST)) TAGS 452 453TAGS: cscope.files 454 @echo "Building etags" 455 @-cat cscope.files | etags -l auto -S - 2> /dev/null 456 457help: 458 @cat README 459 460print_exports: 461 $(_v)printenv | sort 462 463 464generated_top_level_print_exports = $(call TOP_LEVEL_EACH_BUILD_CONFIG_BOOTSTRAP_template,print_exports,,,,1,$(FIRST_BUILD_CONFIG)) 465ifeq ($(VERBOSE),YES) 466$(warning Generate makefile fragment: $(generated_top_level_print_exports)) 467endif 468$(eval $(generated_top_level_print_exports)) 469 470print_exports_first_build_config: print_exports_bootstrap 471