1# 2# Arm SCP/MCP Software 3# Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved. 4# 5# SPDX-License-Identifier: BSD-3-Clause 6# 7 8# 9# Directories 10# 11export TOP_DIR := $(shell pwd) 12export ARCH_DIR := $(TOP_DIR)/arch 13export FWK_DIR := $(TOP_DIR)/framework 14export TOOLS_DIR := $(TOP_DIR)/tools 15export PRODUCTS_DIR := $(TOP_DIR)/product 16export MODULES_DIR := $(TOP_DIR)/module 17export DOC_DIR := $(TOP_DIR)/doc 18export MOD_TEST_DIR := $(TOP_DIR)/unit_test 19export MOD_TEST_BUILD_DIR=$(BUILD_DIR)/module/test 20export FWK_TEST_DIR=$(FWK_DIR)/test 21export FWK_TEST_BUILD_DIR=$(BUILD_DIR)/framework/test 22export PROD_TEST_DIR := $(TOP_DIR)/product/test 23export PROD_TEST_BUILD_DIR=$(BUILD_DIR)/product/test 24 25# 26# Tools 27# 28export RM := rm -rf 29export MD := mkdir -p 30export CP := cp -r 31export DOC := doxygen 32export CMAKE := cmake 33export CTEST := ctest 34export CD := cd 35export LCOV := lcov 36export GENHTML := genhtml 37export PYTHON := python3 38 39# 40# Documentation paths 41# 42export BUILD_STRING := $(shell $(TOOLS_DIR)/build_string.py 2>/dev/null) 43 44export BUILD_DOC_DIR = $(BUILD_DIR)/doc 45export MODULE_INCLUDES := $(shell ls -d $(MODULES_DIR)/*/include/ 2>/dev/null) 46export MODULE_DOCS := $(shell ls -d $(MODULES_DIR)/*/doc/ 2>/dev/null) 47export MODULE_DOCS += $(shell ls -d $(PRODUCTS_DIR)/*/module/*/doc/ 2>/dev/null) 48 49# 50# Default options 51# 52DEFAULT_MODE := release 53DEFAULT_BUILD_PATH := $(TOP_DIR)/build 54DEFAULT_VERBOSE := n 55DEFAULT_DEBUGGER := n 56DEFAULT_ENABLE_COVERAGE := n 57DEFAULT_TOOLCHAIN := GNU 58DEFAULT_BUILD_SYSTEM := Ninja 59export CMSIS_DIR := $(TOP_DIR)/contrib/cmsis/git/CMSIS/Core 60DEFAULT_LOG_LEVEL_debug := INFO 61DEFAULT_LOG_LEVEL_release := WARN 62DEFAULT_DIRECT_BUILD := n 63 64DEFAULT_CMAKE_TOOL_LOG_LEVEL := NOTICE 65 66# 67# Top-level configuration 68# 69.DEFAULT_GOAL = all 70# MAKECMDGOALS isn't set if there's no explicit goal in the 71# command line, so set the default. 72MAKECMDGOALS ?= $(.DEFAULT_GOAL) 73 74# Mode 75MODE ?= $(DEFAULT_MODE) 76ifneq ($(filter-out debug release, $(MODE)),) 77 $(error "Invalid MODE parameter. Aborting...") 78endif 79 80# Build System 81BUILD_SYSTEM ?= $(DEFAULT_BUILD_SYSTEM) 82ifneq ($(filter-out Make Ninja, $(BUILD_SYSTEM)),) 83 $(error "Invalid BUILD_SYSTEM parameter. Aborting...") 84endif 85 86# Toolchain 87TOOLCHAIN ?= $(DEFAULT_TOOLCHAIN) 88ifneq ($(filter-out GNU ArmClang Clang, $(TOOLCHAIN)),) 89 $(error "Invalid TOOLCHAIN parameter. Aborting...") 90endif 91 92# Log level 93LOG_LEVEL ?= $(DEFAULT_LOG_LEVEL_${MODE}) 94CMAKE_SCP_LOG_LEVEL_OPTION=-DSCP_LOG_LEVEL=$(LOG_LEVEL) 95 96# Build directory 97BUILD_PATH ?= $(DEFAULT_BUILD_PATH) 98ifeq ($(BUILD_PATH),) 99 $(error "Invalid BUILD_PATH parameter. Aborting...") 100endif 101export BUILD_DIR = $(abspath $(BUILD_PATH)) 102 103# Verbose mode: y/n 104export V ?= $(DEFAULT_VERBOSE) 105ifneq ($(V),n) 106 CMAKE_TOOL_LOG_LEVEL := --log-level=VERBOSE 107 CMAKE_BUILD_VERBOSE_OPTION := -v 108else 109 CMAKE_TOOL_LOG_LEVEL := --log-level=$(DEFAULT_CMAKE_TOOL_LOG_LEVEL) 110 MAKEFLAGS += --silent 111 MAKEFLAGS += --no-print-directory 112endif 113 114# Build directly to build directory 115DIRECT_BUILD ?= $(DEFAULT_DIRECT_BUILD) 116export DIRECT_BUILD 117 118# Include debugger library: y/n 119DEBUGGER ?= $(DEFAULT_DEBUGGER) 120ifeq ($(DEBUGGER),y) 121 CMAKE_DEBUGGER_OPTION := -DSCP_ENABLE_DEBUGGER=ON 122endif 123 124ENABLE_COVERAGE ?= $(DEFAULT_ENABLE_COVERAGE) 125 126# 127# Products 128# 129PRODUCTS := $(sort $(shell find product -name "product.mk" -printf "%h\n" | cut -d'/' -f2-3)) 130 131# 132# Deprecated Products/Platforms 133# 134DEPRECATED_PLATFORMS := none 135 136PRODUCT_INDEPENDENT_GOALS := clean help test doc fwk_test mod_test prod_test 137 138ifneq ($(filter-out $(PRODUCT_INDEPENDENT_GOALS), $(MAKECMDGOALS)),) 139 ifeq ($(PRODUCT),) 140 $(error "You must define PRODUCT. Aborting...") 141 endif 142 143 PRODUCT_DIR := $(PRODUCTS_DIR)/$(PRODUCT) 144 145 ifeq ($(wildcard $(PRODUCT_DIR)/product.mk),) 146 $(error "Missing product.mk in $(PRODUCT_DIR)") 147 endif 148 149 include $(PRODUCT_DIR)/product.mk 150 151 ifeq ($(BS_FIRMWARE_LIST),) 152 $(error "You must define BS_FIRMWARE_LIST in product.mk. Aborting...") 153 endif 154 155 # Terminate the build if the chosen platform is in the list of deprecated 156 # ones. 157 ifeq ($(filter-out $(DEPRECATED_PLATFORMS), $(PRODUCT)),) 158 $(error "$(PRODUCT) has been deprecated! Build terminated") 159 endif 160 161 FIRMWARE_TARGETS := $(addprefix firmware-, $(BS_FIRMWARE_LIST)) 162 163ifeq ($(DIRECT_BUILD), n) 164 ifndef PLATFORM_VARIANT 165 PRODUCT_BUILD_DIR := $(BUILD_PATH)/$(BS_PRODUCT_NAME)/$(TOOLCHAIN)/$(MODE) 166 else 167 PRODUCT_BUILD_DIR := $(BUILD_PATH)/$(BS_PRODUCT_NAME)/platform_variant_$(PLATFORM_VARIANT)/$(TOOLCHAIN)/$(MODE) 168 endif 169else 170 PRODUCT_BUILD_DIR := $(BUILD_PATH) 171endif 172 173define msg_start 174================================================================ 175Arm SCP/MCP Software build System 176Platform : $(BS_PRODUCT_NAME) 177Mode : $(MODE) 178Firmware(s) : $(BS_FIRMWARE_LIST) 179================================================================ 180endef 181 182 $(info $(msg_start)) 183endif 184 185ifeq ($(MODE),debug) 186 CMAKE_BUILD_TYPE=-DCMAKE_BUILD_TYPE=Debug 187endif 188 189CMAKE_COMMAND_OPTION := $(CMAKE_BUILD_TYPE) 190CMAKE_COMMAND_OPTION += -DSCP_TOOLCHAIN="$(TOOLCHAIN)" 191CMAKE_COMMAND_OPTION += -DSCP_LLVM_SYSROOT_CC="$(LLVM_SYSROOT_CC)" 192 193ifdef PLATFORM_VARIANT 194 CMAKE_COMMAND_OPTION += -DSCP_PLATFORM_VARIANT="$(PLATFORM_VARIANT)" 195endif 196 197ifdef CMAKE_BUILD_VERBOSE_OPTION 198 CMAKE_COMMAND_OPTION += -DCOMMAND_OUTPUT_VERBOSE=1 199endif 200 201ifeq ($(TEST_ON_TARGET),1) 202 CMAKE_COMMAND_OPTION += -DTEST_ON_TARGET=1 203endif 204 205ifeq ($(BUILD_SYSTEM), Ninja) 206 CMAKE_COMMAND_OPTION += -G $(BUILD_SYSTEM) 207endif 208 209CMAKE_COMMAND_OPTION += $(CMAKE_TOOL_LOG_LEVEL) 210CMAKE_COMMAND_OPTION += $(CMAKE_SCP_LOG_LEVEL_OPTION) 211CMAKE_COMMAND_OPTION += $(CMAKE_DEBUGGER_OPTION) 212 213# 214# Rules 215# 216.PHONY: help 217 218help: 219 @echo "Arm SCP/MCP Software build system" 220 @echo "" 221 @echo "Usage: make -f Makefile.cmake [PRODUCT=<name>] [OPTIONS] [TARGET]" 222 @echo "" 223 @echo "--------------------------------------------------------------------" 224 @echo "| Available Targets |" 225 @echo "--------------------------------------------------------------------" 226 @echo " all Build all firmware defined by PRODUCT=<product>" 227 @echo " clean Remove all built products" 228 @echo " fwk_test Build and runs framework unit tests" 229 @echo " mod_test Build and runs module unit tests" 230 @echo " help Show this documentation" 231 @echo " doc Generate the documentation of this project with Doxygen" 232 @echo "" 233 @echo "--------------------------------------------------------------------" 234 @echo "| Product Selection |" 235 @echo "--------------------------------------------------------------------" 236 @echo " PRODUCT" 237 @echo " Available products: $(PRODUCTS)" 238 @echo " Select the target product to build. This is a required" 239 @echo " parameter." 240 @echo "" 241 @echo "--------------------------------------------------------------------" 242 @echo "| Options |" 243 @echo "--------------------------------------------------------------------" 244 @echo " BUILD_PATH" 245 @echo " Value: <Full, user provided path>" 246 @echo " Default: '$(DEFAULT_BUILD_PATH)'" 247 @echo " Set the base directory used during the build process." 248 @echo "" 249 @echo " MODE" 250 @echo " Value: <debug | release>" 251 @echo " Default: '$(DEFAULT_MODE)'" 252 @echo " Choose between release and debug mode." 253 @echo "" 254 @echo " O" 255 @echo " Value: <Compiler-specific optimization level>" 256 @echo " Default: <Compiler and MODE specific>" 257 @echo " Set the desired level of optimization the compiler will use." 258 @echo "" 259 @echo " V" 260 @echo " Value: <y|n>" 261 @echo " Default: $(DEFAULT_VERBOSE)" 262 @echo " Enable or disable verbose mode for the build system." 263 @echo "" 264 @echo " DEBUGGER" 265 @echo " Value: <y|n>" 266 @echo " Default: $(DEFAULT_DEBUGGER)" 267 @echo " Include the debugger library." 268 @echo "" 269 @echo " LOG_LEVEL" 270 @echo " Value: <DEBUG|INFO|WARN|ERROR|CRIT|DISABLED>" 271 @echo " Default: $(LOG_LEVEL)" 272 @echo " Filter log messages less important than this level." 273 @echo "" 274 @echo " BUILD_SYSTEM" 275 @echo " Value: <Make|Ninja>" 276 @echo " Default: $(DEFAULT_BUILD_SYSTEM)" 277 @echo " Specify CMake to generate GNU Make or Ninja build system." 278 @echo "" 279 @echo " TOOLCHAIN" 280 @echo " Value: <GNU|ArmClang|Clang>" 281 @echo " Default: $(DEFAULT_TOOLCHAIN)" 282 @echo " Specify Toolchain to build the firmware." 283 @echo "" 284 @echo " LLVM_SYSROOT_CC" 285 @echo " Value: <LLVM sysroot compiler path>" 286 @echo " Specify LLVM sysroot compiler path to build the firmware." 287 @echo "" 288 @echo " PLATFORM_VARIANT" 289 @echo " Value: <Platform variant>" 290 @echo " Specify Platform variant if it is required." 291 @echo "" 292 @echo " EXTRA_CONFIG_ARGS" 293 @echo " Value: <cmake configuration parameters>" 294 @echo " Default: " 295 @echo " Pass extra arguments directly to cmake configuration stage." 296 @echo " Multiplle extra args can be added with += or by passing the arguments as a string" 297 @echo "" 298 @echo " EXTRA_BUILD_ARGS" 299 @echo " Value: <cmake build parameters>" 300 @echo " Default: " 301 @echo " Pass extra arguments directly to cmake build stage." 302 @echo " Multiplle extra args can be added with += or by passing the arguments as a string" 303 @echo "" 304 @echo " ENABLE_COVERAGE" 305 @echo " Value: <y|n>" 306 @echo " Default: n" 307 @echo " Enable or disable generation of code coverage reports for unit tests." 308 @echo " Use ENABLE_COVERAGE=y to enable coverage for 'fwk_test' and 'mod_test' targets." 309 @echo "" 310 @echo " DIRECT_BUILD" 311 @echo " Value: <y|n>" 312 @echo " Default: n" 313 @echo " Build directly to the specified build path without modifying it." 314 @echo "" 315 316.SECONDEXPANSION: 317 318.PHONY: all 319all: $(FIRMWARE_TARGETS) 320 321firmware-%: $(PRODUCT_BUILD_DIR)/$$@/CMakeCache.txt 322 $(CMAKE) --build $(<D)/ $(CMAKE_BUILD_VERBOSE_OPTION) $(EXTRA_BUILD_ARGS) 323 324.PRECIOUS: $(PRODUCT_BUILD_DIR)/firmware-%/CMakeCache.txt 325 326$(PRODUCT_BUILD_DIR)/firmware-%/CMakeCache.txt: $(PRODUCT_DIR)/%/Firmware.cmake 327 $(RM) $(@D) 328 $(CMAKE) -B $(@D) -DSCP_FIRMWARE_SOURCE_DIR:PATH=$(PRODUCT_DIR)/$* $(CMAKE_COMMAND_OPTION) $(EXTRA_CONFIG_ARGS) 329 330.PHONY: clean 331clean: 332 $(RM) $(BUILD_DIR) 333 334 335.PHONY: doc 336doc: 337 mkdir -p $(BUILD_DOC_DIR) 338 $(DOC) $(DOC_DIR)/Doxyfile 339 340.PHONY: test 341test : fwk_test mod_test 342 343.PHONY: fwk_test 344fwk_test: 345 $(CMAKE) -B $(FWK_TEST_BUILD_DIR) $(FWK_TEST_DIR) -G Ninja 346 $(CMAKE) --build ${BUILD_PATH}/framework/test 347 # --test-dir option of ctest is not available before ctest 3.20 348 # so use workaround to change the test dir and run the tests from there 349 ${CD} $(FWK_TEST_BUILD_DIR) && ${CTEST} -V --output-junit Testing/TestResults.xml 350ifeq ($(ENABLE_COVERAGE),y) 351 ${CD} $(FWK_TEST_BUILD_DIR) && $(LCOV) --capture --directory . --output-file scp_v2_fwk_test_coverage.info 352 ${CD} $(FWK_TEST_BUILD_DIR) && $(PYTHON) $(TOOLS_DIR)/filter_coverage_report.py --filename scp_v2_fwk_test_coverage.info 353 ${CD} $(FWK_TEST_BUILD_DIR) && $(GENHTML) scp_v2_fwk_test_coverage_filtered.info --prefix "$(TOP_DIR)" --output-directory $(FWK_TEST_BUILD_DIR)/coverage_report 354endif 355 356.PHONY: mod_test 357mod_test: 358 $(CMAKE) -B $(MOD_TEST_BUILD_DIR) $(MOD_TEST_DIR) -G Ninja 359 $(CMAKE) --build $(MOD_TEST_BUILD_DIR) 360 ${CD} $(MOD_TEST_BUILD_DIR) && $(CTEST) -V --output-junit Testing/TestResults.xml 361ifeq ($(ENABLE_COVERAGE),y) 362 ${CD} $(MOD_TEST_BUILD_DIR) && $(LCOV) --capture --directory $(MOD_TEST_BUILD_DIR) --output-file scp_v2_unit_test_coverage.info 363 ${CD} $(MOD_TEST_BUILD_DIR) && $(PYTHON) $(TOOLS_DIR)/filter_coverage_report.py --filename scp_v2_unit_test_coverage.info 364 ${CD} $(MOD_TEST_BUILD_DIR) && $(GENHTML) scp_v2_unit_test_coverage_filtered.info --prefix "$(TOP_DIR)" --output-directory $(MOD_TEST_BUILD_DIR)/coverage_report 365endif 366 367.PHONY: prod_test 368prod_test: 369 $(CMAKE) -B $(PROD_TEST_BUILD_DIR) $(PROD_TEST_DIR) -G Ninja 370 $(CMAKE) --build $(PROD_TEST_BUILD_DIR) 371 ${CD} $(PROD_TEST_BUILD_DIR) && $(CTEST) -V --output-junit Testing/TestResults.xml 372ifeq ($(ENABLE_COVERAGE),y) 373 ${CD} $(PROD_TEST_BUILD_DIR) && $(LCOV) --capture --directory $(PROD_TEST_BUILD_DIR) --output-file scp_v2_product_test_coverage.info 374 ${CD} $(PROD_TEST_BUILD_DIR) && $(PYTHON) $(TOOLS_DIR)/filter_coverage_report.py --filename scp_v2_product_test_coverage.info 375 ${CD} $(PROD_TEST_BUILD_DIR) && $(GENHTML) scp_v2_product_test_coverage_filtered.info --prefix "$(TOP_DIR)" --output-directory $(PROD_TEST_BUILD_DIR)/coverage_report 376endif 377