CONFIG_IAR_DATA_INIT did inadvertently not initialize BSS. Signed-off-by: Robin Kastberg <robin.kastberg@iar.com>
958 lines
35 KiB
CMake
958 lines
35 KiB
CMake
# Copyright (c) 2025 IAR Systems AB
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
cmake_minimum_required(VERSION 3.17)
|
|
|
|
set(SORT_TYPE_NAME Lexical)
|
|
|
|
set_property(GLOBAL PROPERTY ILINK_REGION_SYMBOL_ICF)
|
|
|
|
# This function post process the region for easier use.
|
|
#
|
|
# Tasks:
|
|
# - Symbol translation using a steering file is configured.
|
|
function(process_region)
|
|
cmake_parse_arguments(REGION "" "OBJECT" "" ${ARGN})
|
|
|
|
process_region_common(${ARGN})
|
|
|
|
get_property(empty GLOBAL PROPERTY ${REGION_OBJECT}_EMPTY)
|
|
if(NOT empty)
|
|
# For scatter files we move any system symbols into first non-empty load section.
|
|
get_parent(OBJECT ${REGION_OBJECT} PARENT parent TYPE SYSTEM)
|
|
get_property(symbols GLOBAL PROPERTY ${parent}_SYMBOLS)
|
|
set_property(GLOBAL APPEND PROPERTY ${REGION_OBJECT}_SYMBOLS ${symbols})
|
|
set_property(GLOBAL PROPERTY ${parent}_SYMBOLS)
|
|
endif()
|
|
|
|
get_property(sections GLOBAL PROPERTY ${REGION_OBJECT}_SECTION_LIST_ORDERED)
|
|
foreach(section ${sections})
|
|
|
|
get_property(name GLOBAL PROPERTY ${section}_NAME)
|
|
get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
get_property(noinput GLOBAL PROPERTY ${section}_NOINPUT)
|
|
get_property(type GLOBAL PROPERTY ${section}_TYPE)
|
|
get_property(nosymbols GLOBAL PROPERTY ${section}_NOSYMBOLS)
|
|
|
|
if(NOT nosymbols)
|
|
if(${name} STREQUAL .ramfunc)
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_load_start
|
|
EXPR "@ADDR(.ramfunc_init)@"
|
|
)
|
|
else()
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_load_start
|
|
EXPR "@LOADADDR(${name_clean})@"
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
get_property(indicies GLOBAL PROPERTY ${section}_SETTINGS_INDICIES)
|
|
list(LENGTH indicies length)
|
|
foreach(idx ${indicies})
|
|
set(steering_postfixes Base Limit)
|
|
get_property(symbols GLOBAL PROPERTY ${section}_SETTING_${idx}_SYMBOLS)
|
|
get_property(sort GLOBAL PROPERTY ${section}_SETTING_${idx}_SORT)
|
|
get_property(offset GLOBAL PROPERTY ${section}_SETTING_${idx}_OFFSET)
|
|
if(DEFINED offset AND NOT offset EQUAL 0 )
|
|
# Same behavior as in section_to_string
|
|
elseif(DEFINED offset AND offset STREQUAL 0 )
|
|
# Same behavior as in section_to_string
|
|
elseif(sort)
|
|
# Treated by labels in the icf or image symbols.
|
|
elseif(DEFINED symbols AND ${length} EQUAL 1 AND noinput)
|
|
endif()
|
|
endforeach()
|
|
|
|
# Symbols translation here.
|
|
|
|
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end)
|
|
|
|
if("${symbol_val}" STREQUAL "${name_clean}")
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name_clean}_size
|
|
EXPR "@SIZE(${name_clean})@"
|
|
)
|
|
else()
|
|
# These seem to be thing that can't be transformed to $$Length
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_REGION_SYMBOL_ICF
|
|
"define image symbol __${name_clean}_size = (__${symbol_val} - ADDR(${name_clean}))")
|
|
endif()
|
|
set(ZI)
|
|
|
|
if(${name_clean} STREQUAL last_ram_section)
|
|
# A trick to add the symbol for the nxp devices
|
|
# _flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start;
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL _flash_used
|
|
EXPR "(@LOADADDR(last_section)@ + @SIZE(last_section)@ - @__rom_region_start@)"
|
|
)
|
|
endif()
|
|
|
|
if(${name_clean} STREQUAL rom_start)
|
|
# The below two symbols is meant to make aliases to the _vector_table symbol.
|
|
list(GET symbols 0 symbol_start)
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __Vectors
|
|
EXPR "@ADDR(${symbol_start})@"
|
|
)
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __vector_table
|
|
EXPR "@ADDR(${symbol_start})@"
|
|
)
|
|
endif()
|
|
# Treat BSS to be noinit
|
|
if(CONFIG_IAR_ZEPHYR_INIT AND type STREQUAL BSS)
|
|
set_property(GLOBAL PROPERTY ${section}_NOINIT TRUE)
|
|
endif()
|
|
endforeach() # all sections
|
|
|
|
#Add houseeeping symbols for sektion start, end, size, load start.
|
|
get_property(groups GLOBAL PROPERTY ${REGION_OBJECT}_GROUP_LIST_ORDERED)
|
|
foreach(group ${groups})
|
|
get_property(name GLOBAL PROPERTY ${group}_NAME)
|
|
string(TOLOWER ${name} name)
|
|
|
|
get_property(group_type GLOBAL PROPERTY ${group}_OBJ_TYPE)
|
|
get_property(parent GLOBAL PROPERTY ${group}_PARENT)
|
|
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
|
|
# Need to find the init manually group or parent
|
|
if(${parent_type} STREQUAL GROUP)
|
|
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
|
|
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
|
|
else()
|
|
get_property(vma GLOBAL PROPERTY ${group}_VMA)
|
|
get_property(lma GLOBAL PROPERTY ${group}_LMA)
|
|
endif()
|
|
|
|
get_objects(LIST sections OBJECT ${group} TYPE SECTION)
|
|
list(GET sections 0 section)
|
|
get_property(first_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
list(POP_BACK sections section)
|
|
get_property(last_section_name GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
|
|
if(DEFINED vma AND DEFINED lma)
|
|
# Something to init
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_load_start
|
|
EXPR "@ADDR(${first_section_name}_init)@"
|
|
)
|
|
else()
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_load_start
|
|
EXPR "@LOADADDR(${first_section_name})@"
|
|
)
|
|
endif()
|
|
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_start
|
|
EXPR "@ADDR(${first_section_name})@"
|
|
)
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_end
|
|
EXPR "@END(${last_section_name})@"
|
|
)
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_size
|
|
EXPR "(@(__${name}_end)@ - @(__${name}_start)@)"
|
|
)
|
|
|
|
endforeach()
|
|
|
|
# create_symbol() for region-symbols that dont have an expression ?
|
|
get_property(symbols GLOBAL PROPERTY ${REGION_OBJECT}_SYMBOLS)
|
|
foreach(symbol ${symbols})
|
|
get_property(name GLOBAL PROPERTY ${symbol}_NAME)
|
|
get_property(expr GLOBAL PROPERTY ${symbol}_EXPR)
|
|
if(NOT DEFINED expr)
|
|
create_symbol(OBJECT ${REGION_OBJECT} SYMBOL __${name}_size
|
|
EXPR "@(ADDR(${name})@"
|
|
)
|
|
endif()
|
|
endforeach()
|
|
|
|
# This is only a trick to get the memories
|
|
set(groups)
|
|
get_objects(LIST groups OBJECT ${REGION_OBJECT} TYPE GROUP)
|
|
foreach(group ${groups})
|
|
get_property(group_type GLOBAL PROPERTY ${group}_OBJ_TYPE)
|
|
get_property(parent GLOBAL PROPERTY ${group}_PARENT)
|
|
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
|
|
|
|
if(${group_type} STREQUAL GROUP)
|
|
get_property(group_name GLOBAL PROPERTY ${group}_NAME)
|
|
get_property(group_lma GLOBAL PROPERTY ${group}_LMA)
|
|
if(${group_name} STREQUAL ROM_REGION)
|
|
set_property(GLOBAL PROPERTY ILINK_ROM_REGION_NAME ${group_lma})
|
|
endif()
|
|
endif()
|
|
|
|
#Short circuit our vma and lma to the parent's vma and lma
|
|
if(${parent_type} STREQUAL GROUP)
|
|
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
|
|
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
|
|
|
|
set_property(GLOBAL PROPERTY ${group}_VMA ${vma})
|
|
set_property(GLOBAL PROPERTY ${group}_LMA ${lma})
|
|
endif()
|
|
endforeach()
|
|
|
|
endfunction()
|
|
|
|
#
|
|
# String functions - start
|
|
#
|
|
|
|
function(system_to_string)
|
|
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
|
|
|
|
get_property(name GLOBAL PROPERTY ${STRING_OBJECT}_NAME)
|
|
get_property(regions GLOBAL PROPERTY ${STRING_OBJECT}_REGIONS)
|
|
get_property(format GLOBAL PROPERTY ${STRING_OBJECT}_FORMAT)
|
|
|
|
# Ilink specials
|
|
# set(${STRING_STRING} "build for rom;\n")
|
|
set(${STRING_STRING} "build for ram;\n")
|
|
if("${format}" MATCHES "aarch64")
|
|
set(${STRING_STRING} "${${STRING_STRING}}define memory mem with size = 16E;\n")
|
|
else()
|
|
set(${STRING_STRING} "${${STRING_STRING}}define memory mem with size = 4G;\n")
|
|
endif()
|
|
|
|
foreach(region ${regions})
|
|
get_property(name GLOBAL PROPERTY ${region}_NAME)
|
|
get_property(address GLOBAL PROPERTY ${region}_ADDRESS)
|
|
get_property(flags GLOBAL PROPERTY ${region}_FLAGS)
|
|
get_property(size GLOBAL PROPERTY ${region}_SIZE)
|
|
|
|
if(DEFINED flags)
|
|
if(${flags} STREQUAL rx)
|
|
set(flags " rom")
|
|
elseif(${flags} STREQUAL ro)
|
|
set(flags " rom")
|
|
elseif(${flags} STREQUAL wx)
|
|
set(flags " ram")
|
|
elseif(${flags} STREQUAL rw)
|
|
set(flags " ram")
|
|
endif()
|
|
endif()
|
|
|
|
if(${name} STREQUAL IDT_LIST)
|
|
# Need to use a untyped region for IDT_LIST
|
|
set(flags "")
|
|
endif()
|
|
|
|
if(DEFINED address)
|
|
set(start "${address}")
|
|
endif()
|
|
|
|
if(DEFINED size)
|
|
set(size "${size}")
|
|
endif()
|
|
# define rom region FLASH = mem:[from 0x0 size 0x40000];
|
|
set(memory_region "define${flags} region ${name} = mem:[from ${start} size ${size}];")
|
|
|
|
set(${STRING_STRING} "${${STRING_STRING}}${memory_region}\n")
|
|
set(flags)
|
|
endforeach()
|
|
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n\n")
|
|
set_property(GLOBAL PROPERTY ILINK_SYMBOL_ICF)
|
|
|
|
#Generate all regions
|
|
foreach(region ${regions})
|
|
get_property(empty GLOBAL PROPERTY ${region}_EMPTY)
|
|
if(NOT empty)
|
|
get_property(name GLOBAL PROPERTY ${region}_NAME)
|
|
set(ILINK_CURRENT_NAME ${name})
|
|
to_string(OBJECT ${region} STRING ${STRING_STRING})
|
|
set(ILINK_CURRENT_NAME)
|
|
endif()
|
|
endforeach()
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n/*SYSTEM_SECTIONS*/\n")
|
|
|
|
# Sections that sit directly under the system are fishy characters.
|
|
# Currently there are two classes of them:
|
|
# 1 - .rel.iplt & friends - these are not used by iar tools currently.
|
|
# These do not have any parents, so get no placement. Ignore them for
|
|
# now, since the get Error[Lc041]: "foo" defined but not referenced
|
|
# 2 - TYPE LINKER_SCRIPT_FOOTER - these have vma and lma settings, and so
|
|
# are easy to handle
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS)
|
|
foreach(section ${sections})
|
|
get_property(vma GLOBAL PROPERTY ${section}_VMA)
|
|
get_property(lma GLOBAL PROPERTY ${section}_LMA)
|
|
if(DEFINED lma OR DEFINED vma)
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
place_in_region(STRING place OBJECT ${section})
|
|
string(APPEND ${STRING_STRING} "${place}")
|
|
endif()
|
|
endforeach()
|
|
|
|
#Generate all image symbols we have collected
|
|
get_property(symbols_icf GLOBAL PROPERTY ILINK_SYMBOL_ICF)
|
|
foreach(image_symbol ${symbols_icf})
|
|
set(${STRING_STRING} "${${STRING_STRING}}define image symbol ${image_symbol};\n")
|
|
endforeach()
|
|
|
|
get_property(symbols_icf GLOBAL PROPERTY ILINK_REGION_SYMBOL_ICF)
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n")
|
|
foreach(image_symbol ${symbols_icf})
|
|
set(${STRING_STRING} "${${STRING_STRING}}${image_symbol};\n")
|
|
endforeach()
|
|
|
|
if(IAR_LIBC)
|
|
set(${STRING_STRING} "${${STRING_STRING}}if (K_HEAP_MEM_POOL_SIZE>0)\n{\n")
|
|
set(${STRING_STRING} "${${STRING_STRING}} define block HEAP with alignment=8 { symbol kheap__system_heap };\n")
|
|
set(${STRING_STRING} "${${STRING_STRING}}}\nelse\n{\n")
|
|
set(${STRING_STRING} "${${STRING_STRING}} define block HEAP with alignment=8, expanding size { };\n")
|
|
set(${STRING_STRING} "${${STRING_STRING}}}\n")
|
|
set(${STRING_STRING} "${${STRING_STRING}}\"DLib heap\": place in RAM { block HEAP };\n")
|
|
# set(${STRING_STRING} "${${STRING_STRING}}define exported symbol HEAP$$Base=kheap__system_heap;\n")
|
|
# set(${STRING_STRING} "${${STRING_STRING}}define exported symbol HEAP$$Limit=END(kheap__system_heap);\n")
|
|
endif()
|
|
|
|
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
#A helper to output "place in <Region>"
|
|
function(place_in_region)
|
|
cmake_parse_arguments(PLACE "" "OBJECT;STRING" "" ${ARGN})
|
|
set(section ${PLACE_OBJECT})
|
|
get_property(name GLOBAL PROPERTY ${section}_NAME)
|
|
|
|
get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
|
|
get_property(parent GLOBAL PROPERTY ${section}_PARENT)
|
|
get_property(noinit GLOBAL PROPERTY ${section}_NOINIT)
|
|
# This is only a trick to get the memories
|
|
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
|
|
if(${parent_type} STREQUAL GROUP)
|
|
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
|
|
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
|
|
endif()
|
|
|
|
if(DEFINED vma)
|
|
set(ILINK_CURRENT_NAME ${vma})
|
|
elseif(DEFINED lma)
|
|
set(ILINK_CURRENT_NAME ${lma})
|
|
else()
|
|
# message(FATAL_ERROR "Need either vma or lma")
|
|
endif()
|
|
|
|
set(result "\"${name}\": place in ${ILINK_CURRENT_NAME} { block ${name_clean} };\n")
|
|
if(CONFIG_IAR_ZEPHYR_INIT AND DEFINED vma AND DEFINED lma AND (NOT ${noinit}) AND NOT ("${vma}" STREQUAL "${lma}") )
|
|
string(APPEND result "\"${name}_init\": place in ${lma} { block ${name_clean}_init };\n")
|
|
endif()
|
|
set(${PLACE_STRING} "${result}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(group_to_string)
|
|
cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN})
|
|
|
|
get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE)
|
|
if(${type} STREQUAL REGION)
|
|
get_property(empty GLOBAL PROPERTY ${STRING_OBJECT}_EMPTY)
|
|
if(empty)
|
|
return()
|
|
endif()
|
|
endif()
|
|
|
|
#_SECTIONS_FIXED need a place at address statement:
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS_FIXED)
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
get_property(name GLOBAL PROPERTY ${section}_NAME)
|
|
get_property(name_clean GLOBAL PROPERTY ${section}_NAME_CLEAN)
|
|
get_property(section_address GLOBAL PROPERTY ${section}_ADDRESS)
|
|
set(${STRING_STRING} "${${STRING_STRING}}\"${name}\": place at address mem:${section_address} { block ${name_clean} };\n")
|
|
endforeach()
|
|
|
|
#Generate sub-groups
|
|
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_GROUPS)
|
|
foreach(group ${groups})
|
|
to_string(OBJECT ${group} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
#Generate sections
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_SECTIONS)
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
|
|
place_in_region(STRING place OBJECT ${section})
|
|
string(APPEND ${STRING_STRING} "${place}")
|
|
endforeach()
|
|
|
|
get_parent(OBJECT ${STRING_OBJECT} PARENT parent TYPE SYSTEM)
|
|
get_property(regions GLOBAL PROPERTY ${parent}_REGIONS)
|
|
list(REMOVE_ITEM regions ${STRING_OBJECT})
|
|
|
|
#Go over REGIONS
|
|
foreach(region ${regions})
|
|
get_property(vma GLOBAL PROPERTY ${region}_NAME)
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS_FIXED)
|
|
|
|
#Generate our fixed-sections that has vma in this region
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
#generate our groups with vma in region
|
|
get_property(groups GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_GROUPS)
|
|
foreach(group ${groups})
|
|
to_string(OBJECT ${group} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
get_property(sections GLOBAL PROPERTY ${STRING_OBJECT}_${vma}_SECTIONS)
|
|
foreach(section ${sections})
|
|
to_string(OBJECT ${section} STRING ${STRING_STRING})
|
|
get_property(name GLOBAL PROPERTY ${section}_NAME)
|
|
string(REGEX REPLACE "^[\.]" "" name_clean "${name}")
|
|
string(REPLACE "." "_" name_clean "${name_clean}")
|
|
set(${STRING_STRING} "${${STRING_STRING}}\"${name}\": place in ${vma} { block ${name_clean} };\n")
|
|
|
|
# Insert 'do not initialize' here
|
|
get_property(current_sections GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
|
|
if(${name} STREQUAL .bss)
|
|
if(DEFINED current_sections)
|
|
set(${STRING_STRING} "${${STRING_STRING}}do not initialize\n")
|
|
set(${STRING_STRING} "${${STRING_STRING}}{\n")
|
|
foreach(section ${current_sections})
|
|
set(${STRING_STRING} "${${STRING_STRING}} ${section},\n")
|
|
endforeach()
|
|
set(${STRING_STRING} "${${STRING_STRING}}};\n")
|
|
set(current_sections)
|
|
set_property(GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endforeach()
|
|
|
|
get_property(symbols GLOBAL PROPERTY ${STRING_OBJECT}_SYMBOLS)
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n")
|
|
foreach(symbol ${symbols})
|
|
to_string(OBJECT ${symbol} STRING ${STRING_STRING})
|
|
endforeach()
|
|
|
|
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
|
|
function(section_to_string)
|
|
cmake_parse_arguments(STRING "" "SECTION;STRING" "" ${ARGN})
|
|
|
|
get_property(name GLOBAL PROPERTY ${STRING_SECTION}_NAME)
|
|
get_property(address GLOBAL PROPERTY ${STRING_SECTION}_ADDRESS)
|
|
get_property(type GLOBAL PROPERTY ${STRING_SECTION}_TYPE)
|
|
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_ALIGN)
|
|
get_property(subalign GLOBAL PROPERTY ${STRING_SECTION}_SUBALIGN)
|
|
get_property(endalign GLOBAL PROPERTY ${STRING_SECTION}_ENDALIGN)
|
|
get_property(vma GLOBAL PROPERTY ${STRING_SECTION}_VMA)
|
|
get_property(lma GLOBAL PROPERTY ${STRING_SECTION}_LMA)
|
|
get_property(min_size GLOBAL PROPERTY ${STRING_SECTION}_MIN_SIZE)
|
|
get_property(max_size GLOBAL PROPERTY ${STRING_SECTION}_MAX_SIZE)
|
|
get_property(noinput GLOBAL PROPERTY ${STRING_SECTION}_NOINPUT)
|
|
get_property(noinit GLOBAL PROPERTY ${STRING_SECTION}_NOINIT)
|
|
|
|
get_property(nosymbols GLOBAL PROPERTY ${STRING_SECTION}_NOSYMBOLS)
|
|
get_property(start_syms GLOBAL PROPERTY ${STRING_SECTION}_START_SYMBOLS)
|
|
get_property(end_syms GLOBAL PROPERTY ${STRING_SECTION}_END_SYMBOLS)
|
|
|
|
get_property(parent GLOBAL PROPERTY ${STRING_SECTION}_PARENT)
|
|
|
|
get_property(parent_type GLOBAL PROPERTY ${parent}_OBJ_TYPE)
|
|
if(${parent_type} STREQUAL GROUP)
|
|
get_property(group_parent_vma GLOBAL PROPERTY ${parent}_VMA)
|
|
get_property(group_parent_lma GLOBAL PROPERTY ${parent}_LMA)
|
|
if(NOT DEFINED vma)
|
|
get_property(vma GLOBAL PROPERTY ${parent}_VMA)
|
|
endif()
|
|
if(NOT DEFINED lma)
|
|
get_property(lma GLOBAL PROPERTY ${parent}_LMA)
|
|
endif()
|
|
endif()
|
|
|
|
if(DEFINED group_parent_vma AND DEFINED group_parent_lma)
|
|
# Something to init
|
|
set(part "rw ")
|
|
else()
|
|
set(part)
|
|
endif()
|
|
|
|
|
|
set_property(GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
|
|
|
|
string(REGEX REPLACE "^[\.]" "" name_clean "${name}")
|
|
string(REPLACE "." "_" name_clean "${name_clean}")
|
|
|
|
# WA for 'Error[Lc036]: no block or place matches the pattern "ro data section .tdata_init"'
|
|
if("${name_clean}" STREQUAL "tdata")
|
|
set(TEMP "${TEMP}define block ${name_clean}_init { ro section .tdata_init };\n")
|
|
set(TEMP "${TEMP}\"${name_clean}_init\": place in ${ILINK_CURRENT_NAME} { block ${name_clean}_init };\n\n")
|
|
endif()
|
|
|
|
get_property(indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES)
|
|
# ZIP_LISTS partner
|
|
get_property(next_indicies GLOBAL PROPERTY ${STRING_SECTION}_SETTINGS_INDICIES)
|
|
list(POP_FRONT next_indicies first_index)
|
|
|
|
set(first_index_section)
|
|
set(first_index_section_name)
|
|
if(DEFINED first_index)
|
|
# Handle case where the first section has an offset
|
|
get_property(first_index_offset
|
|
GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${first_index}_OFFSET)
|
|
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${first_index}_KEEP)
|
|
if(DEFINED keep)
|
|
set(root "root ")
|
|
else()
|
|
set(root)
|
|
endif()
|
|
if(DEFINED first_index_offset AND NOT first_index_offset EQUAL 0 )
|
|
set(first_index_section_name "${name_clean}_${first_index}_offset")
|
|
set(first_index_section
|
|
"define ${root}section ${first_index_section_name} {};")
|
|
else()
|
|
set(first_index)
|
|
endif()
|
|
endif()
|
|
|
|
foreach(start_symbol ${start_syms})
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${start_symbol} = ADDR(${name_clean})")
|
|
endforeach()
|
|
foreach(end_symbol ${end_syms})
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${end_symbol} = END(${name_clean})")
|
|
endforeach()
|
|
|
|
if(NOT nosymbols)
|
|
if("${name_clean}" STREQUAL "tdata")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_start = (__iar_tls$$INIT_DATA$$Base)")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_end = (__iar_tls$$INIT_DATA$$Limit)")
|
|
else()
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_start = ADDR(${name_clean})")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "__${name_clean}_end = END(${name_clean})")
|
|
endif()
|
|
endif()
|
|
# section patterns and blocks to keep { }
|
|
set(to_be_kept "")
|
|
|
|
if(DEFINED first_index_section)
|
|
set(TEMP "${TEMP}${first_index_section}\n")
|
|
endif()
|
|
|
|
set(TEMP "${TEMP}define block ${name_clean} with fixed order")
|
|
|
|
if(align)
|
|
set(TEMP "${TEMP}, alignment=${align}")
|
|
elseif(subalign)
|
|
set(TEMP "${TEMP}, alignment = ${subalign}")
|
|
elseif(part)
|
|
set(TEMP "${TEMP}, alignment = input")
|
|
else()
|
|
set(TEMP "${TEMP}, alignment=4")
|
|
endif()
|
|
if(endalign)
|
|
set(TEMP "${TEMP}, end alignment=${endalign}")
|
|
endif()
|
|
if(DEFINED min_size)
|
|
set(TEMP "${TEMP}, minimum size=${min_size}")
|
|
endif()
|
|
if(DEFINED max_size)
|
|
set(TEMP "${TEMP}, maximum size=${max_size}")
|
|
endif()
|
|
|
|
set(TEMP "${TEMP}\n{")
|
|
|
|
# foreach(start_symbol ${start_syms})
|
|
# set(TEMP "${TEMP}\n section ${start_symbol},")
|
|
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${start_symbol}")
|
|
# endforeach()
|
|
|
|
# if(NOT nosymbols)
|
|
# set(TEMP "${TEMP}\n section __${name_clean}_start,")
|
|
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section __${name_clean}_start")
|
|
# endif()
|
|
|
|
list(GET indicies -1 last_index)
|
|
list(LENGTH indicies length)
|
|
|
|
if(NOT noinput)
|
|
|
|
set(TEMP "${TEMP}\n block ${name_clean}_winput")
|
|
if(align)
|
|
list(APPEND block_attr "alignment = ${align}")
|
|
elseif(subalign)
|
|
list(APPEND block_attr "alignment = ${subalign}")
|
|
elseif(part)
|
|
# list(APPEND block_attr "alignment = input")
|
|
else()
|
|
list(APPEND block_attr "alignment=4")
|
|
endif()
|
|
list(APPEND block_attr "fixed order")
|
|
|
|
list(JOIN block_attr ", " block_attr_str)
|
|
if(block_attr_str)
|
|
set(TEMP "${TEMP} with ${block_attr_str}")
|
|
endif()
|
|
set(block_attr)
|
|
set(block_attr_str)
|
|
|
|
set(TEMP "${TEMP} { ${part}section ${name}, ${part}section ${name}.* }")
|
|
if(${length} GREATER 0)
|
|
set(TEMP "${TEMP},")
|
|
endif()
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${name}")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${name}.*")
|
|
endif()
|
|
|
|
foreach(idx idx_next IN ZIP_LISTS indicies next_indicies)
|
|
get_property(align GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ALIGN)
|
|
get_property(any GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_ANY)
|
|
get_property(first GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FIRST)
|
|
get_property(keep GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_KEEP)
|
|
get_property(sort GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SORT)
|
|
get_property(flags GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_FLAGS)
|
|
get_property(input GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_INPUT)
|
|
get_property(symbols GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_SYMBOLS)
|
|
get_property(i_min_size GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_MIN_SIZE)
|
|
get_property(i_max_size GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx}_MAX_SIZE)
|
|
|
|
# Get the next offset and use that as this ones size!
|
|
get_property(offset GLOBAL PROPERTY ${STRING_SECTION}_SETTING_${idx_next}_OFFSET)
|
|
|
|
if(keep)
|
|
list(APPEND to_be_kept "block ${name_clean}_${idx}")
|
|
foreach(setting ${input})
|
|
list(APPEND to_be_kept "section ${setting}")
|
|
endforeach()
|
|
endif()
|
|
# In ilink if a block with min_size=X does not match any input sections,
|
|
# its _init block may be discarded despite being needed for spacing with
|
|
# other _init blocks. To get around tihs, lets tag min_size blocks as keep.
|
|
if(CONFIG_IAR_ZEPHYR_INIT
|
|
AND DEFINED group_parent_vma AND DEFINED group_parent_lma
|
|
AND DEFINED i_min_size
|
|
AND NOT ${noinit})
|
|
list(APPEND to_be_kept "block ${name_clean}_${idx}_init")
|
|
endif()
|
|
if(DEFINED symbols)
|
|
list(LENGTH symbols symbols_count)
|
|
if(${symbols_count} GREATER 0)
|
|
list(GET symbols 0 symbol_start)
|
|
endif()
|
|
if(${symbols_count} GREATER 1)
|
|
list(GET symbols 1 symbol_end)
|
|
endif()
|
|
endif()
|
|
|
|
if(DEFINED symbol_start)
|
|
# set(TEMP "${TEMP}\n section ${symbol_start},")
|
|
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${symbol_start}")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${symbol_start} = ADDR(${name_clean}_${idx})")
|
|
endif()
|
|
|
|
if(DEFINED first_index AND first_index EQUAL ${idx})
|
|
# Create the offset
|
|
set(TEMP "${TEMP}\n block ${first_index_section_name}")
|
|
list(APPEND block_attr "size = ${first_index_offset}")
|
|
if(sort)
|
|
if(${sort} STREQUAL NAME)
|
|
list(APPEND block_attr "alphabetical order")
|
|
endif()
|
|
endif()
|
|
if(align)
|
|
list(APPEND block_attr "alignment = ${align}")
|
|
elseif(subalign)
|
|
list(APPEND block_attr "alignment = ${subalign}")
|
|
elseif(part)
|
|
# list(APPEND block_attr "alignment = input")
|
|
else()
|
|
list(APPEND block_attr "alignment=4")
|
|
endif()
|
|
list(APPEND block_attr "fixed order")
|
|
|
|
list(JOIN block_attr ", " block_attr_str)
|
|
if(block_attr_str)
|
|
set(TEMP "${TEMP} with ${block_attr_str}")
|
|
endif()
|
|
set(block_attr)
|
|
set(block_attr_str)
|
|
|
|
set(TEMP "${TEMP} { section ${first_index_section_name} },\n")
|
|
endif()
|
|
|
|
# block init_100 with alphabetical order { section .z_init_EARLY_?_}
|
|
set(TEMP "${TEMP}\n block ${name_clean}_${idx}")
|
|
if(DEFINED offset AND NOT offset EQUAL 0 )
|
|
list(APPEND block_attr "size = ${offset}")
|
|
elseif(DEFINED offset AND offset STREQUAL 0 )
|
|
# Do nothing
|
|
endif()
|
|
if(sort)
|
|
if(${sort} STREQUAL NAME)
|
|
list(APPEND block_attr "alphabetical order")
|
|
endif()
|
|
endif()
|
|
if(align)
|
|
list(APPEND block_attr "alignment = ${align}")
|
|
elseif(subalign)
|
|
list(APPEND block_attr "alignment = ${subalign}")
|
|
elseif(part)
|
|
# list(APPEND block_attr "alignment = input")
|
|
else()
|
|
list(APPEND block_attr "alignment=4")
|
|
endif()
|
|
if(DEFINED i_min_size AND NOT i_min_size EQUAL 0)
|
|
list(APPEND block_attr "minimum size = ${i_min_size}")
|
|
endif()
|
|
if(DEFINED i_max_size )
|
|
list(APPEND block_attr "maximum size = ${i_max_size}")
|
|
endif()
|
|
|
|
# LD
|
|
# There are two ways to include more than one section:
|
|
#
|
|
# *(.text .rdata)
|
|
# *(.text) *(.rdata)
|
|
#
|
|
# The difference between these is the order in which
|
|
# the `.text' and `.rdata' input sections will appear in the output section.
|
|
# In the first example, they will be intermingled,
|
|
# appearing in the same order as they are found in the linker input.
|
|
# In the second example, all `.text' input sections will appear first,
|
|
# followed by all `.rdata' input sections.
|
|
#
|
|
# ILINK solved by adding 'fixed order'
|
|
if(NOT sort AND NOT first)
|
|
list(APPEND block_attr "fixed order")
|
|
endif()
|
|
|
|
list(JOIN block_attr ", " block_attr_str)
|
|
if(block_attr_str)
|
|
set(TEMP "${TEMP} with ${block_attr_str}")
|
|
endif()
|
|
set(block_attr)
|
|
set(block_attr_str)
|
|
|
|
list(GET input -1 last_input)
|
|
|
|
set(TEMP "${TEMP} {")
|
|
if(NOT DEFINED input AND NOT any)
|
|
set(TEMP "${TEMP} }")
|
|
endif()
|
|
|
|
foreach(setting ${input})
|
|
if(first)
|
|
set(TEMP "${TEMP} first")
|
|
set(first "")
|
|
endif()
|
|
|
|
set(section_type "")
|
|
|
|
set(TEMP "${TEMP}${section_type} ${part}section ${setting}")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${setting}")
|
|
set(section_type "")
|
|
|
|
if("${setting}" STREQUAL "${last_input}")
|
|
set(TEMP "${TEMP} }")
|
|
else()
|
|
set(TEMP "${TEMP}, ")
|
|
endif()
|
|
|
|
# set(TEMP "${TEMP}\n *.o(${setting})")
|
|
endforeach()
|
|
|
|
if(any)
|
|
if(NOT flags)
|
|
message(FATAL_ERROR ".ANY requires flags to be set.")
|
|
endif()
|
|
set(ANY_FLAG "")
|
|
foreach(flag ${flags})
|
|
# if("${flag}" STREQUAL +RO OR "${flag}" STREQUAL +XO)
|
|
# set(ANY_FLAG "readonly")
|
|
# # elseif("${flag}" STREQUAL +RW)
|
|
# # set(ANY_FLAG "readwrite")
|
|
# else
|
|
if("${flag}" STREQUAL +ZI)
|
|
set(ANY_FLAG "zeroinit")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "${ANY_FLAG}")
|
|
endif()
|
|
endforeach()
|
|
set(TEMP "${TEMP} ${ANY_FLAG} }")
|
|
endif()
|
|
|
|
if(DEFINED symbol_end)
|
|
# set(TEMP "${TEMP},\n section ${symbol_end}")
|
|
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${symbol_end}")
|
|
set_property(GLOBAL APPEND PROPERTY ILINK_SYMBOL_ICF "${symbol_end} = END(${name_clean}_${idx})")
|
|
endif()
|
|
if(${length} GREATER 0)
|
|
if(NOT "${idx}" STREQUAL "${last_index}")
|
|
set(TEMP "${TEMP},")
|
|
elseif()
|
|
endif()
|
|
endif()
|
|
|
|
set(symbol_start)
|
|
set(symbol_end)
|
|
endforeach()
|
|
set(next_indicies)
|
|
|
|
set(last_index)
|
|
set(last_input)
|
|
set(TEMP "${TEMP}")
|
|
|
|
# if(NOT nosymbols)
|
|
# set(TEMP "${TEMP},\n section __${name_clean}_end")
|
|
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section __${name_clean}_end")
|
|
# endif()
|
|
|
|
# foreach(end_symbol ${end_syms})
|
|
# set(TEMP "${TEMP},\n section ${end_symbol}")
|
|
# set_property(GLOBAL APPEND PROPERTY ILINK_CURRENT_SECTIONS "section ${end_symbol}")
|
|
# endforeach()
|
|
|
|
set(TEMP "${TEMP}\n};")
|
|
|
|
get_property(current_sections GLOBAL PROPERTY ILINK_CURRENT_SECTIONS)
|
|
if(${noinit})
|
|
list(JOIN current_sections ", " SELECTORS)
|
|
set(TEMP "${TEMP}\ndo not initialize {\n${SELECTORS}\n};")
|
|
elseif(DEFINED group_parent_vma AND DEFINED group_parent_lma)
|
|
if(CONFIG_IAR_DATA_INIT AND DEFINED current_sections)
|
|
set(TEMP "${TEMP}\ninitialize by copy\n")
|
|
set(TEMP "${TEMP}{\n")
|
|
foreach(section ${current_sections})
|
|
set(TEMP "${TEMP} ${section},\n")
|
|
endforeach()
|
|
set(TEMP "${TEMP}};")
|
|
|
|
set(TEMP "${TEMP}\n\"${name}_init\": place in ${group_parent_lma} {\n")
|
|
foreach(section ${current_sections})
|
|
set(TEMP "${TEMP} ${section}_init,\n")
|
|
endforeach()
|
|
set(TEMP "${TEMP}};")
|
|
elseif(CONFIG_IAR_ZEPHYR_INIT)
|
|
# Generate the _init block and the initialize manually statement.
|
|
# Note that we need to have the X_init block defined even if we have
|
|
# no sections, since there will come a "place in XXX" statement later.
|
|
|
|
# "${TEMP}" is there too keep the ';' else it will be a list
|
|
string(REGEX REPLACE "(block[ \t\r\n]+)([^ \t\r\n]+)" "\\1\\2_init" INIT_TEMP "${TEMP}")
|
|
string(REGEX REPLACE "(rw)([ \t\r\n]+)(section[ \t\r\n]+)([^ \t\r\n,]+)" "\\1\\2\\3\\4_init" INIT_TEMP "${INIT_TEMP}")
|
|
string(REGEX REPLACE "(rw)([ \t\r\n]+)(section[ \t\r\n]+)" "ro\\2\\3" INIT_TEMP "${INIT_TEMP}")
|
|
|
|
# No alphabetical orders on initializers
|
|
# Only alphabetical attribute.
|
|
string(REGEX REPLACE "with alphabetical order {" " {" INIT_TEMP "${INIT_TEMP}")
|
|
# Respect other attributes.
|
|
string(REGEX REPLACE "(, alphabetical order|alphabetical order, )" "" INIT_TEMP "${INIT_TEMP}")
|
|
string(REGEX REPLACE "{ readwrite }" "{ }" INIT_TEMP "${INIT_TEMP}")
|
|
set(TEMP "${TEMP}\n${INIT_TEMP}\n")
|
|
|
|
# If any content is marked as keep, is has to be applied to the init block
|
|
# too, esp. for blocks that are not referenced (e.g. empty blocks with min_size)
|
|
if(to_be_kept)
|
|
list(APPEND to_be_kept "block ${name_clean}_init")
|
|
endif()
|
|
|
|
if(DEFINED current_sections)
|
|
set(TEMP "${TEMP}\ninitialize manually with copy friendly\n")
|
|
set(TEMP "${TEMP}{\n")
|
|
foreach(section ${current_sections})
|
|
set(TEMP "${TEMP} ${section},\n")
|
|
endforeach()
|
|
set(TEMP "${TEMP}};")
|
|
endif()
|
|
endif()
|
|
set(current_sections)
|
|
endif()
|
|
|
|
# Finally, add the keeps.
|
|
if(to_be_kept)
|
|
list(JOIN to_be_kept ", " K)
|
|
set(TEMP "${TEMP}\nkeep { ${K} };\n")
|
|
endif()
|
|
|
|
set(${STRING_STRING} "${${STRING_STRING}}\n${TEMP}\n" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(symbol_to_string)
|
|
cmake_parse_arguments(STRING "" "SYMBOL;STRING" "" ${ARGN})
|
|
|
|
get_property(name GLOBAL PROPERTY ${STRING_SYMBOL}_NAME)
|
|
get_property(expr GLOBAL PROPERTY ${STRING_SYMBOL}_EXPR)
|
|
get_property(size GLOBAL PROPERTY ${STRING_SYMBOL}_SIZE)
|
|
get_property(symbol GLOBAL PROPERTY ${STRING_SYMBOL}_SYMBOL)
|
|
get_property(subalign GLOBAL PROPERTY ${STRING_SYMBOL}_SUBALIGN)
|
|
|
|
string(REPLACE "\\" "" expr "${expr}")
|
|
string(REGEX MATCHALL "@([^@]*)@" match_res ${expr})
|
|
|
|
foreach(match ${match_res})
|
|
string(REPLACE "@" "" match ${match})
|
|
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE_${match})
|
|
string(REPLACE "@${match}@" "${match}" expr ${expr})
|
|
endforeach()
|
|
|
|
list(LENGTH match_res match_res_count)
|
|
|
|
if(match_res_count)
|
|
if(${match_res_count} GREATER 1)
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
|
|
)
|
|
else()
|
|
if((expr MATCHES "Base|Limit|Length") OR (expr MATCHES "ADDR\\(|END\\(|SIZE\\("))
|
|
# Anything like $$Base/$$Limit/$$Length should be an image symbol
|
|
if( "${symbol}" STREQUAL "__tdata_size")
|
|
# This will handle the alignment of the TBSS block
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}define image symbol ${symbol}=(__iar_tls$$INIT_DATA$$Limit-__iar_tls$$INIT_DATA$$Base);\n"
|
|
)
|
|
elseif( "${symbol}" STREQUAL "__tbss_size")
|
|
# This will handle the alignment of the TBSS block by
|
|
# pre-padding bytes
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}define image symbol ${symbol}=((tbss$$Limit-__iar_tls$$DATA$$Base)-(__iar_tls$$INIT_DATA$$Limit-__iar_tls$$INIT_DATA$$Base));\n"
|
|
)
|
|
else()
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
|
|
)
|
|
endif()
|
|
else()
|
|
list(GET match_res 0 match)
|
|
string(REPLACE "@" "" match ${match})
|
|
get_property(symbol_val GLOBAL PROPERTY SYMBOL_TABLE_${match})
|
|
if(symbol_val)
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
|
|
)
|
|
else()
|
|
# Treatmen of "zephyr_linker_symbol(SYMBOL z_arm_platform_init EXPR "@SystemInit@")"
|
|
set_property(GLOBAL APPEND PROPERTY SYMBOL_STEERING_FILE
|
|
"--redirect ${symbol}=${expr}\n"
|
|
)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
else()
|
|
# Handle things like ADDR(.ramfunc)
|
|
if(${expr} MATCHES "^[A-Za-z]?ADDR\\(.+\\)")
|
|
# string(REGEX REPLACE "^[A-Za-z]?ADDR\\((.+)\\)" "(\\1$$Base)" expr ${expr})
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}define image symbol ${symbol} = ${expr};\n"
|
|
)
|
|
else()
|
|
set(${STRING_STRING}
|
|
"${${STRING_STRING}}define exported symbol ${symbol} = ${expr};\n"
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../linker_script_common.cmake)
|
|
|
|
if(DEFINED STEERING_FILE)
|
|
get_property(steering_content GLOBAL PROPERTY SYMBOL_STEERING_FILE)
|
|
file(WRITE ${STEERING_FILE} "/* AUTO-GENERATED - Do not modify\n")
|
|
file(APPEND ${STEERING_FILE} " * AUTO-GENERATED - All changes will be lost\n")
|
|
file(APPEND ${STEERING_FILE} " */\n")
|
|
|
|
file(APPEND ${STEERING_FILE} ${steering_content})
|
|
endif()
|