1find_package(Zephyr REQUIRED COMPONENTS extensions HINTS ${CMAKE_CURRENT_LIST_DIR}/../../) 2 3# 4# Create functions - start 5# 6function(create_system) 7 cmake_parse_arguments(OBJECT "" "ENTRY;FORMAT;NAME;OBJECT" "" ${ARGN}) 8 9 set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME} TRUE) 10 set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_OBJ_TYPE SYSTEM) 11 set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_NAME ${OBJECT_NAME}) 12 set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_FORMAT ${OBJECT_FORMAT}) 13 set_property(GLOBAL PROPERTY SYSTEM_${OBJECT_NAME}_ENTRY ${OBJECT_ENTRY}) 14 15 set(${OBJECT_OBJECT} SYSTEM_${OBJECT_NAME} PARENT_SCOPE) 16endfunction() 17 18function(create_region) 19 cmake_parse_arguments(OBJECT "" "NAME;OBJECT;SIZE;START;FLAGS" "" ${ARGN}) 20 21 if(DEFINED OBJECT_SIZE) 22 if(${OBJECT_SIZE} MATCHES "^([0-9]*)[kK]$") 23 math(EXPR OBJECT_SIZE "1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL) 24 elseif(${OBJECT_SIZE} MATCHES "^([0-9]*)[mM]$") 25 math(EXPR OBJECT_SIZE "1024 * 1024 * ${CMAKE_MATCH_1}" OUTPUT_FORMAT HEXADECIMAL) 26 elseif(NOT (${OBJECT_SIZE} MATCHES "^([0-9]*)$" OR ${OBJECT_SIZE} MATCHES "^0x([0-9a-fA-F]*)$")) 27 message(FATAL_ERROR "SIZE format is unknown.") 28 endif() 29 endif() 30 31 set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME} TRUE) 32 set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_OBJ_TYPE REGION) 33 set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_NAME ${OBJECT_NAME}) 34 set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_ADDRESS ${OBJECT_START}) 35 set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_FLAGS ${OBJECT_FLAGS}) 36 set_property(GLOBAL PROPERTY REGION_${OBJECT_NAME}_SIZE ${OBJECT_SIZE}) 37 38 set(${OBJECT_OBJECT} REGION_${OBJECT_NAME} PARENT_SCOPE) 39endfunction() 40 41function(get_parent) 42 cmake_parse_arguments(GET_PARENT "" "OBJECT;PARENT;TYPE" "" ${ARGN}) 43 44 get_property(type GLOBAL PROPERTY ${GET_PARENT_OBJECT}_OBJ_TYPE) 45 if(${type} STREQUAL ${GET_PARENT_TYPE}) 46 # Already the right type, so just set and return. 47 set(${GET_PARENT_PARENT} ${GET_PARENT_OBJECT} PARENT_SCOPE) 48 return() 49 endif() 50 51 # Follow parent pointers until a GET_PARENT_TYPE is reached 52 get_property(parent GLOBAL PROPERTY ${GET_PARENT_OBJECT}_PARENT) 53 get_property(type GLOBAL PROPERTY ${parent}_OBJ_TYPE) 54 while(NOT ${type} STREQUAL ${GET_PARENT_TYPE}) 55 get_property(parent GLOBAL PROPERTY ${parent}_PARENT) 56 get_property(type GLOBAL PROPERTY ${parent}_OBJ_TYPE) 57 endwhile() 58 59 set(${GET_PARENT_PARENT} ${parent} PARENT_SCOPE) 60endfunction() 61 62function(create_group) 63 cmake_parse_arguments(OBJECT "" "GROUP;LMA;NAME;OBJECT;SYMBOL;VMA" "" ${ARGN}) 64 65 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME} TRUE) 66 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_OBJ_TYPE GROUP) 67 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_NAME ${OBJECT_NAME}) 68 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_SYMBOL ${OBJECT_SYMBOL}) 69 70 if(DEFINED OBJECT_GROUP) 71 find_object(OBJECT parent NAME ${OBJECT_GROUP}) 72 else() 73 if(DEFINED OBJECT_VMA) 74 find_object(OBJECT obj NAME ${OBJECT_VMA}) 75 get_parent(OBJECT ${obj} PARENT parent TYPE REGION) 76 77 get_property(vma GLOBAL PROPERTY ${parent}_NAME) 78 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_VMA ${vma}) 79 endif() 80 81 if(DEFINED OBJECT_LMA) 82 find_object(OBJECT obj NAME ${OBJECT_LMA}) 83 get_parent(OBJECT ${obj} PARENT parent TYPE REGION) 84 85 get_property(lma GLOBAL PROPERTY ${parent}_NAME) 86 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_LMA ${lma}) 87 endif() 88 endif() 89 90 get_property(GROUP_FLAGS_INHERITED GLOBAL PROPERTY ${parent}_FLAGS) 91 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_FLAGS ${GROUP_FLAGS_INHERITED}) 92 set_property(GLOBAL PROPERTY GROUP_${OBJECT_NAME}_PARENT ${parent}) 93 94 add_group(OBJECT ${parent} GROUP GROUP_${OBJECT_NAME}) 95 96 set(${OBJECT_OBJECT} GROUP_${OBJECT_NAME} PARENT_SCOPE) 97endfunction() 98 99function(is_active_in_pass ret_ptr current_pass pass_rules) 100 # by validation in zephyr_linker_* we know that if there is a NOT, 101 # it is the first, and the other entries are pass names 102 if(NOT pass_rules) 103 set(result 1) 104 elseif("NOT" IN_LIST pass_rules) 105 set(result 1) 106 if(current_pass IN_LIST pass_rules) 107 set(result 0) 108 endif() 109 else() 110 set(result 0) 111 if(current_pass IN_LIST pass_rules) 112 set(result 1) 113 endif() 114 endif() 115 set(${ret_ptr} ${result} PARENT_SCOPE) 116endfunction() 117 118function(create_section) 119 set(single_args "NAME;ADDRESS;ALIGN_WITH_INPUT;TYPE;ALIGN;ENDALIGN;SUBALIGN;VMA;LMA;NOINPUT;NOINIT;NOSYMBOLS;GROUP;SYSTEM;MIN_SIZE;MAX_SIZE") 120 set(multi_args "PASS") 121 122 cmake_parse_arguments(SECTION "" "${single_args}" "${multi_args}" ${ARGN}) 123 124 if(DEFINED SECTION_PASS) 125 is_active_in_pass(active ${PASS} "${SECTION_PASS}") 126 if(NOT active) 127 return() 128 endif() 129 endif() 130 131 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME} TRUE) 132 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_OBJ_TYPE SECTION) 133 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME ${SECTION_NAME}) 134 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ADDRESS ${SECTION_ADDRESS}) 135 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_TYPE ${SECTION_TYPE}) 136 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN ${SECTION_ALIGN}) 137 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ALIGN_WITH_INPUT ${SECTION_ALIGN_WITH_INPUT}) 138 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SUBALIGN ${SECTION_SUBALIGN}) 139 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_ENDALIGN ${SECTION_ENDALIGN}) 140 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINPUT ${SECTION_NOINPUT}) 141 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOINIT ${SECTION_NOINIT}) 142 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NOSYMBOLS ${SECTION_NOSYMBOLS}) 143 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_MIN_SIZE ${SECTION_MIN_SIZE}) 144 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_MAX_SIZE ${SECTION_MAX_SIZE}) 145 146 string(REGEX REPLACE "^[\.]" "" name_clean "${SECTION_NAME}") 147 string(REPLACE "." "_" name_clean "${name_clean}") 148 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_NAME_CLEAN ${name_clean}) 149 150 set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_start ${name_clean}) 151 set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_size ${name_clean}) 152 set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_load_start ${name_clean}) 153 set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end ${name_clean}) 154 155 set(INDEX 100) 156 set(settings_single "ALIGN;ANY;FIRST;KEEP;OFFSET;PRIO;SECTION;SORT;MIN_SIZE;MAX_SIZE") 157 set(settings_multi "FLAGS;INPUT;PASS;SYMBOLS") 158 foreach(settings ${SECTION_SETTINGS} ${DEVICE_API_SECTION_SETTINGS}) 159 if("${settings}" MATCHES "^{(.*)}$") 160 cmake_parse_arguments(SETTINGS "" "${settings_single}" "${settings_multi}" ${CMAKE_MATCH_1}) 161 162 if(NOT ("${SETTINGS_SECTION}" STREQUAL "${SECTION_NAME}")) 163 continue() 164 endif() 165 166 if(DEFINED SETTINGS_PASS) 167 is_active_in_pass(active ${PASS} "${SETTINGS_PASS}") 168 if(NOT active) 169 continue() 170 endif() 171 endif() 172 173 if(DEFINED SETTINGS_PRIO) 174 set(idx ${SETTINGS_PRIO}) 175 else() 176 set(idx ${INDEX}) 177 math(EXPR INDEX "${INDEX} + 1") 178 endif() 179 180 foreach(setting ${settings_single} ${settings_multi}) 181 set_property(GLOBAL PROPERTY 182 SECTION_${SECTION_NAME}_SETTING_${idx}_${setting} 183 ${SETTINGS_${setting}} 184 ) 185 if(DEFINED SETTINGS_SORT) 186 set_property(GLOBAL PROPERTY SYMBOL_TABLE___${name_clean}_end ${name_clean}_end) 187 endif() 188 endforeach() 189 190 set_property(GLOBAL APPEND PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${idx}) 191 192 endif() 193 endforeach() 194 195 get_property(indicies GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES) 196 if(DEFINED indicies) 197 list(SORT indicies COMPARE NATURAL) 198 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_SETTINGS_INDICIES ${indicies}) 199 endif() 200 201 if(DEFINED SECTION_GROUP) 202 find_object(OBJECT parent NAME ${SECTION_GROUP}) 203 elseif(DEFINED SECTION_VMA OR DEFINED SECTION_LMA) 204 if(DEFINED SECTION_VMA) 205 find_object(OBJECT object NAME ${SECTION_VMA}) 206 get_parent(OBJECT ${object} PARENT parent TYPE REGION) 207 208 get_property(vma GLOBAL PROPERTY ${parent}_NAME) 209 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_VMA ${vma}) 210 set(SECTION_VMA ${vma}) 211 endif() 212 213 if(DEFINED SECTION_LMA) 214 find_object(OBJECT object NAME ${SECTION_LMA}) 215 get_parent(OBJECT ${object} PARENT parent TYPE REGION) 216 217 get_property(lma GLOBAL PROPERTY ${parent}_NAME) 218 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_LMA ${lma}) 219 set(SECTION_LMA ${lma}) 220 endif() 221 else() 222 set(parent ${SECTION_SYSTEM}) 223 endif() 224 if(SECTION_TYPE STREQUAL "LINKER_SCRIPT_FOOTER") 225 set(SECTION_VMA) # pretend that we have no VMA, so the section ends up in 226 # the general heap of sections directly below the system 227 set(parent ${SECTION_SYSTEM}) 228 endif() 229 230 set_property(GLOBAL PROPERTY SECTION_${SECTION_NAME}_PARENT ${parent}) 231 add_section(OBJECT ${parent} SECTION ${SECTION_NAME} ADDRESS ${SECTION_ADDRESS} VMA ${SECTION_VMA}) 232endfunction() 233 234function(create_symbol) 235 cmake_parse_arguments(SYM "" "OBJECT;EXPR;SIZE;SUBALIGN;SYMBOL" "" ${ARGN}) 236 237 set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL} TRUE) 238 set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_OBJ_TYPE SYMBOL) 239 set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_NAME ${SYM_SYMBOL}) 240 set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_EXPR ${SYM_EXPR}) 241 set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SIZE ${SYM_SIZE}) 242 set_property(GLOBAL PROPERTY SYMBOL_${SYM_SYMBOL}_SYMBOL ${SYM_SYMBOL}) 243 244 set_property(GLOBAL PROPERTY SYMBOL_TABLE_${SYM_SYMBOL} ${SYM_SYMBOL}) 245 246 add_symbol(OBJECT ${SYM_OBJECT} SYMBOL SYMBOL_${SYM_SYMBOL}) 247endfunction() 248 249# 250# Create functions - end 251# 252 253# 254# Add functions - start 255# 256function(add_region) 257 cmake_parse_arguments(ADD_REGION "" "OBJECT;REGION" "" ${ARGN}) 258 259 get_property(exists GLOBAL PROPERTY ${ADD_REGION_OBJECT}) 260 if(NOT exists) 261 message(FATAL_ERROR 262 "Adding region ${ADD_REGION_REGION} to none-existing object: " 263 "${ADD_REGION_OBJECT}" 264 ) 265 endif() 266 267 set_property(GLOBAL PROPERTY ${ADD_REGION_REGION}_PARENT ${ADD_REGION_OBJECT}) 268 set_property(GLOBAL APPEND PROPERTY ${ADD_REGION_OBJECT}_REGIONS ${ADD_REGION_REGION}) 269endfunction() 270 271# add_group OBJECT o GROUP g adds group g to object o 272function(add_group) 273 cmake_parse_arguments(ADD_GROUP "" "OBJECT;GROUP" "" ${ARGN}) 274 275 get_property(exists GLOBAL PROPERTY ${ADD_GROUP_OBJECT}) 276 if(NOT exists) 277 message(FATAL_ERROR 278 "Adding group ${ADD_GROUP_GROUP} to none-existing object: " 279 "${ADD_GROUP_OBJECT}" 280 ) 281 endif() 282 283 get_property(vma GLOBAL PROPERTY ${ADD_GROUP_GROUP}_VMA) 284 get_property(object_name GLOBAL PROPERTY ${ADD_GROUP_OBJECT}_NAME) 285 286 if((NOT DEFINED vma) OR ("${vma}" STREQUAL ${object_name})) 287 set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_GROUPS ${ADD_GROUP_GROUP}) 288 else() 289 set_property(GLOBAL APPEND PROPERTY ${ADD_GROUP_OBJECT}_${vma}_GROUPS ${ADD_GROUP_GROUP}) 290 endif() 291endfunction() 292 293function(add_section) 294 cmake_parse_arguments(ADD_SECTION "" "OBJECT;SECTION;ADDRESS;VMA" "" ${ARGN}) 295 296 if(DEFINED ADD_SECTION_OBJECT) 297 get_property(type GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_OBJ_TYPE) 298 get_property(object_name GLOBAL PROPERTY ${ADD_SECTION_OBJECT}_NAME) 299 300 if(NOT DEFINED type) 301 message(FATAL_ERROR 302 "Adding section ${ADD_SECTION_SECTION} to " 303 "none-existing object: ${ADD_SECTION_OBJECT}" 304 ) 305 endif() 306 else() 307 set(ADD_SECTION_OBJECT RELOCATEABLE) 308 endif() 309 310 if("${ADD_SECTION_VMA}" STREQUAL "${object_name}" AND DEFINED ADD_SECTION_ADDRESS) 311 set_property(GLOBAL APPEND PROPERTY 312 ${ADD_SECTION_OBJECT}_SECTIONS_FIXED 313 SECTION_${ADD_SECTION_SECTION} 314 ) 315 elseif(NOT DEFINED ADD_SECTION_VMA AND DEFINED SECTION_ADDRESS) 316 set_property(GLOBAL APPEND PROPERTY 317 ${ADD_SECTION_OBJECT}_SECTIONS_FIXED 318 SECTION_${ADD_SECTION_SECTION} 319 ) 320 elseif("${ADD_SECTION_VMA}" STREQUAL "${object_name}") 321 set_property(GLOBAL APPEND PROPERTY 322 ${ADD_SECTION_OBJECT}_SECTIONS 323 SECTION_${ADD_SECTION_SECTION} 324 ) 325 elseif(NOT DEFINED ADD_SECTION_VMA) 326 set_property(GLOBAL APPEND PROPERTY 327 ${ADD_SECTION_OBJECT}_SECTIONS 328 SECTION_${ADD_SECTION_SECTION} 329 ) 330 elseif(DEFINED SECTION_ADDRESS) 331 set_property(GLOBAL APPEND PROPERTY 332 ${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS_FIXED 333 SECTION_${ADD_SECTION_SECTION} 334 ) 335 else() 336 set_property(GLOBAL APPEND PROPERTY 337 ${ADD_SECTION_OBJECT}_${ADD_SECTION_VMA}_SECTIONS 338 SECTION_${ADD_SECTION_SECTION} 339 ) 340 endif() 341endfunction() 342 343function(add_symbol) 344 cmake_parse_arguments(ADD_SYMBOL "" "OBJECT;SYMBOL" "" ${ARGN}) 345 346 # Section can be fixed address or not, VMA == LMA, . 347 # 348 get_property(exists GLOBAL PROPERTY ${ADD_SYMBOL_OBJECT}) 349 if(NOT exists) 350 message(FATAL_ERROR 351 "Adding symbol ${ADD_SYMBOL_SYMBOL} to none-existing object: " 352 "${ADD_SYMBOL_OBJECT}" 353 ) 354 endif() 355 356 set_property(GLOBAL APPEND PROPERTY ${ADD_SYMBOL_OBJECT}_SYMBOLS ${ADD_SYMBOL_SYMBOL}) 357endfunction() 358 359# 360# Add functions - end 361# 362 363# 364# Retrieval functions - start 365# 366function(find_object) 367 cmake_parse_arguments(FIND "" "OBJECT;NAME" "" ${ARGN}) 368 369 get_property(REGION GLOBAL PROPERTY REGION_${FIND_NAME}) 370 get_property(GROUP GLOBAL PROPERTY GROUP_${FIND_NAME}) 371 get_property(SECTION GLOBAL PROPERTY SECTION_${FIND_NAME}) 372 373 if(REGION) 374 set(${FIND_OBJECT} REGION_${FIND_NAME} PARENT_SCOPE) 375 elseif(GROUP) 376 set(${FIND_OBJECT} GROUP_${FIND_NAME} PARENT_SCOPE) 377 elseif(SECTION) 378 set(${FIND_OBJECT} SECTION_${FIND_NAME} PARENT_SCOPE) 379 else() 380 message(WARNING "No object with name ${FIND_NAME} could be found.") 381 endif() 382endfunction() 383 384# get_object(LIST l OBJECT o TYPE t) 385# sets l to a list of objects of type t that are children of o 386function(get_objects) 387 cmake_parse_arguments(GET "" "LIST;OBJECT;TYPE" "" ${ARGN}) 388 389 # Get what type of object we are starting from 390 get_property(type GLOBAL PROPERTY ${GET_OBJECT}_OBJ_TYPE) 391 392 if(${type} STREQUAL SECTION) 393 # A section doesn't have sub-items. 394 return() 395 endif() 396 397 if(NOT (${GET_TYPE} STREQUAL SECTION 398 OR ${GET_TYPE} STREQUAL GROUP) 399 ) 400 message(WARNING "Only retrieval of SECTION GROUP objects are supported.") 401 return() 402 endif() 403 404 set(out) 405 406 # Find (other) regions in our system 407 get_parent(OBJECT ${GET_OBJECT} PARENT parent TYPE SYSTEM) 408 get_property(regions GLOBAL PROPERTY ${parent}_REGIONS) 409 list(REMOVE_ITEM regions ${GET_OBJECT}) 410 411 if(${GET_TYPE} STREQUAL SECTION) 412 # If we are retrieving sections, then we need to get _SECTIONS_FIXED, 413 # sections from sub-groups, and immediate setion children 414 get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS_FIXED) 415 list(APPEND out ${sections}) 416 417 get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS) 418 foreach(group ${groups}) 419 get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE}) 420 list(APPEND out ${sections}) 421 endforeach() 422 423 get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_SECTIONS) 424 list(APPEND out ${sections}) 425 426 # Now pick up sections from each region via the _vma_ properties. 427 foreach(region ${regions}) 428 get_property(vma GLOBAL PROPERTY ${region}_NAME) 429 430 get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS_FIXED) 431 list(APPEND out ${sections}) 432 433 get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS) 434 foreach(group ${groups}) 435 get_objects(LIST sections OBJECT ${group} TYPE ${GET_TYPE}) 436 list(APPEND out ${sections}) 437 endforeach() 438 439 get_property(sections GLOBAL PROPERTY ${GET_OBJECT}_${vma}_SECTIONS) 440 list(APPEND out ${sections}) 441 endforeach() 442 endif() 443 444 if(${GET_TYPE} STREQUAL GROUP) 445 # For groups we add immediate sub-groups, and all their descendant groups, 446 # and all the _vma_ groups and descendants 447 get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_GROUPS) 448 list(APPEND out ${groups}) 449 450 foreach(group ${groups}) 451 get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE}) 452 list(APPEND out ${subgroups}) 453 endforeach() 454 455 foreach(region ${regions}) 456 get_property(vma GLOBAL PROPERTY ${region}_NAME) 457 458 get_property(groups GLOBAL PROPERTY ${GET_OBJECT}_${vma}_GROUPS) 459 list(APPEND out ${groups}) 460 461 foreach(group ${groups}) 462 get_objects(LIST subgroups OBJECT ${group} TYPE ${GET_TYPE}) 463 list(APPEND out ${subgroups}) 464 endforeach() 465 endforeach() 466 endif() 467 468 set(${GET_LIST} ${out} PARENT_SCOPE) 469endfunction() 470 471# 472# Retrieval functions - end 473# 474 475function(is_empty) 476 cmake_parse_arguments(IS_EMPTY "" "OBJECT" "" ${ARGN}) 477 478 get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS_FIXED) 479 if(DEFINED sections) 480 set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE) 481 return() 482 endif() 483 484 get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_GROUPS) 485 if(DEFINED groups) 486 set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE) 487 return() 488 endif() 489 490 491 get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_SECTIONS) 492 if(DEFINED sections) 493 set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE) 494 return() 495 endif() 496 497 get_parent(OBJECT ${IS_EMPTY_OBJECT} PARENT parent TYPE SYSTEM) 498 get_property(regions GLOBAL PROPERTY ${parent}_REGIONS) 499 list(REMOVE_ITEM regions ${IS_EMPTY_OBJECT}) 500 foreach(region ${regions}) 501 get_property(vma GLOBAL PROPERTY ${region}_NAME) 502 get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS_FIXED) 503 if(DEFINED sections) 504 set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE) 505 return() 506 endif() 507 508 get_property(groups GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_GROUPS) 509 if(DEFINED groups) 510 set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE) 511 return() 512 endif() 513 514 get_property(sections GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_${vma}_SECTIONS) 515 if(DEFINED sections) 516 set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY FALSE) 517 return() 518 endif() 519 endforeach() 520 set_property(GLOBAL PROPERTY ${IS_EMPTY_OBJECT}_EMPTY TRUE) 521endfunction() 522 523# This function post process the region for easier use. 524# 525# This is common post processing. 526# If the calling <linker>_script.cmake generator implements its own 527# process_region(), then the process_region_common() must be called explicitly 528# from the process_region() from the <linker>_script.cmake generator. 529# 530# This allows a custom <linker>_script.cmake generator to completely disable 531# the common post processing of regions. 532# 533# Tasks: 534# - Apply missing settings, such as initial address for first section in a region. 535# - Symbol names on sections 536# - Ordered list of all sections for easier retrieval on printing and configuration. 537function(process_region_common) 538 cmake_parse_arguments(REGION_COMMON "" "OBJECT" "" ${ARGN}) 539 540 is_empty(OBJECT ${REGION_COMMON_OBJECT}) 541 542 set(sections) 543 get_objects(LIST sections OBJECT ${REGION_COMMON_OBJECT} TYPE SECTION) 544 set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_SECTION_LIST_ORDERED ${sections}) 545 546 set(groups) 547 get_objects(LIST groups OBJECT ${REGION_COMMON_OBJECT} TYPE GROUP) 548 set_property(GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_GROUP_LIST_ORDERED ${groups}) 549 550 list(LENGTH sections section_count) 551 if(section_count GREATER 0) 552 list(GET sections 0 section) 553 get_property(address GLOBAL PROPERTY ${section}_ADDRESS) 554 if(NOT DEFINED address) 555 get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE REGION) 556 get_property(address GLOBAL PROPERTY ${parent}_ADDRESS) 557 set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address}) 558 endif() 559 endif() 560 561 # Loop over other regions with the same parent 562 get_parent(OBJECT ${REGION_COMMON_OBJECT} PARENT parent TYPE SYSTEM) 563 get_property(regions GLOBAL PROPERTY ${parent}_REGIONS) 564 list(REMOVE_ITEM regions ${REGION_COMMON_OBJECT}) 565 foreach(region ${regions}) 566 get_property(vma GLOBAL PROPERTY ${region}_NAME) 567 set(sections_${vma}) 568 get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS_FIXED) 569 list(APPEND sections_${vma} ${sections}) 570 571 get_property(groups GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_GROUPS) 572 foreach(group ${groups}) 573 get_objects(LIST sections OBJECT ${group} TYPE SECTION) 574 list(APPEND sections_${vma} ${sections}) 575 endforeach() 576 577 get_property(sections GLOBAL PROPERTY ${REGION_COMMON_OBJECT}_${vma}_SECTIONS) 578 list(APPEND sections_${vma} ${sections}) 579 580 list(LENGTH sections_${vma} section_count) 581 if(section_count GREATER 0) 582 list(GET sections_${vma} 0 section) 583 get_property(address GLOBAL PROPERTY ${section}_ADDRESS) 584 if(NOT DEFINED address) 585 get_property(address GLOBAL PROPERTY ${region}_ADDRESS) 586 set_property(GLOBAL PROPERTY ${section}_ADDRESS ${address}) 587 endif() 588 endif() 589 endforeach() 590endfunction() 591 592if(NOT COMMAND process_region) 593 function(process_region) 594 process_region_common(${ARGN}) 595 endfunction() 596endif() 597 598 599# 600# String functions - start 601# 602# Each linker must implement their own <type>_to_string() functions to 603# generate a correct linker script. 604# 605if(NOT COMMAND system_to_string) 606 function(system_to_string) 607 message(WARNING "No linker defined function found. Please implement a " 608 "system_to_string() function for this linker." 609 ) 610 endfunction() 611endif() 612 613if(NOT COMMAND group_to_string) 614 function(group_to_string) 615 message(WARNING "No linker defined function found. Please implement a " 616 "group_to_string() function for this linker." 617 ) 618 endfunction() 619endif() 620 621if(NOT COMMAND section_to_string) 622 function(section_to_string) 623 message(WARNING "No linker defined function found. Please implement a " 624 "section_to_string() function for this linker." 625 ) 626 endfunction() 627endif() 628 629if(NOT COMMAND symbol_to_string) 630 function(symbol_to_string) 631 message(WARNING "No linker defined function found. Please implement a " 632 "symbol_to_string() function for this linker." 633 ) 634 endfunction() 635endif() 636 637function(to_string) 638 cmake_parse_arguments(STRING "" "OBJECT;STRING" "" ${ARGN}) 639 640 get_property(type GLOBAL PROPERTY ${STRING_OBJECT}_OBJ_TYPE) 641 642 if("${type}" STREQUAL SYSTEM) 643 system_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING}) 644 elseif(("${type}" STREQUAL REGION) OR ("${type}" STREQUAL GROUP)) 645 group_to_string(OBJECT ${STRING_OBJECT} STRING ${STRING_STRING}) 646 elseif("${type}" STREQUAL SECTION) 647 section_to_string(SECTION ${STRING_OBJECT} STRING ${STRING_STRING}) 648 elseif("${type}" STREQUAL SYMBOL) 649 symbol_to_string(SYMBOL ${STRING_OBJECT} STRING ${STRING_STRING}) 650 endif() 651 652 set(${STRING_STRING} ${${STRING_STRING}} PARENT_SCOPE) 653endfunction() 654 655# 656# String functions - end 657# 658 659## Preprocess and gather input 660foreach(VAR ${VARIABLES}) 661 if("${VAR}" MATCHES "^{(.*)}$") 662 cmake_parse_arguments(VAR "" "VAR;VALUE" "PASS" ${CMAKE_MATCH_1}) 663 664 if(DEFINED VAR_PASS) 665 is_active_in_pass(active ${PASS} "${VAR_PASS}") 666 if(NOT active) 667 continue() 668 endif() 669 endif() 670 671 set(${VAR_VAR} "${VAR_VALUE}" CACHE INTERNAL "") 672 endif() 673endforeach() 674 675# By the input we have INCLUDES defined that contains the files that we need 676# to include depending on linker pass. 677foreach(file ${INCLUDES}) 678 if("${file}" MATCHES "^{(.*)}$") 679 cmake_parse_arguments(INC "" "KCONFIG;HEADER;CMAKE" "PASS" ${CMAKE_MATCH_1}) 680 681 if(DEFINED INC_PASS) 682 is_active_in_pass(active ${PASS} "${INC_PASS}") 683 if(NOT active) 684 continue() 685 endif() 686 endif() 687 688 if(CMAKE_VERBOSE_MAKEFILE) 689 message("Reading file ${INC_KCONFIG}${INC_HEADER}${INC_CMAKE}") 690 endif() 691 692 if(INC_KCONFIG) 693 import_kconfig(CONFIG ${INC_KCONFIG}) 694 elseif(INC_CMAKE) 695 include(${INC_CMAKE}) 696 elseif(INC_HEADER) 697 list(APPEND PREPROCESSOR_FILES ${INC_HEADER}) 698 endif() 699 endif() 700endforeach() 701 702# For now, lets start with @FOO@ and store each #define FOO value as a global 703# property AT_VAR_FOO (prefix to avoid name clashes). 704# We will do all the replacements in the input lists before giving them to the 705# generator functions. 706set(VAR_DEF_REGEX "#define ([A-Za-z0-9_]+)[ \t\r\n]+(.+)") 707foreach(file IN LISTS PREPROCESSOR_FILES ) 708 if(EXISTS ${file}) 709 file(STRINGS ${file} defs REGEX ${VAR_DEF_REGEX}) 710 foreach(def ${defs}) 711 if(${def} MATCHES ${VAR_DEF_REGEX}) 712 set("AT_VAR_${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}") 713 endif() 714 endforeach() 715 else() 716 message("Missing file ${file}") 717 endif() 718endforeach() 719 720# To pickup information gathered by the scripts from the previous pass, we use 721# the syntax @FOO@ where FOO is a cmake variable name 722function(do_var_replace_in res_ptr src) 723 string(REGEX MATCHALL "@([^@]*)@" match_res "${src}") 724 foreach(match IN LISTS match_res) 725 string(REPLACE "@" "" expr ${match}) 726 # the variable expression is as follows: 727 # @NAME[,undef:VALUE]@ Where the VALUE gets picked if we dont find NAME 728 string(REPLACE "," ";" expr ${expr}) 729 list(GET expr 0 var) 730 if(DEFINED "AT_VAR_${var}") 731 set(value "${AT_VAR_${var}}") 732 elseif(DEFINED ${var}) # set by zephyr_linker_include_generated files 733 set(value "${${var}}") 734 elseif("${expr}" MATCHES ";undef:([^,]*)") 735 set(value "${CMAKE_MATCH_1}") 736 else() 737 set(value "${match}") 738 # can't warn here because we can't check for what is relevant in this pass 739 # message(WARNING "Missing definition for ${match}") 740 endif() 741 742 if(CMAKE_VERBOSE_MAKEFILE) 743 message("Using variable ${match} with value ${value}") 744 endif() 745 string(REPLACE "${match}" "${value}" src "${src}") 746 endforeach() 747 set(${res_ptr} "${src}" PARENT_SCOPE) 748endfunction() 749 750foreach(input IN ITEMS "MEMORY_REGIONS" "GROUPS" "SECTIONS" "SECTION_SETTINGS") 751 do_var_replace_in(${input} "${${input}}") 752endforeach() 753 754 755create_system(OBJECT new_system NAME ZEPHYR_LINKER_v1 FORMAT ${FORMAT} ENTRY ${ENTRY}) 756 757# Sorting the memory sections in ascending order. 758foreach(region ${MEMORY_REGIONS}) 759 if("${region}" MATCHES "^{(.*)}$") 760 cmake_parse_arguments(REGION "" "NAME;START" "" ${CMAKE_MATCH_1}) 761 math(EXPR start_dec "${REGION_START}" OUTPUT_FORMAT DECIMAL) 762 set(region_id ${start_dec}_${REGION_NAME}) 763 set(region_${region_id} ${region}) 764 string(REPLACE ";" "\;" region_${region_id} "${region_${region_id}}") 765 list(APPEND region_sort ${region_id}) 766 endif() 767endforeach() 768 769list(SORT region_sort COMPARE NATURAL) 770set(MEMORY_REGIONS_SORTED) 771foreach(region_start ${region_sort}) 772 list(APPEND MEMORY_REGIONS_SORTED "${region_${region_start}}") 773endforeach() 774# sorting complete. 775 776foreach(region ${MEMORY_REGIONS_SORTED}) 777 if("${region}" MATCHES "^{(.*)}$") 778 create_region(OBJECT new_region ${CMAKE_MATCH_1}) 779 add_region(OBJECT ${new_system} REGION ${new_region}) 780 endif() 781endforeach() 782 783foreach(group ${GROUPS}) 784 if("${group}" MATCHES "^{(.*)}$") 785 create_group(OBJECT new_group ${CMAKE_MATCH_1}) 786 endif() 787endforeach() 788 789foreach(section ${SECTIONS} ${DEVICE_API_SECTIONS}) 790 if("${section}" MATCHES "^{(.*)}$") 791 create_section(${CMAKE_MATCH_1} SYSTEM ${new_system}) 792 endif() 793endforeach() 794 795foreach(symbol ${SYMBOLS}) 796 if("${symbol}" MATCHES "^{(.*)}$") 797 create_symbol(OBJECT ${new_system} ${CMAKE_MATCH_1}) 798 endif() 799endforeach() 800 801get_property(regions GLOBAL PROPERTY ${new_system}_REGIONS) 802foreach(region ${regions}) 803 process_region(OBJECT ${region}) 804endforeach() 805 806set(OUT) 807to_string(OBJECT ${new_system} STRING OUT) 808 809if(OUT_FILE) 810 file(WRITE ${OUT_FILE} "${OUT}") 811endif() 812