cmake: ld: adding common linker script generator

Adding intial version of linker_script_common.cmake.

This script parses memory regions, groups, sections, settings, and
symbols defined in the Zephyr CMake build system.

The linker script creates objects for each type above and groups
sections, symbols, and groups together based on their configuration.

This creates a hierarchy which the `<linker>_script.cmake`
implementations can then use during linker script generation.

linker_script_common.cmake also provides stubs for <type>_to_string()
functions which are used when generating the output script.

Each specific `<linker>_script.cmake` must implement those to_string()
functions to create the final linker script.

Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit is contained in:
Torsten Rasmussen 2021-08-09 10:41:20 +02:00 committed by Anas Nashif
commit 02fb26dd44

View file

@ -0,0 +1,672 @@
#
# Create functions - start
#
function(create_system)
cmake_parse_arguments(OBJECT "" "ENTRY;FORMAT;NAME;OBJECT" "" ${ARGN})
set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME} TRUE)
set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_OBJ_TYPE SYSTEM)
set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_NAME ${OBJECT_NAME})
set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_FORMAT ${OBJECT_FORMAT})
set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_ENTRY ${OBJECT_ENTRY})
set(${OBJECT_OBJECT} SYSTEM_${OBJECT_NAME} PARENT_SCOPE)
endfunction()
function(create_region)
cmake_parse_arguments(OBJECT "" "NAME;OBJECT;SIZE;START;FLAGS" "" ${ARGN})
if(DEFINED OBJECT_SIZE)
if(${OBJECT_SIZE} MATCHES "^([0-9]*)[kK]$")
math(EXPR OBJECT_SIZE "1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL)
elseif(${OBJECT_SIZE} MATCHES "^([0-9]*)[mM]$")
math(EXPR OBJECT_SIZE "1024 * 1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL)
elseif(NOT (${OBJECT_SIZE} MATCHES "^([0-9]*)$" OR ${OBJECT_SIZE} MATCHES "^0x([0-9a-fA-F]*)$"))
message(FATAL_ERROR "SIZE format is unknown.")
endif()
endif()
set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME} TRUE)
set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_OBJ_TYPE REGION)
set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_NAME ${OBJECT_NAME})
set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_ADDRESS ${OBJECT_START})
set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_FLAGS ${OBJECT_FLAGS})
set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_SIZE ${OBJECT_SIZE})
set(${OBJECT_OBJECT} REGION_${OBJECT_NAME} PARENT_SCOPE)
endfunction()
function(get_parent)
cmake_parse_arguments(GET_PARENT "" "OBJECT;PARENT;TYPE" "" ${ARGN})
get_property(type GLOBAL PROPERTY ${GET_PARENT_OBJECT}_OBJ_TYPE)
if(${type} STREQUAL ${GET_PARENT_TYPE})
# Already the right type, so just set and return.
set(${GET_PARENT_PARENT} ${GET_PARENT_OBJECT} PARENT_SCOPE)
return()
endif()
get_property(parent GLOBAL PROPERTY ${GET_PARENT_OBJECT}_PARENT)
get_property(type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
while(NOT ${type} STREQUAL ${GET_PARENT_TYPE})
get_property(parent GLOBAL PROPERTY ${parent}_PARENT)
get_property(type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
endwhile()
set(${GET_PARENT_PARENT} ${parent} PARENT_SCOPE)
endfunction()
function(create_group)
cmake_parse_arguments(OBJECT "" "GROUP;LMA;NAME;OBJECT;VMA" "" ${ARGN})
set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME} TRUE)
set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_OBJ_TYPE GROUP)
set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_NAME ${OBJECT_NAME})
if(DEFINED OBJECT_GROUP)
find_object(OBJECT parent NAME ${OBJECT_GROUP})
else()
if(DEFINED OBJECT_VMA)
find_object(OBJECT obj NAME ${OBJECT_VMA})
get_parent(OBJECT ${obj} PARENT parent TYPE REGION)
get_property(vma GLOBAL PROPERTY ${parent}_NAME)
set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_VMA ${vma})
endif()
if(DEFINED OBJECT_LMA)
find_object(OBJECT obj NAME ${OBJECT_LMA})
get_parent(OBJECT ${obj} PARENT parent TYPE REGION)
get_property(lma GLOBAL PROPERTY ${parent}_NAME)
set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_LMA ${lma})
endif()
endif()
get_property(GROUP_FLAGS_INHERITED GLOBAL PROPERTY ${parent}_FLAGS)
set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_FLAGS ${GROUP_FLAGS_INHERITED})
set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_PARENT ${parent})
add_group(OBJECT ${parent} GROUP GROUP_${OBJECT_NAME})
set(${OBJECT_OBJECT} GROUP_${OBJECT_NAME} PARENT_SCOPE)
endfunction()
function(create_section)
set(single_args "NAME;ADDRESS;ALIGN_WITH_INPUT;TYPE;ALIGN;ENDALIGN;SUBALIGN;VMA;LMA;NOINPUT;NOINIT;NOSYMBOLS;GROUP;SYSTEM")
set(multi_args "PASS")
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()
endif()
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME} TRUE)
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_OBJ_TYPE SECTION)
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME ${SECTION_NAME})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ADDRESS ${SECTION_ADDRESS})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_TYPE ${SECTION_TYPE})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN ${SECTION_ALIGN})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN_WITH_INPUT ${SECTION_ALIGN_WITH_INPUT})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SUBALIGN ${SECTION_SUBALIGN})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ENDALIGN ${SECTION_ENDALIGN})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINPUT ${SECTION_NOINPUT})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINIT ${SECTION_NOINIT})
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOSYMBOLS ${SECTION_NOSYMBOLS})
string(REGEX REPLACE "^[\.]" "" name_clean "${SECTION_NAME}")
string(REPLACE "." "_" name_clean "${name_clean}")
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME_CLEAN ${name_clean})
set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_start ${name_clean})
set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_size ${name_clean})
set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_load_start ${name_clean})
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")
foreach(settings ${SECTION_SETTINGS})
if("${settings}" MATCHES "^{(.*)}$")
cmake_parse_arguments(SETTINGS "" "${settings_single}" "${settings_multi}" ${CMAKE_MATCH_1})
if(NOT ("${SETTINGS_SECTION}" STREQUAL "${SECTION_NAME}"))
continue()
endif()
if(DEFINED SETTINGS_PASS AND NOT "${PASS}" IN_LIST SETTINGS_PASS)
# This section setting is not active in this pass, ignore.
continue()
endif()
if(DEFINED SETTINGS_PRIO)
set(idx ${SETTINGS_PRIO})
else()
set(idx ${INDEX})
math(EXPR INDEX "${INDEX} + 1")
endif()
foreach(setting ${settings_single} ${settings_multi})
set_property(GLOBAL PROPERTY
SECTION_${SECTION_NAME}_SETTING_${idx}_${setting}
${SETTINGS_${setting}}
)
if(DEFINED SETTINGS_SORT)
set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end ${name_clean}_end)
endif()
endforeach()
set_property(GLOBAL APPEND PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${idx})
endif()
endforeach()
get_property(indicies GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES)
if(DEFINED indicies)
list(SORT indicies COMPARE NATURAL)
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${indicies})
endif()
if(DEFINED SECTION_GROUP)
find_object(OBJECT parent NAME ${SECTION_GROUP})
elseif(DEFINED SECTION_VMA OR DEFINED SECTION_LMA)
if(DEFINED SECTION_VMA)
find_object(OBJECT object NAME ${SECTION_VMA})
get_parent(OBJECT ${object} PARENT parent TYPE REGION)
get_property(vma GLOBAL PROPERTY ${parent}_NAME)
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_VMA ${vma})
set(SECTION_VMA ${vma})
endif()
if(DEFINED SECTION_LMA)
find_object(OBJECT object NAME ${SECTION_LMA})
get_parent(OBJECT ${object} PARENT parent TYPE REGION)
get_property(lma GLOBAL PROPERTY ${parent}_NAME)
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_LMA ${lma})
set(SECTION_LMA ${lma})
endif()
else()
set(parent ${SECTION_SYSTEM})
endif()
set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_PARENT ${parent})
add_section(OBJECT ${parent} SECTION ${SECTION_NAME} ADDRESS ${SECTION_ADDRESS} VMA ${SECTION_VMA})
endfunction()
function(create_symbol)
cmake_parse_arguments(SYM "" "OBJECT;EXPR;SIZE;SUBALIGN;SYMBOL" "" ${ARGN})
set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL} TRUE)
set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_OBJ_TYPE SYMBOL)
set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_NAME ${SYM_SYMBOL})
set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_EXPR ${SYM_EXPR})
set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SIZE ${SYM_SIZE})
set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SYMBOL ${SYM_SYMBOL})
set_property(GLOBAL PROPERTY SYMBOL_TABLE_${SYM_SYMBOL} ${SYM_SYMBOL})
add_symbol(OBJECT ${SYM_OBJECT} SYMBOL SYMBOL_${SYM_SYMBOL})
endfunction()
#
# Create functions - end
#
#
# Add functions - start
#
function(add_region)
cmake_parse_arguments(ADD_REGION "" "OBJECT;REGION" "" ${ARGN})
get_property(exists GLOBAL PROPERTY ${ADD_REGION_OBJECT})
if(NOT exists)
message(FATAL_ERROR
"Adding region ${ADD_REGION_REGION} to none-existing object: "
"${ADD_REGION_OBJECT}"
)
endif()
set_property(GLOBAL PROPERTY ${ADD_REGION_REGION}_PARENT ${ADD_REGION_OBJECT})
set_property(GLOBAL APPEND PROPERTY ${ADD_REGION_OBJECT}_REGIONS ${ADD_REGION_REGION})
endfunction()
function(add_group)
cmake_parse_arguments(ADD_GROUP "" "OBJECT;GROUP" "" ${ARGN})
get_property(exists GLOBAL PROPERTY ${ADD_GROUP_OBJECT})
if(NOT exists)
message(FATAL_ERROR
"Adding group ${ADD_GROUP_GROUP} to none-existing object: "
"${ADD_GROUP_OBJECT}"
)
endif()
get_property(vma GLOBAL PROPERTY ${ADD_GROUP_GROUP}_VMA)
get_property(object_name GLOBAL PROPERTY ${ADD_GROUP_OBJECT}_NAME)
if((NOT DEFINED vma) OR ("${vma}" STREQUAL ${object_name}))
set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_GROUPS ${ADD_GROUP_GROUP})
else()
set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_${vma}_GROUPS ${ADD_GROUP_GROUP})
endif()
endfunction()
function(add_section)
cmake_parse_arguments(ADD_SECTION "" "OBJECT;SECTION;ADDRESS;VMA" "" ${ARGN})
if(DEFINED ADD_SECTION_OBJECT)
get_property(type GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_OBJ_TYPE)
get_property(object_name GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_NAME)
if(NOT DEFINED type)
message(FATAL_ERROR
"Adding section ${ADD_SECTION_SECTION} to "
"none-existing object: ${ADD_SECTION_OBJECT}"
)
endif()
else()
set(ADD_SECTION_OBJECT RELOCATEABLE)
endif()
if("${ADD_SECTION_VMA}" STREQUAL "${object_name}" AND DEFINED ADD_SECTION_ADDRESS)
set_property(GLOBAL APPEND PROPERTY
${ADD_SECTION_OBJECT}_SECTIONS_FIXED
SECTION_${ADD_SECTION_SECTION}
)
elseif(NOT DEFINED ADD_SECTION_VMA AND DEFINED SECTION_ADDRESS)
set_property(GLOBAL APPEND PROPERTY
${ADD_SECTION_OBJECT}_SECTIONS_FIXED
SECTION_${ADD_SECTION_SECTION}
)
elseif("${ADD_SECTION_VMA}" STREQUAL "${object_name}")
set_property(GLOBAL APPEND PROPERTY
${ADD_SECTION_OBJECT}_SECTIONS
SECTION_${ADD_SECTION_SECTION}
)
elseif(NOT DEFINED ADD_SECTION_VMA)
set_property(GLOBAL APPEND PROPERTY
${ADD_SECTION_OBJECT}_SECTIONS
SECTION_${ADD_SECTION_SECTION}
)
elseif(DEFINED SECTION_ADDRESS)
set_property(GLOBAL APPEND PROPERTY
${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS_FIXED
SECTION_${ADD_SECTION_SECTION}
)
else()
set_property(GLOBAL APPEND PROPERTY
${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS
SECTION_${ADD_SECTION_SECTION}
)
endif()
endfunction()
function(add_symbol)
cmake_parse_arguments(ADD_SYMBOL "" "OBJECT;SYMBOL" "" ${ARGN})
# Section can be fixed address or not, VMA == LMA, .
#
get_property(exists GLOBAL PROPERTY ${ADD_SYMBOL_OBJECT})
if(NOT exists)
message(FATAL_ERROR
"Adding symbol ${ADD_SYMBOL_SYMBOL} to none-existing object: "
"${ADD_SYMBOL_OBJECT}"
)
endif()
set_property(GLOBAL APPEND PROPERTY ${ADD_SYMBOL_OBJECT}_SYMBOLS ${ADD_SYMBOL_SYMBOL})
endfunction()
#
# Add functions - end
#
#
# Retrieval functions - start
#
function(find_object)
cmake_parse_arguments(FIND "" "OBJECT;NAME" "" ${ARGN})
get_property(REGION GLOBAL PROPERTY REGION_${FIND_NAME})
get_property(GROUP GLOBAL PROPERTY GROUP_${FIND_NAME})
get_property(SECTION GLOBAL PROPERTY SECTION_${FIND_NAME})
if(REGION)
set(${FIND_OBJECT} REGION_${FIND_NAME} PARENT_SCOPE)
elseif(GROUP)
set(${FIND_OBJECT} GROUP_${FIND_NAME} PARENT_SCOPE)
elseif(SECTION)
set(${FIND_OBJECT} SECTION_${FIND_NAME} PARENT_SCOPE)
else()
message(WARNING "No object with name ${FIND_NAME} could be found.")
endif()
endfunction()
function(get_objects)
cmake_parse_arguments(GET "" "LIST;OBJECT;TYPE" "" ${ARGN})
get_property(type GLOBAL PROPERTY ${GET_OBJECT}_OBJ_TYPE)
if(${type} STREQUAL SECTION)
# A section doesn't have sub-items.
return()
endif()
if(NOT (${GET_TYPE} STREQUAL SECTION
OR ${GET_TYPE} STREQUAL GROUP)
)
message(WARNING "Only retrieval of SECTION GROUP objects are supported.")
return()
endif()
set(out)
get_parent(OBJECT ${GET_OBJECT} PARENT parent TYPE SYSTEM)
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
list(REMOVE_ITEM regions ${GET_OBJECT})
if(${GET_TYPE} STREQUAL SECTION)
get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS_FIXED)
list(APPEND out ${sections})
get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS)
foreach(group ${groups})
get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE})
list(APPEND out ${sections})
endforeach()
get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS)
list(APPEND out ${sections})
foreach(region ${regions})
get_property(vma GLOBAL PROPERTY ${region}_NAME)
get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS_FIXED)
list(APPEND out ${sections})
get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS)
foreach(group ${groups})
get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE})
list(APPEND out ${sections})
endforeach()
get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS)
list(APPEND out ${sections})
endforeach()
endif()
if(${GET_TYPE} STREQUAL GROUP)
get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS)
list(APPEND out ${groups})
foreach(group ${groups})
get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE})
list(APPEND out ${subgroups})
endforeach()
foreach(region ${regions})
get_property(vma GLOBAL PROPERTY ${region}_NAME)
get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS)
list(APPEND out ${groups})
foreach(group ${groups})
get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE})
list(APPEND out ${subgroups})
endforeach()
endforeach()
endif()
set(${GET_LIST} ${out} PARENT_SCOPE)
endfunction()
#
# Retrieval functions - end
#
function(is_empty)
cmake_parse_arguments(IS_EMPTY "" "OBJECT" "" ${ARGN})
get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS_FIXED)
if(DEFINED sections)
set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
return()
endif()
get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_GROUPS)
if(DEFINED groups)
set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
return()
endif()
get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS)
if(DEFINED sections)
set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
return()
endif()
get_parent(OBJECT ${IS_EMPTY_OBJECT} PARENT parent TYPE SYSTEM)
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
list(REMOVE_ITEM regions ${IS_EMPTY_OBJECT})
foreach(region ${regions})
get_property(vma GLOBAL PROPERTY ${region}_NAME)
get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS_FIXED)
if(DEFINED sections)
set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
return()
endif()
get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_GROUPS)
if(DEFINED groups)
set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
return()
endif()
get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS)
if(DEFINED sections)
set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE)
return()
endif()
endforeach()
set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY TRUE)
endfunction()
# This function post process the region for easier use.
#
# This is common post processing.
# If the calling <linker>_script.cmake generator implements its own
# process_region(), then the process_region_common() must be called explicitly
# from the process_region() from the <linker>_script.cmake generator.
#
# This allows a custom <linker>_script.cmake generator to completely disable
# the common post processing of regions.
#
# Tasks:
# - Apply missing settings, such as initial address for first section in a region.
# - Symbol names on sections
# - Ordered list of all sections for easier retrival on printing and configuration.
function(process_region_common)
cmake_parse_arguments(REGION_COMMON "" "OBJECT" "" ${ARGN})
is_empty(OBJECT ${REGION_COMMON_OBJECT})
set(sections)
get_objects(LIST sections OBJECT ${REGION_COMMON_OBJECT} TYPE SECTION)
set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_SECTION_LIST_ORDERED ${sections})
set(groups)
get_objects(LIST groups OBJECT ${REGION_COMMON_OBJECT} TYPE GROUP)
set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_GROUP_LIST_ORDERED ${groups})
list(LENGTH sections section_count)
if(section_count GREATER 0)
list(GET sections 0 section)
get_property(address GLOBAL PROPERTY ${section}_ADDRESS)
if(NOT DEFINED address)
get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE REGION)
get_property(address GLOBAL PROPERTY ${parent}_ADDRESS)
set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address})
endif()
endif()
get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE SYSTEM)
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
list(REMOVE_ITEM regions ${REGION_COMMON_OBJECT})
foreach(region ${regions})
get_property(vma GLOBAL PROPERTY ${region}_NAME)
set(sections_${vma})
get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS_FIXED)
list(APPEND sections_${vma} ${sections})
get_property(groups GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_GROUPS)
foreach(group ${groups})
get_objects(LIST sections OBJECT ${group} TYPE SECTION)
list(APPEND sections_${vma} ${sections})
endforeach()
get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS)
list(APPEND sections_${vma} ${sections})
list(LENGTH sections_${vma} section_count)
if(section_count GREATER 0)
list(GET sections_${vma} 0 section)
get_property(address GLOBAL PROPERTY ${section}_ADDRESS)
if(NOT DEFINED address)
get_property(address GLOBAL PROPERTY ${region}_ADDRESS)
set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address})
endif()
endif()
endforeach()
endfunction()
if(NOT COMMAND process_region)
function(process_region)
process_region_common(${ARGN})
endfunction()
endif()
#
# String functions - start
#
# Each linker must implement their own <type>_to_string() functions to
# generate a correct linker script.
#
if(NOT COMMAND system_to_string)
function(system_to_string)
message(WARNING "No linker defined function found. Please implement a "
"system_to_string() function for this linker."
)
endfunction()
endif()
if(NOT COMMAND group_to_string)
function(group_to_string)
message(WARNING "No linker defined function found. Please implement a "
"group_to_string() function for this linker."
)
endfunction()
endif()
if(NOT COMMAND section_to_string)
function(section_to_string)
message(WARNING "No linker defined function found. Please implement a "
"section_to_string() function for this linker."
)
endfunction()
endif()
if(NOT COMMAND symbol_to_string)
function(symbol_to_string)
message(WARNING "No linker defined function found. Please implement a "
"symbol_to_string() function for this linker."
)
endfunction()
endif()
function(to_string)
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE)
if("${type}" STREQUAL SYSTEM)
system_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING})
elseif(("${type}" STREQUAL REGION) OR ("${type}" STREQUAL GROUP))
group_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING})
elseif("${type}" STREQUAL SECTION)
section_to_string(SECTION ${STRING_OBJECT} STRING ${STRING_STRING})
elseif("${type}" STREQUAL SYMBOL)
symbol_to_string(SYMBOL ${STRING_OBJECT} STRING ${STRING_STRING})
endif()
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
endfunction()
#
# String functions - end
#
create_system(OBJECT new_system NAME ZEPHYR_LINKER_v1 FORMAT ${FORMAT} ENTRY ${ENTRY})
# Sorting the memory sections in ascending order.
foreach(region ${MEMORY_REGIONS})
if("${region}" MATCHES "^{(.*)}$")
cmake_parse_arguments(REGION "" "NAME;START" "" ${CMAKE_MATCH_1})
math(EXPR start_dec "${REGION_START}" OUTPUT_FORMAT DECIMAL)
set(region_id ${start_dec}_${REGION_NAME})
set(region_${region_id} ${region})
string(REPLACE ";" "\;" region_${region_id} "${region_${region_id}}")
list(APPEND region_sort ${region_id})
endif()
endforeach()
list(SORT region_sort COMPARE NATURAL)
set(MEMORY_REGIONS_SORTED)
foreach(region_start ${region_sort})
list(APPEND MEMORY_REGIONS_SORTED "${region_${region_start}}")
endforeach()
# sorting complete.
foreach(region ${MEMORY_REGIONS_SORTED})
if("${region}" MATCHES "^{(.*)}$")
create_region(OBJECT new_region ${CMAKE_MATCH_1})
add_region(OBJECT ${new_system} REGION ${new_region})
endif()
endforeach()
foreach(group ${GROUPS})
if("${group}" MATCHES "^{(.*)}$")
create_group(OBJECT new_group ${CMAKE_MATCH_1})
endif()
endforeach()
foreach(section ${SECTIONS})
if("${section}" MATCHES "^{(.*)}$")
create_section(${CMAKE_MATCH_1} SYSTEM ${new_system})
endif()
endforeach()
foreach(symbol ${SYMBOLS})
if("${symbol}" MATCHES "^{(.*)}$")
create_symbol(OBJECT ${new_system} ${CMAKE_MATCH_1})
endif()
endforeach()
get_property(regions GLOBAL PROPERTY ${new_system}_REGIONS)
foreach(region ${regions})
process_region(OBJECT ${region})
endforeach()
set(OUT)
to_string(OBJECT ${new_system} STRING OUT)
if(OUT_FILE)
file(WRITE ${OUT_FILE} "${OUT}")
endif()