diff --git a/Makefile.include b/Makefile.include index 18f272c6d621..4acf053677ab 100644 --- a/Makefile.include +++ b/Makefile.include @@ -120,6 +120,9 @@ include $(RIOTMAKE)/info-nproc.inc.mk # List of boards variables include $(RIOTMAKE)/boards.inc.mk +# Debug targets for build system migration +include $(RIOTMAKE)/dependencies_debug.inc.mk + GLOBAL_GOALS += buildtest buildtest-indocker info-boards-supported info-boards-features-missing info-buildsizes info-buildsizes-diff ifneq (, $(filter $(GLOBAL_GOALS), $(MAKECMDGOALS))) BOARD=none diff --git a/dist/tools/buildsystem_sanity_check/save_all_dependencies_resolution_variables.sh b/dist/tools/buildsystem_sanity_check/save_all_dependencies_resolution_variables.sh new file mode 100755 index 000000000000..21a892a78671 --- /dev/null +++ b/dist/tools/buildsystem_sanity_check/save_all_dependencies_resolution_variables.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2019 Freie Universität Berlin +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. +# + +# Script to save all the dependencies resolution variables for both normal and +# in `info-boards-supported` resolution. +# +# The script takes a long time +# +# @author: Gaëtan Harter + +: "${RIOTBASE:="$(cd "$(dirname "$0")/../../../" || exit; pwd)"}" + +usage() { + echo "Usage: $0 " +} + + +applications() { + make --no-print-directory -C "${RIOTBASE}" info-applications +} + + +boards() { + make --no-print-directory -C "${RIOTBASE}" info-boards +} + + +function info_deps_variables_application() { + local application="$1" + local output_dir="$2/${application}" + + DEPENDENCY_DEBUG=1 DEPENDENCY_DEBUG_OUTPUT_DIR="${output_dir}/info-global" make --no-print-directory -C "${RIOTBASE}/${application}" info-boards-supported >/dev/null + for board in $(boards) + do + DEPENDENCY_DEBUG_OUTPUT_DIR="${output_dir}/info" BOARD="${board}" make --no-print-directory -C "${RIOTBASE}/${application}" dependency-debug >/dev/null + done +} + + +main() { + if [[ $# -ne 1 ]]; then + usage + exit 1 + fi + local output_dir + + # No 'realpath' in mac by default… + output_dir=$(python -c 'import os.path; print(os.path.abspath("'"$1"'"))') + + for app in $(applications) + do + echo "Evaluating ${app}" >&2 + info_deps_variables_application "${app}" "${output_dir}" + done + + # Generate the aggregated files to simplify comparing both parsing + find "${output_dir}" -type f -name 'dependencies_info_*' | sort | xargs cat > "${output_dir}"/deps_info + find "${output_dir}" -type f -name 'dependencies_info-boards-supported_*' | sort | xargs cat > ${output_dir}/deps_info-boards-supported +} + + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi diff --git a/doc/doxygen/src/advanced-build-system-tricks.md b/doc/doxygen/src/advanced-build-system-tricks.md index 9c3d13c9e0d0..c7614a8bec43 100644 --- a/doc/doxygen/src/advanced-build-system-tricks.md +++ b/doc/doxygen/src/advanced-build-system-tricks.md @@ -38,3 +38,38 @@ You can configure your own files that will be parsed by the build system main * Specify a hard written `PORT` / `DEBUG_ADAPTER_ID` for some BOARD values * Define your custom targets * Override default targets + + +Analyze dependency resolution {#analyze-depedency-resolution} +============================= + +When refactoring dependency handling or modifying variables used for dependency +resolution, one may want to evaluate the impact on the existing applications. +This describe some debug targets to dump variables used during dependency +resolution. + +To analyze one board and application run the following commands in an +application directory. + +Generate the variables dump with the normal dependency resolution to a +`dependencies_info_board_name` file: + +~~~~~~~~~~~~~~~~~~~ +BOARD=board_name make dependency-debug +~~~~~~~~~~~~~~~~~~~ + +Or with the "quick" version used by murdock to know supported boards +(this is an incomplete resolution, details in `makefiles/dependencies_debug.inc.mk`) +to a `dependencies_info-boards-supported_board_name` file: + +~~~~~~~~~~~~~~~~~~~ +BOARDS=board_name DEPENDENCY_DEBUG=1 make info-boards-supported +~~~~~~~~~~~~~~~~~~~ + +For more configuration and usage details, see in the file defining the targets +`makefiles/dependencies_debug.inc.mk` + +To do a repository wide analysis, you can use the script +`dist/tools/buildsystem_sanity_check/save_all_dependencies_resolution_variables.sh` +that will generate the output for all boards and applications. +It currently take around 2 hours on an 8 cores machine with ssd. diff --git a/makefiles/dependencies_debug.inc.mk b/makefiles/dependencies_debug.inc.mk new file mode 100644 index 000000000000..5926b6135731 --- /dev/null +++ b/makefiles/dependencies_debug.inc.mk @@ -0,0 +1,55 @@ +# Debug targets to evaluate dependency migrations +# +# The goal is to get the value of variables used for dependency resolution +# and the impact of refactoring + +# Files output can be generated through the normal resolution with executing +# 'dependency-debug' for each board +# +# BOARD=board_name make dependency-debug +# +# And the 'quick' version that is used by murdock with `info-boards-supported`. +# This one currently uses only a subset of the files/values required for +# dependency resolution. +# +# DEPENDENCY_DEBUG=1 make info-boards-supported +# +# +# To compare in an aggregated file, you can run in an application directory: +# +# for board in $(make info-boards); do DEPENDENCY_DEBUG_OUTPUT_DIR=bin/info BOARD=${board} make dependency-debug; done; cat bin/info/* > bin/deps_info +# DEPENDENCY_DEBUG=1 DEPENDENCY_DEBUG_OUTPUT_DIR=bin/info-global make info-boards-supported; cat bin/info-global/* > bin/deps_info-boards-supported +# # And compare both files +# diff -u bin/deps_info bin/deps_info-boards-supported +# +# And when comparing two revisions, include the revision in the file names + +.PHONY: dependency-debug +# Only generate the dependencies when the board is not disabled +# This will allow comparing with the output of `info-boards-supported` more easily +dependency-debug: +ifneq (,$(filter-out $(BOARD_BLACKLIST),$(filter $(if $(BOARD_WHITELIST),$(BOARD_WHITELIST), %),$(BOARD)))) + $(call file_save_dependencies_variables,dependencies_info) + @: +else + @echo Skipping $(BOARD) is not whitelisted or blacklisted +endif + +DEPENDENCY_DEBUG_OUTPUT_DIR ?= $(CURDIR) + +# Save variables that are used for parsing dependencies +_DEPS_DEBUG_VARS += BOARD CPU CPU_MODEL CPU_FAM +_DEPS_DEBUG_VARS += FEATURES_PROVIDED _FEATURES_PROVIDED_SORTED FEATURES_REQUIRED _FEATURES_REQUIRED_SORTED FEATURES_OPTIONAL FEATURES_USED FEATURES_MISSING FEATURES_CONFLICT FEATURES_CONFLICTING +_DEPS_DEBUG_VARS += USEMODULE DEFAULT_MODULE DISABLE_MODULE +DEPS_DEBUG_VARS ?= $(_DEPS_DEBUG_VARS) + +_FEATURES_PROVIDED_SORTED = $(sort $(FEATURES_PROVIDED)) +_FEATURES_REQUIRED_SORTED = $(sort $(FEATURES_REQUIRED)) + +file_save_dependencies_variables = $(call file_save_variable,$(DEPENDENCY_DEBUG_OUTPUT_DIR)/$1_$(BOARD),$(DEPS_DEBUG_VARS)) +# Remove file before to be sure appending is started with an empty file +file_save_variable = $(shell mkdir -p $(dir $1); rm -f $1)$(foreach v,$2,$(file >>$1,$(call _print_var,$v))) + +# Remove spaces in case of empty value +# Remove spaces around value as it happens +_print_var = $(strip $1 = $(strip $($1))) diff --git a/makefiles/info-global.inc.mk b/makefiles/info-global.inc.mk index 0160237b15eb..b3a97394a250 100644 --- a/makefiles/info-global.inc.mk +++ b/makefiles/info-global.inc.mk @@ -40,6 +40,10 @@ define board_missing_features BOARDS_FEATURES_MISSING += "$(1) $$(FEATURES_MISSING)" BOARDS_WITH_MISSING_FEATURES += $(1) endif + + ifneq (,$$(DEPENDENCY_DEBUG)) + $$(call file_save_dependencies_variables,dependencies_info-boards-supported) + endif endef BOARDS := $(filter $(if $(BOARD_WHITELIST), $(BOARD_WHITELIST), %), $(BOARDS))