From 9c74027a7bbdc7348441ef2144a8c198c4e13d45 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Mon, 1 Nov 2021 13:22:55 +0100 Subject: [PATCH] cmake: CMake linker script generator pass handling To prepare for linker script creation with flexible number of linker passes depending on system configuration then the Zephyr CMake linker script generator has been updated to use pass names instead of pass numbers. This allows greater flexibility as a section can now be active based on the settings on the pass and not the linking pass index number. As part of this, the `PASS` processing in `linker_script_common.cmake` has been adjusted so that it properly handles when a linking pass is handling multiple settings, such as both `LINKER_APP_SMEM_UNALIGNED` and `DEVICE_HANDLES_PASS1` in same linking pass. As the number of linking passes are more flexible, then the PASS argument in `zephyr_linker_section()` and `zephyr_linker_section_configure()` has been updated to also support a `NOT ` argument, for example: `PASS NOT LINKER_ZEPHYR_FINAL`. Signed-off-by: Torsten Rasmussen --- arch/common/CMakeLists.txt | 6 +-- cmake/extensions.cmake | 49 ++++++++++++++++----- cmake/linker/armlink/target.cmake | 9 ++-- cmake/linker/ld/target.cmake | 8 +--- cmake/linker/linker_script_common.cmake | 20 +++++---- cmake/linker_script/common/common-rom.cmake | 4 +- 6 files changed, 59 insertions(+), 37 deletions(-) diff --git a/arch/common/CMakeLists.txt b/arch/common/CMakeLists.txt index ca0062a317f..aa9ddec353d 100644 --- a/arch/common/CMakeLists.txt +++ b/arch/common/CMakeLists.txt @@ -25,12 +25,12 @@ zephyr_linker_sources_ifdef(CONFIG_GEN_ISR_TABLES ) if(CONFIG_GEN_ISR_TABLES) - zephyr_linker_section(NAME .intList VMA IDT_LIST LMA IDT_LIST NOINPUT PASS 1) + zephyr_linker_section(NAME .intList VMA IDT_LIST LMA IDT_LIST NOINPUT PASS NOT LINKER_ZEPHYR_FINAL) zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".irq_info" FIRST) zephyr_linker_section_configure(SECTION .intList KEEP INPUT ".intList") - zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".irq_info" PASS 2) - zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".intList" PASS 2) + zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".irq_info" PASS LINKER_ZEPHYR_FINAL) + zephyr_linker_section_configure(SECTION /DISCARD/ KEEP INPUT ".intList" PASS LINKER_ZEPHYR_FINAL) endif() zephyr_linker_sources_ifdef(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT diff --git a/cmake/extensions.cmake b/cmake/extensions.cmake index 264884dd9b6..40b8b44fbc4 100644 --- a/cmake/extensions.cmake +++ b/cmake/extensions.cmake @@ -3256,7 +3256,7 @@ endfunction() # [ADDRESS
] [ALIGN ] # [SUBALIGN ] [FLAGS ] # [HIDDEN] [NOINPUT] [NOINIT] -# [PASS [...] +# [PASS [NOT] ] # ) # # Zephyr linker output section. @@ -3311,11 +3311,14 @@ endfunction() # NOINPUT : No default input sections will be defined, to setup input # sections for section , the corresponding # `zephyr_linker_section_configure()` must be used. -# PASS [ ..] : Linker pass iteration where this section should be active. +# PASS [NOT] : Linker pass iteration where this section should be active. # Default a section will be present during all linker passes -# But in cases a section shall only be present at a specific +# but in cases a section shall only be present at a specific # pass, this argument can be used. For example to only have -# this section present on the first linker pass, use `PASS 1`. +# this section present on the `TEST` linker pass, use `PASS TEST`. +# It is possible to negate , such as `PASS NOT `. +# For example, `PASS NOT TEST` means the call is effective +# on all but the `TEST` linker pass iteration. # # Note: VMA and LMA are mutual exclusive with GROUP # @@ -3353,6 +3356,17 @@ function(zephyr_linker_section) endif() endif() + if(DEFINED SECTION_PASS) + list(LENGTH SECTION_PASS pass_length) + if(${pass_length} GREATER 1) + list(GET SECTION_PASS 0 pass_elem_0) + if((NOT (${pass_elem_0} STREQUAL "NOT")) OR (${pass_length} GREATER 2)) + message(FATAL_ERROR "zephyr_linker_section(PASS takes maximum " + "a single argument of the form: '' or 'NOT '.") + endif() + endif() + endif() + set(SECTION) zephyr_linker_arg_val_list(SECTION "${single_args}") zephyr_linker_arg_val_list(SECTION "${options}") @@ -3513,7 +3527,7 @@ endfunction() # Usage: # zephyr_linker_section_configure(SECTION
[ALIGN ] -# [PASS ] [PRIO ] [SORT ] +# [PASS [NOT] ] [PRIO ] [SORT ] # [ANY] [FIRST] [KEEP] # ) # @@ -3542,18 +3556,20 @@ endfunction() # you may use `PRIO 50`, `PRIO 20` and so on. # To ensure an input section is at the end, it is advised # to use `PRIO 200` and above. -# PASS : The call should only be considered for linker pass number . -# For example, `PASS 1` means the call is only effective -# on first linker pass iteration. `PASS 2` on second iteration, -# and so on. +# PASS [NOT] : The call should only be considered for linker pass where +# is defined. It is possible to negate , such +# as `PASS NOT . +# For example, `PASS TEST` means the call is only effective +# on the `TEST` linker pass iteration. `PASS NOT TEST` on +# all iterations the are not `TEST`. # FLAGS : Special section flags such as "+RO", +XO, "+ZI". # ANY : ANY section flag in scatter file. # The FLAGS and ANY arguments only has effect for scatter files. # function(zephyr_linker_section_configure) set(options "ANY;FIRST;KEEP") - set(single_args "ALIGN;OFFSET;PASS;PRIO;SECTION;SORT") - set(multi_args "FLAGS;INPUT;SYMBOLS") + set(single_args "ALIGN;OFFSET;PRIO;SECTION;SORT") + set(multi_args "FLAGS;INPUT;PASS;SYMBOLS") cmake_parse_arguments(SECTION "${options}" "${single_args}" "${multi_args}" ${ARGN}) if(SECTION_UNPARSED_ARGUMENTS) @@ -3568,6 +3584,17 @@ function(zephyr_linker_section_configure) endif() endif() + if(DEFINED SECTION_PASS) + list(LENGTH SECTION_PASS pass_length) + if(${pass_length} GREATER 1) + list(GET SECTION_PASS 0 pass_elem_0) + if((NOT (${pass_elem_0} STREQUAL "NOT")) OR (${pass_length} GREATER 2)) + message(FATAL_ERROR "zephyr_linker_section_configure(PASS takes maximum " + "a single argument of the form: '' or 'NOT '.") + endif() + endif() + endif() + set(SECTION) zephyr_linker_arg_val_list(SECTION "${single_args}") zephyr_linker_arg_val_list(SECTION "${options}") diff --git a/cmake/linker/armlink/target.cmake b/cmake/linker/armlink/target.cmake index 359d3e7454b..d263e424aac 100644 --- a/cmake/linker/armlink/target.cmake +++ b/cmake/linker/armlink/target.cmake @@ -31,10 +31,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) set(STEERING_FILE_ARG) set(STEERING_C_ARG) - if("${linker_pass_define}" STREQUAL "LINKER_ZEPHYR_PREBUILT") - set(PASS 1) - elseif("${linker_pass_define}" STREQUAL "LINKER_ZEPHYR_FINAL") - set(PASS 2) + if("LINKER_ZEPHYR_FINAL" IN_LIST "${linker_pass_define}") set(STEERING_FILE ${CMAKE_CURRENT_BINARY_DIR}/armlink_symbol_steering.steer) set(STEERING_C ${CMAKE_CURRENT_BINARY_DIR}/armlink_symbol_steering.c) set(STEERING_FILE_ARG "-DSTEERING_FILE=${STEERING_FILE}") @@ -46,7 +43,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) ${STEERING_FILE} ${STEERING_C} COMMAND ${CMAKE_COMMAND} - -DPASS=${PASS} + -DPASS="${linker_pass_define}" -DMEMORY_REGIONS="$" -DGROUPS="$" -DSECTIONS="$" @@ -58,7 +55,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) -P ${ZEPHYR_BASE}/cmake/linker/armlink/scatter_script.cmake ) - if("${PASS}" EQUAL 2) + if("LINKER_ZEPHYR_FINAL" IN_LIST "${linker_pass_define}") add_library(armlink_steering OBJECT ${STEERING_C}) target_link_libraries(armlink_steering PRIVATE zephyr_interface) endif() diff --git a/cmake/linker/ld/target.cmake b/cmake/linker/ld/target.cmake index ce2a4388fc1..f29d4e6be78 100644 --- a/cmake/linker/ld/target.cmake +++ b/cmake/linker/ld/target.cmake @@ -32,16 +32,10 @@ macro(configure_linker_script linker_script_gen linker_pass_define) set(extra_dependencies ${ARGN}) if(CONFIG_CMAKE_LINKER_GENERATOR) - if("${linker_pass_define}" STREQUAL "LINKER_ZEPHYR_PREBUILT") - set(PASS 1) - elseif("${linker_pass_define}" STREQUAL "LINKER_ZEPHYR_FINAL") - set(PASS 2) - endif() - add_custom_command( OUTPUT ${linker_script_gen} COMMAND ${CMAKE_COMMAND} - -DPASS=${PASS} + -DPASS="${linker_pass_define}" -DFORMAT="$" -DENTRY="$" -DMEMORY_REGIONS="$" diff --git a/cmake/linker/linker_script_common.cmake b/cmake/linker/linker_script_common.cmake index fef3ad1e144..71811842ba2 100644 --- a/cmake/linker/linker_script_common.cmake +++ b/cmake/linker/linker_script_common.cmake @@ -100,9 +100,11 @@ function(create_section) cmake_parse_arguments(SECTION "" "${single_args}" "${multi_args}" ${ARGN}) - if(DEFINED SECTION_PASS AND NOT "${PASS}" IN_LIST SECTION_PASS) - # This section is not active in this pass, ignore. - return() + if(DEFINED SECTION_PASS) + if(NOT (${SECTION_PASS} IN_LIST PASS)) + # This section is not active in this pass, ignore. + return() + endif() endif() set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME} TRUE) @@ -128,8 +130,8 @@ function(create_section) set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end ${name_clean}) set(INDEX 100) - set(settings_single "ALIGN;ANY;FIRST;KEEP;OFFSET;PASS;PRIO;SECTION;SORT") - set(settings_multi "FLAGS;INPUT;SYMBOLS") + set(settings_single "ALIGN;ANY;FIRST;KEEP;OFFSET;PRIO;SECTION;SORT") + set(settings_multi "FLAGS;INPUT;PASS;SYMBOLS") foreach(settings ${SECTION_SETTINGS}) if("${settings}" MATCHES "^{(.*)}$") cmake_parse_arguments(SETTINGS "" "${settings_single}" "${settings_multi}" ${CMAKE_MATCH_1}) @@ -138,9 +140,11 @@ function(create_section) continue() endif() - if(DEFINED SETTINGS_PASS AND NOT "${PASS}" IN_LIST SETTINGS_PASS) - # This section setting is not active in this pass, ignore. - continue() + if(DEFINED SETTINGS_PASS) + if(NOT (${SETTINGS_PASS} IN_LIST PASS)) + # This section setting is not active in this pass, ignore. + continue() + endif() endif() if(DEFINED SETTINGS_PRIO) diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index 6f873e5d6d0..5d7f36ea86b 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -179,5 +179,5 @@ zephyr_linker_section(NAME zephyr_dbg_info KVMA RAM_REGION GROUP RODATA_REGION N zephyr_linker_section_configure(SECTION zephyr_dbg_info INPUT ".zephyr_dbg_info" KEEP) zephyr_linker_section(NAME device_handles KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT} ENDALIGN 16) -zephyr_linker_section_configure(SECTION device_handles INPUT .__device_handles_pass1* KEEP SORT NAME PASS 1) -zephyr_linker_section_configure(SECTION device_handles INPUT .__device_handles_pass2* KEEP SORT NAME PASS 2) +zephyr_linker_section_configure(SECTION device_handles INPUT .__device_handles_pass1* KEEP SORT NAME PASS LINKER_ZEPHYR_PREBUILT) +zephyr_linker_section_configure(SECTION device_handles INPUT .__device_handles_pass2* KEEP SORT NAME PASS NOT LINKER_ZEPHYR_PREBUILT)