From 0b3c65feea10295ebbd067f69e6d4aa4c0a2fc85 Mon Sep 17 00:00:00 2001 From: Mark Ruvald Pedersen Date: Wed, 30 Jan 2019 10:12:30 +0100 Subject: [PATCH] cmake: Toolchain abstraction: optimizations Introduce toolchain_cc_optimize_for_* family of macros. Each macro represents a general optimization class. Each macro is then responsible for setting an output variable to that class-of-optimization's flag. The names of these output variables are decided from the root CMakeLists.txt. No functional change expected. Clang's optimization flags are compatible with gcc, and are thus inherited. This is motivated by the wish to abstract Zephyr's usage of toolchains, permitting easier porting to other (commercial) toolchains. Signed-off-by: Mark Ruvald Pedersen --- CMakeLists.txt | 35 +++++++++++-------- cmake/compiler/clang/target.cmake | 1 + cmake/compiler/gcc/target.cmake | 1 + cmake/compiler/gcc/target_optimizations.cmake | 25 +++++++++++++ cmake/compiler/host-gcc/target.cmake | 1 + 5 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 cmake/compiler/gcc/target_optimizations.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cf8b9e5ba5..cbd4a132d12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,21 +99,26 @@ if(BUILD_VERSION) ) endif() -# We need to set an optimization level. -# Default to -Os -# unless CONFIG_NO_OPTIMIZATIONS is set, then it is -O0 -# or unless CONFIG_DEBUG is set, then it is -Og +# @Intent: Obtain compiler optimizations flags and store in variables +# @details: +# Kconfig.zephyr "Optimization level" is a kconfig choice, ensuring +# only *one* of CONFIG_{NO,DEBUG,SPEED,SIZE}_OPTIMIZATIONS is set. +# Refer to Kconfig.zephyr for selection logic and description of these choices. +# toolchain_cc_optimize_*() macros must provide the mapping from these kconfigs +# to compiler flags. Each macro will store the flags in a CMake variable, whose +# name is passed as argument (somewhat like by reference). # -# also, some toolchain's break with -Os, and some toolchain's break -# with -Og so allow them to override what flag to use +# If the user wants to tweak the optimizations, there are two ways: +# 1) Using EXTRA_CFLAGS which is applied regardless of kconfig choice, or +# 2) Rely on override support being implemented by your toolchain_cc_optimize_*() # -# Finally, the user can use Kconfig to add compiler options that will -# come after these options and override them -set_ifndef(OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG "-O0") -set_ifndef(OPTIMIZE_FOR_DEBUG_FLAG "-Og") -set_ifndef(OPTIMIZE_FOR_SIZE_FLAG "-Os") -set_ifndef(OPTIMIZE_FOR_SPEED_FLAG "-O2") +toolchain_cc_optimize_for_no_optimizations_flag(OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG) +toolchain_cc_optimize_for_debug_flag(OPTIMIZE_FOR_DEBUG_FLAG) +toolchain_cc_optimize_for_speed_flag(OPTIMIZE_FOR_SPEED_FLAG) +toolchain_cc_optimize_for_size_flag(OPTIMIZE_FOR_SIZE_FLAG) +# From kconfig choice, pick the actual OPTIMIZATION_FLAG to use. +# Kconfig choice ensures only one of these CONFIG_*_OPTIMIZATIONS is set. if(CONFIG_NO_OPTIMIZATIONS) set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG}) elseif(CONFIG_DEBUG_OPTIMIZATIONS) @@ -121,11 +126,14 @@ elseif(CONFIG_DEBUG_OPTIMIZATIONS) elseif(CONFIG_SPEED_OPTIMIZATIONS) set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SPEED_FLAG}) elseif(CONFIG_SIZE_OPTIMIZATIONS) - set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SIZE_FLAG}) # Default + set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SIZE_FLAG}) # Default in kconfig else() assert(0 "Unreachable code. Expected optimization level to have been chosen. See Kconfig.zephyr") endif() +# Apply the final optimization flag(s) +zephyr_compile_options(${OPTIMIZATION_FLAG}) + # Dialects of C++, corresponding to the multiple published ISO standards. # Which standard it implements can be selected using the -std= command-line option. set_ifndef(DIALECT_STD_CPP98 "c++98") @@ -149,7 +157,6 @@ else() endif() zephyr_compile_options( - ${OPTIMIZATION_FLAG} # Usually -Os -g # TODO: build configuration enough? -Wall -Wformat diff --git a/cmake/compiler/clang/target.cmake b/cmake/compiler/clang/target.cmake index f12abf22f42..9ae784e8eec 100644 --- a/cmake/compiler/clang/target.cmake +++ b/cmake/compiler/clang/target.cmake @@ -56,3 +56,4 @@ string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") # Clang and GCC are almost feature+flag compatible, so reuse freestanding gcc include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_security_fortify.cmake) include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_security_canaries.cmake) +include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_optimizations.cmake) diff --git a/cmake/compiler/gcc/target.cmake b/cmake/compiler/gcc/target.cmake index f23c4f6f00a..33ba21c4bcd 100644 --- a/cmake/compiler/gcc/target.cmake +++ b/cmake/compiler/gcc/target.cmake @@ -141,3 +141,4 @@ string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") # Load toolchain_cc-family macros include(${ZEPHYR_BASE}/cmake/compiler/${COMPILER}/target_security_fortify.cmake) include(${ZEPHYR_BASE}/cmake/compiler/${COMPILER}/target_security_canaries.cmake) +include(${ZEPHYR_BASE}/cmake/compiler/${COMPILER}/target_optimizations.cmake) diff --git a/cmake/compiler/gcc/target_optimizations.cmake b/cmake/compiler/gcc/target_optimizations.cmake new file mode 100644 index 00000000000..583bb13d17b --- /dev/null +++ b/cmake/compiler/gcc/target_optimizations.cmake @@ -0,0 +1,25 @@ +# See root CMakeLists.txt for description and expectations of this macro +# +# NOTE: Some GNU toolchains break with plain '-Os' or '-Og', but is fixable +# with tweaks. So allow user to override, via ifndef, the compile flags that +# CONFIG_{NO,DEBUG,SPEED,SIZE}_OPTIMIZATIONS will cause, yet still leaving the +# selection logic in kconfig. +# +# These macros leaves it up to the root CMakeLists.txt to choose the CMake +# variable names to store the optimization flags in. + +macro(toolchain_cc_optimize_for_no_optimizations_flag dest_var_name) + set_ifndef(${dest_var_name} "-O0") +endmacro() + +macro(toolchain_cc_optimize_for_debug_flag dest_var_name) + set_ifndef(${dest_var_name} "-Og") +endmacro() + +macro(toolchain_cc_optimize_for_speed_flag dest_var_name) + set_ifndef(${dest_var_name} "-O2") +endmacro() + +macro(toolchain_cc_optimize_for_size_flag dest_var_name) + set_ifndef(${dest_var_name} "-Os") +endmacro() diff --git a/cmake/compiler/host-gcc/target.cmake b/cmake/compiler/host-gcc/target.cmake index 3a071c50a89..4165b4e1f85 100644 --- a/cmake/compiler/host-gcc/target.cmake +++ b/cmake/compiler/host-gcc/target.cmake @@ -61,3 +61,4 @@ endif() # Significant overlap with freestanding gcc compiler so reuse it include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_security_fortify.cmake) include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_security_canaries.cmake) +include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_optimizations.cmake)