1# Copyright (C) 2021-2022 Intel Corporation. 2# SPDX-License-Identifier: BSD-3-Clause 3 4# usage: check_coexistence <symbol 1> <symbol 2> 5# 6# This macro checks if the given symbols are both defined or both not. This is used to check the coexistence of BOARD & 7# SCENARIO or BOARD_FILE & SCENARIO_FILE. 8define check_coexistence = 9ifdef $(1) 10 ifndef $(2) 11 $$(warning $(1) is defined while $(2) is empty) 12 $$(error $(1) & $(2) must be given in pair) 13 endif 14else 15 ifdef $(2) 16 $$(warning $(2) is defined while $(1) is empty) 17 $$(error $(1) & $(2) must be given in pair) 18 endif 19endif 20endef 21 22# usage: determine_config <symbol> 23# 24# BOARD and SCENARIO can be specified in the following places. 25# 26# 1. Configuration data in config.mk (named CONFIG_BOARD or CONFIG_SCENARIO) which are extracted from the existing XML 27# file. 28# 29# 2. Variables defined on the command line when invoking 'make'. 30# 31# In place #2 it can be either a board/scenario name or path to an XML file. Depending on where these variables are 32# defined and their values, this script behaves as follows. 33# 34# * If a variable is defined in both #1 and #2 with the same value, that value is effective for the build. 35# 36# * If a variable is defined in both #1 and #2 with different values, the build terminates with an error message. 37# 38# * If a variable is defined in either #1 or #2 (but not both), that value is effective for the build. 39# 40# * If a variable is defined in neither #1 nor #2, the build terminates with an error message. 41# 42# If #2 gives a path to an XML file, the board/scenario defined in that file is used for the comparison above. 43# 44# This macro implements the policy. The following variables will be rewritten after the rules are evaluated without any 45# error. 46# 47# * The <symbol> (i.e. either BOARD or SCENARIO) will always hold the name of the effective board/scenario. 48# 49# * The <symbol>_FILE (i.e. either BOARD_FILE or SCENARIO_FILE) will hold the path to an existing XML file that 50# defines the effective board/scenario. If only a BOARD/SCENARIO name is given from the command line, a predefined 51# configuration under misc/config_tools/data/$BOARD will be used. If neither <symbol>_FILE nor <symbol> is given, 52# this variable has an empty string as its value. 53# 54define determine_config = 55ifneq ($($(1)),) 56 ifneq ($(realpath $($(1))),) 57 override $(1)_FILE := $($(1)) 58 ifneq (SCENARIO, $(1)) 59 override $(1) := $$(shell xmllint --xpath 'string(/acrn-config/@$(shell echo $(1) | tr A-Z a-z))' $$($(1)_FILE)) 60 else 61 scenario_name := $(subst .xml,,$(notdir $($(1)))) 62 override $(1) := $$(if $$(subst scenario,,$$(scenario_name)),$$(scenario_name),$(notdir $(abspath $(dir $($(1)))))) 63 endif 64 else 65 override $(1)_FILE := $(HV_PREDEFINED_DATA_DIR)/$$(BOARD)/$$($(1)).xml 66 ifeq ($$(realpath $$($(1)_FILE)),) 67 $$(error $(1) = '$($(1))' is neither path to a file nor name of a predefined board) 68 endif 69 endif 70 ifdef CONFIG_$(1) 71 ifneq ($$($(1)), $(CONFIG_$(1))) 72 $$(warning The command line sets $(1) to be '$$($(1))', but an existing build is configured with '$(CONFIG_$(1))') 73 $$(warning Try cleaning up the existing build with 'make clean' or setting HV_OBJDIR to a newly-created directory) 74 $$(error Configuration conflict identified) 75 endif 76 endif 77else 78 ifdef CONFIG_$(1) 79 override $(1) := $(CONFIG_$(1)) 80 override $(1)_FILE := 81 else 82 $$(error There is no $(1) parameter specified on the command-line and none from a previous build. Please provide a valid $(1) parameter) 83 endif 84endif 85endef 86 87# usage: determine_build_type <default> 88# 89# Similar to BOARD or SCENARIO, the RELEASE variable has three sources where it can be defined. But unlike those 90# variables that cannot be modified once configured, users shall be able to tweak RELEASE from the command line even a 91# build directory has already been configured. 92# 93# This macro implements the same check as determine_config, but attempts to update the configuration file if RELEASE is 94# changed. 95define determine_build_type = 96ifdef RELEASE 97 ifdef CONFIG_RELEASE 98 ifneq ($(RELEASE),$(CONFIG_RELEASE)) 99 $$(warning The command line sets RELEASE to be '$(RELEASE)', but an existing build is configured with '$(CONFIG_RELEASE)') 100 $$(warning The configuration will be modified for RELEASE=$(RELEASE)) 101 ifeq ($(RELEASE),y) 102 $$(shell sed -i "s@\(<BUILD_TYPE.*>\).*\(</BUILD_TYPE>\)@\1release\2@g" $(HV_SCENARIO_XML)) 103 else 104 $$(shell sed -i "s@\(<BUILD_TYPE.*>\).*\(</BUILD_TYPE>\)@\1debug\2@g" $(HV_SCENARIO_XML)) 105 endif 106 endif 107 endif 108else 109 ifdef CONFIG_RELEASE 110 override RELEASE := $(CONFIG_RELEASE) 111 else 112 override RELEASE := $(1) 113 endif 114endif 115endef 116 117# Paths to the inputs 118HV_BOARD_XML := $(HV_OBJDIR)/.board.xml 119HV_SCENARIO_XML := $(HV_OBJDIR)/.scenario.xml 120HV_UNIFIED_XML_IN := $(BASEDIR)/scripts/makefile/unified.xml.in 121HV_PREDEFINED_DATA_DIR := $(realpath $(BASEDIR)/../misc/config_tools/data) 122HV_CONFIG_TOOL_DIR := $(realpath $(BASEDIR)/../misc/config_tools) 123HV_CONFIG_XFORM_DIR := $(HV_CONFIG_TOOL_DIR)/xforms 124 125# Paths to the outputs: 126HV_CONFIG_DIR := $(HV_OBJDIR)/configs 127HV_ALLOCATION_XML := $(HV_CONFIG_DIR)/allocation.xml 128HV_UNIFIED_XML := $(HV_CONFIG_DIR)/unified.xml 129HV_CONFIG_H := $(HV_OBJDIR)/include/config.h 130HV_CONFIG_MK := $(HV_CONFIG_DIR)/config.mk 131HV_VALIDATION_TIMESTAMP := $(HV_CONFIG_DIR)/.validation.timestamp 132HV_CONFIG_TIMESTAMP := $(HV_CONFIG_DIR)/.configfiles.timestamp 133HV_DIFFCONFIG_LIST := $(HV_CONFIG_DIR)/.diffconfig 134 135# Directory containing generated configuration sources for diffconfig 136HV_CONFIG_A_DIR := $(HV_OBJDIR)/a 137# Directory containing edited configuration sources for diffconfig 138HV_CONFIG_B_DIR := $(HV_OBJDIR)/b 139# Patch encoding differences between generated and edited config. sources 140HV_CONFIG_DIFF := $(HV_OBJDIR)/config.patch 141 142# Backward-compatibility for RELEASE=(0|1) 143ifdef RELEASE 144 ifeq ($(RELEASE),1) 145 override RELEASE := y 146 else 147 ifeq ($(RELEASE),0) 148 override RELEASE := n 149 endif 150 endif 151endif 152 153# BOARD/SCENARIO/BOARD_FILE/SCENARIO_FILE parameters sanity check. 154# 155# 1. Raise an error if BOARD/SCENARIO (or BOARD_FILE/SCENARIO_FILE) are partially given. 156# 2. Raise an error if BOARD_FILE/SCENARIO_FILE are given but do not point to valid XMLs. 157 158$(eval $(call check_coexistence,BOARD,SCENARIO)) 159$(eval $(call check_coexistence,BOARD_FILE,SCENARIO_FILE)) 160 161# BOARD_FILE/SCENARIO_FILE are to be obsoleted. Users can now use BOARD/SCENARIO to give either pre-defined 162# board/scenario or their own XML files. 163# 164# The following block converts BOARD_FILE/SCENARIO_FILE to BOARD/SCENARIO. Removing support of BOARD_FILE/SCENARIO_FILE 165# can be done by simply deleting it. 166ifneq ($(BOARD_FILE)$(SCENARIO_FILE),) 167 $(warning BOARD_FILE/SCENARIO_FILE are obsoleted. Use BOARD/SCENARIO to specify either predefined board/scenario or your own board/scenario XMLs) 168 169 ifneq ($(BOARD)$(SCENARIO),) 170 $(warning BOARD/SCENARIO and BOARD_FILE/SCENARIO_FILE are both given. BOARD/SCENARIO will take precedence) 171 else 172 ifneq ($(BOARD_FILE), $(wildcard $(BOARD_FILE))) 173 $(error BOARD_FILE: $(BOARD_FILE) does not exist) 174 endif 175 ifneq ($(SCENARIO_FILE), $(wildcard $(SCENARIO_FILE))) 176 $(error SCENARIO_FILE: $(SCENARIO_FILE) does not exist) 177 endif 178 BOARD := $(BOARD_FILE) 179 SCENARIO := $(SCENARIO_FILE) 180 endif 181endif 182 183# Internally we still use BOARD to represent the name of the target board and BOARD_FILE to be the path to the board XML 184# file. SCENARIO/SCENARIO_FILE are used in the same way. The following block translates the user-visible BOARD/SCENARIO 185# (which is multiplexed) to the internal representation. 186 187ifeq ($(findstring $(MAKECMDGOALS),distclean),) 188-include $(HV_CONFIG_MK) 189$(eval $(call determine_config,BOARD)) 190$(eval $(call determine_config,SCENARIO)) 191$(eval $(call determine_build_type,n)) 192endif 193 194$(HV_BOARD_XML): $(BOARD_FILE) 195 @echo "Board XML is fetched from $(realpath $(BOARD_FILE))" 196 @mkdir -p $(dir $(HV_BOARD_XML)) 197 @cp $(BOARD_FILE) $(HV_BOARD_XML) 198 199$(HV_SCENARIO_XML): $(SCENARIO_FILE) 200 @echo "Scenario XML is fetched from $(abspath $(SCENARIO_FILE))" 201 @mkdir -p $(dir $(HV_SCENARIO_XML)) 202 @python3 $(HV_CONFIG_TOOL_DIR)/scenario_config/default_populator.py $(SCENARIO_FILE) $(HV_SCENARIO_XML) 203 @sed "s#<acrn-config.*#<acrn-config scenario=\"$(SCENARIO)\" >#g" -i $(HV_SCENARIO_XML) 204 205# A unified XML is generated to include board and scenario XML files so that XSLT scripts have access to both for 206# generating source files. 207$(HV_ALLOCATION_XML): $(HV_BOARD_XML) $(HV_SCENARIO_XML) $(HV_VALIDATION_TIMESTAMP) | $(HV_CONFIG_DIR) 208 @python3 $(HV_CONFIG_TOOL_DIR)/static_allocators/main.py --board $(HV_BOARD_XML) --scenario $(HV_SCENARIO_XML) --output $(HV_ALLOCATION_XML) 209 @echo "$@ generated" 210 211$(HV_UNIFIED_XML): $(HV_BOARD_XML) $(HV_SCENARIO_XML) $(HV_ALLOCATION_XML) | $(HV_CONFIG_DIR) 212 @sed "s/{BOARD_FILE}/$(subst /,\\/,$(realpath $(HV_BOARD_XML)))/g" $(HV_UNIFIED_XML_IN) | \ 213 sed "s/{SCENARIO_FILE}/$(subst /,\\/,$(HV_SCENARIO_XML))/g" | \ 214 sed "s/{ALLOCATION_FILE}/$(subst /,\\/,$(HV_ALLOCATION_XML))/g" > $@ 215 @echo "$@ generated" 216 217$(HV_CONFIG_MK): $(HV_UNIFIED_XML) | $(HV_CONFIG_DIR) 218 @xsltproc -o $@ --xinclude --xincludestyle $(HV_CONFIG_XFORM_DIR)/config.mk.xsl $< 219 @echo "$@ generated" 220 221$(HV_CONFIG_H): $(HV_UNIFIED_XML) 222 @mkdir -p $(dir $(HV_CONFIG_H)) 223 @xsltproc -o $@ --xinclude --xincludestyle $(HV_CONFIG_XFORM_DIR)/config.h.xsl $< 224 @echo "$@ generated" 225 226$(HV_VALIDATION_TIMESTAMP): $(HV_BOARD_XML) $(HV_SCENARIO_XML) | $(HV_CONFIG_DIR) 227 @echo "Validating scenario configurations..." 228 @python3 $(HV_CONFIG_TOOL_DIR)/scenario_config/validator.py $(HV_BOARD_XML) $(HV_SCENARIO_XML) 229 @touch $@ 230 231$(HV_CONFIG_TIMESTAMP): $(HV_VALIDATION_TIMESTAMP) $(HV_UNIFIED_XML) ${HV_DIFFCONFIG_LIST} | $(HV_CONFIG_DIR) 232 @sh $(BASEDIR)/scripts/genconf.sh $(BASEDIR) $(HV_BOARD_XML) $(HV_SCENARIO_XML) $(HV_CONFIG_DIR) $(HV_UNIFIED_XML) 233 @touch $@ 234 235.PHONY: defconfig 236defconfig: $(HV_CONFIG_TIMESTAMP) 237 238showconfig: 239 @echo "Build directory: $(HV_OBJDIR)" 240 @echo "This build directory is configured with the settings below." 241 @echo "- BOARD = $(BOARD)" 242 @echo "- SCENARIO = $(SCENARIO)" 243 @echo "- RELEASE = $(RELEASE)" 244 245diffconfig: 246 @rm -rf $(HV_CONFIG_A_DIR) $(HV_CONFIG_B_DIR) 247 @sh $(BASEDIR)/scripts/genconf.sh $(BASEDIR) $(HV_BOARD_XML) $(HV_SCENARIO_XML) $(HV_CONFIG_A_DIR) $(HV_UNIFIED_XML) 248 @find $(HV_CONFIG_A_DIR) -name '*.aml' -delete 249 @cd $(HV_CONFIG_DIR) && find . -name '*.c' -or -name '*.h' -or -name '*.config' -or -name '*.asl' | while read f; do \ 250 nf=$(HV_CONFIG_B_DIR)/$${f}; mkdir -p `dirname $${nf}` && cp $${f} $${nf}; \ 251 done 252 @cd $(HV_OBJDIR) && git diff --no-index --no-prefix a/ b/ > $(HV_CONFIG_DIFF) || true 253 @echo "Diff on generated configuration files is available at $(HV_CONFIG_DIFF)." 254 @echo "To make a patch effective, use 'applydiffconfig PATCH=/path/to/patch' to register it to a build." 255 256applydiffconfig: 257ifdef PATCH 258 ifneq ($(realpath $(PATCH)),) 259 ifeq ($(shell grep '^$(realpath ${PATCH})$$' ${HV_DIFFCONFIG_LIST}),) 260 @echo $(realpath $(PATCH)) >> ${HV_DIFFCONFIG_LIST} 261 @echo "${PATCH} is registered for build directory ${HV_OBJDIR}." 262 @echo "Registered patches will be applied the next time 'make' is invoked." 263 @echo "To unregister a patch, remove it from ${HV_DIFFCONFIG_LIST}." 264 else 265 @echo "${PATCH} is already registered for build directory ${HV_OBJDIR}." 266 @echo "To unregister a patch, remove it from ${HV_DIFFCONFIG_LIST}." 267 endif 268 else 269 @echo "${PATCH}: No such file or directory" 270 endif 271else 272 @echo "No patch file or directory is specified" 273 @echo "Try 'make applydiffconfig PATCH=/path/to/patch' to register patches for generated configuration files." 274 ifneq ($(realpath $(HV_DIFFCONFIG_LIST)),) 275 @echo "Registers patches:" 276 @cat $(HV_DIFFCONFIG_LIST) 277 endif 278endif 279 280$(HV_DIFFCONFIG_LIST): | $(HV_CONFIG_DIR) 281 @touch $@ 282 283menuconfig: 284 @echo "To tweak the configurations, run $(HV_CONFIG_TOOL_DIR)/config_app/app.py using python3 and load $(HV_SCENARIO_XML) in the web browser." 285 286$(HV_CONFIG_DIR): 287 @mkdir -p $@ 288 289# Legacy variables and targets 290ifdef TARGET_DIR 291 $(warning TARGET_DIR is obsoleted because generated configuration files are now stored in the build directory) 292endif 293 294oldconfig: 295 @echo "Generated configuration files are now automatically updated with the scenario XML file." 296 @echo "There is no need to invoke oldconfig manually anymore." 297 298update_config: 299 @echo "Generated configuration files are now automatically updated with the scenario XML file." 300 @echo "There is no need to invoke update_config manually anymore." 301 302CFLAGS += -include $(HV_CONFIG_H) 303