extensions.cmake 122 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572
  1. # SPDX-License-Identifier: Apache-2.0
  2. ########################################################
  3. # Table of contents
  4. ########################################################
  5. # 1. Zephyr-aware extensions
  6. # 1.1. zephyr_*
  7. # 1.2. zephyr_library_*
  8. # 1.2.1 zephyr_interface_library_*
  9. # 1.3. generate_inc_*
  10. # 1.4. board_*
  11. # 1.5. Misc.
  12. # 2. Kconfig-aware extensions
  13. # 2.1 Misc
  14. # 3. CMake-generic extensions
  15. # 3.1. *_ifdef
  16. # 3.2. *_ifndef
  17. # 3.3. *_option compiler compatibility checks
  18. # 3.3.1 Toolchain integration
  19. # 3.4. Debugging CMake
  20. # 3.5. File system management
  21. # 4. Devicetree extensions
  22. # 4.1 dt_*
  23. # 5. Zephyr linker functions
  24. # 5.1. zephyr_linker*
  25. ########################################################
  26. # 1. Zephyr-aware extensions
  27. ########################################################
  28. # 1.1. zephyr_*
  29. #
  30. # The following methods are for modifying the CMake library[0] called
  31. # "zephyr". zephyr is a catch-all CMake library for source files that
  32. # can be built purely with the include paths, defines, and other
  33. # compiler flags that all zephyr source files use.
  34. # [0] https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html
  35. #
  36. # Example usage:
  37. # zephyr_sources(
  38. # random_esp32.c
  39. # utils.c
  40. # )
  41. #
  42. # Is short for:
  43. # target_sources(zephyr PRIVATE
  44. # ${CMAKE_CURRENT_SOURCE_DIR}/random_esp32.c
  45. # ${CMAKE_CURRENT_SOURCE_DIR}/utils.c
  46. # )
  47. #
  48. # As a very high-level introduction here are two call graphs that are
  49. # purposely minimalistic and incomplete.
  50. #
  51. # zephyr_library_cc_option()
  52. # |
  53. # v
  54. # zephyr_library_compile_options() --> target_compile_options()
  55. #
  56. #
  57. # zephyr_cc_option() ---> target_cc_option()
  58. # |
  59. # v
  60. # zephyr_cc_option_fallback() ---> target_cc_option_fallback()
  61. # |
  62. # v
  63. # zephyr_compile_options() ---> target_compile_options()
  64. #
  65. # https://cmake.org/cmake/help/latest/command/target_sources.html
  66. function(zephyr_sources)
  67. foreach(arg ${ARGV})
  68. if(IS_DIRECTORY ${arg})
  69. message(FATAL_ERROR "zephyr_sources() was called on a directory")
  70. endif()
  71. target_sources(zephyr PRIVATE ${arg})
  72. endforeach()
  73. endfunction()
  74. # https://cmake.org/cmake/help/latest/command/target_include_directories.html
  75. function(zephyr_include_directories)
  76. foreach(arg ${ARGV})
  77. if(IS_ABSOLUTE ${arg})
  78. set(path ${arg})
  79. else()
  80. set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
  81. endif()
  82. target_include_directories(zephyr_interface INTERFACE ${path})
  83. endforeach()
  84. endfunction()
  85. # https://cmake.org/cmake/help/latest/command/target_include_directories.html
  86. function(zephyr_system_include_directories)
  87. foreach(arg ${ARGV})
  88. if(IS_ABSOLUTE ${arg})
  89. set(path ${arg})
  90. else()
  91. set(path ${CMAKE_CURRENT_SOURCE_DIR}/${arg})
  92. endif()
  93. target_include_directories(zephyr_interface SYSTEM INTERFACE ${path})
  94. endforeach()
  95. endfunction()
  96. # https://cmake.org/cmake/help/latest/command/target_compile_definitions.html
  97. function(zephyr_compile_definitions)
  98. target_compile_definitions(zephyr_interface INTERFACE ${ARGV})
  99. endfunction()
  100. # https://cmake.org/cmake/help/latest/command/target_compile_options.html
  101. function(zephyr_compile_options)
  102. target_compile_options(zephyr_interface INTERFACE ${ARGV})
  103. endfunction()
  104. # https://cmake.org/cmake/help/latest/command/target_link_libraries.html
  105. function(zephyr_link_libraries)
  106. target_link_libraries(zephyr_interface INTERFACE ${ARGV})
  107. endfunction()
  108. # See this file section 3.1. target_cc_option
  109. function(zephyr_cc_option)
  110. foreach(arg ${ARGV})
  111. target_cc_option(zephyr_interface INTERFACE ${arg})
  112. endforeach()
  113. endfunction()
  114. function(zephyr_cc_option_fallback option1 option2)
  115. target_cc_option_fallback(zephyr_interface INTERFACE ${option1} ${option2})
  116. endfunction()
  117. function(zephyr_ld_options)
  118. target_ld_options(zephyr_interface INTERFACE ${ARGV})
  119. endfunction()
  120. # Getter functions for extracting build information from
  121. # zephyr_interface. Returning lists, and strings is supported, as is
  122. # requesting specific categories of build information (defines,
  123. # includes, options).
  124. #
  125. # The naming convention follows:
  126. # zephyr_get_${build_information}_for_lang${format}(lang x [STRIP_PREFIX])
  127. # Where
  128. # the argument 'x' is written with the result
  129. # and
  130. # ${build_information} can be one of
  131. # - include_directories # -I directories
  132. # - system_include_directories # -isystem directories
  133. # - compile_definitions # -D'efines
  134. # - compile_options # misc. compiler flags
  135. # and
  136. # ${format} can be
  137. # - the empty string '', signifying that it should be returned as a list
  138. # - _as_string signifying that it should be returned as a string
  139. # and
  140. # ${lang} can be one of
  141. # - C
  142. # - CXX
  143. # - ASM
  144. #
  145. # STRIP_PREFIX
  146. #
  147. # By default the result will be returned ready to be passed directly
  148. # to a compiler, e.g. prefixed with -D, or -I, but it is possible to
  149. # omit this prefix by specifying 'STRIP_PREFIX' . This option has no
  150. # effect for 'compile_options'.
  151. #
  152. # e.g.
  153. # zephyr_get_include_directories_for_lang(ASM x)
  154. # writes "-Isome_dir;-Isome/other/dir" to x
  155. function(zephyr_get_include_directories_for_lang_as_string lang i)
  156. zephyr_get_include_directories_for_lang(${lang} list_of_flags DELIMITER " " ${ARGN})
  157. convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
  158. set(${i} ${str_of_flags} PARENT_SCOPE)
  159. endfunction()
  160. function(zephyr_get_system_include_directories_for_lang_as_string lang i)
  161. zephyr_get_system_include_directories_for_lang(${lang} list_of_flags DELIMITER " " ${ARGN})
  162. convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
  163. set(${i} ${str_of_flags} PARENT_SCOPE)
  164. endfunction()
  165. function(zephyr_get_compile_definitions_for_lang_as_string lang i)
  166. zephyr_get_compile_definitions_for_lang(${lang} list_of_flags DELIMITER " " ${ARGN})
  167. convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
  168. set(${i} ${str_of_flags} PARENT_SCOPE)
  169. endfunction()
  170. function(zephyr_get_compile_options_for_lang_as_string lang i)
  171. zephyr_get_compile_options_for_lang(${lang} list_of_flags DELIMITER " ")
  172. convert_list_of_flags_to_string_of_flags(list_of_flags str_of_flags)
  173. set(${i} ${str_of_flags} PARENT_SCOPE)
  174. endfunction()
  175. function(zephyr_get_include_directories_for_lang lang i)
  176. zephyr_get_parse_args(args ${ARGN})
  177. get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
  178. process_flags(${lang} flags output_list)
  179. string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
  180. if(NOT ARGN)
  181. set(result_output_list "-I$<JOIN:${genexp_output_list},$<SEMICOLON>-I>")
  182. elseif(args_STRIP_PREFIX)
  183. # The list has no prefix, so don't add it.
  184. set(result_output_list ${output_list})
  185. elseif(args_DELIMITER)
  186. set(result_output_list "-I$<JOIN:${genexp_output_list},${args_DELIMITER}-I>")
  187. endif()
  188. set(${i} ${result_output_list} PARENT_SCOPE)
  189. endfunction()
  190. function(zephyr_get_system_include_directories_for_lang lang i)
  191. zephyr_get_parse_args(args ${ARGN})
  192. get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES)
  193. process_flags(${lang} flags output_list)
  194. string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
  195. set_ifndef(args_DELIMITER "$<SEMICOLON>")
  196. set(result_output_list "$<$<BOOL:${genexp_output_list}>:-isystem$<JOIN:${genexp_output_list},${args_DELIMITER}-isystem>>")
  197. set(${i} ${result_output_list} PARENT_SCOPE)
  198. endfunction()
  199. function(zephyr_get_compile_definitions_for_lang lang i)
  200. zephyr_get_parse_args(args ${ARGN})
  201. get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_COMPILE_DEFINITIONS)
  202. process_flags(${lang} flags output_list)
  203. string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
  204. set_ifndef(args_DELIMITER "$<SEMICOLON>")
  205. set(result_output_list "-D$<JOIN:${genexp_output_list},${args_DELIMITER}-D>")
  206. set(${i} ${result_output_list} PARENT_SCOPE)
  207. endfunction()
  208. function(zephyr_get_compile_options_for_lang lang i)
  209. zephyr_get_parse_args(args ${ARGN})
  210. get_property(flags TARGET zephyr_interface PROPERTY INTERFACE_COMPILE_OPTIONS)
  211. process_flags(${lang} flags output_list)
  212. string(REPLACE ";" "$<SEMICOLON>" genexp_output_list "${output_list}")
  213. set_ifndef(args_DELIMITER "$<SEMICOLON>")
  214. set(result_output_list "$<JOIN:${genexp_output_list},${args_DELIMITER}>")
  215. set(${i} ${result_output_list} PARENT_SCOPE)
  216. endfunction()
  217. # This function writes a dict to it's output parameter
  218. # 'return_dict'. The dict has information about the parsed arguments,
  219. #
  220. # Usage:
  221. # zephyr_get_parse_args(foo ${ARGN})
  222. # print(foo_STRIP_PREFIX) # foo_STRIP_PREFIX might be set to 1
  223. function(zephyr_get_parse_args return_dict)
  224. foreach(x ${ARGN})
  225. if(DEFINED single_argument)
  226. set(${single_argument} ${x} PARENT_SCOPE)
  227. unset(single_argument)
  228. else()
  229. if(x STREQUAL STRIP_PREFIX)
  230. set(${return_dict}_STRIP_PREFIX 1 PARENT_SCOPE)
  231. elseif(x STREQUAL NO_SPLIT)
  232. set(${return_dict}_NO_SPLIT 1 PARENT_SCOPE)
  233. elseif(x STREQUAL DELIMITER)
  234. set(single_argument ${return_dict}_DELIMITER)
  235. endif()
  236. endif()
  237. endforeach()
  238. endfunction()
  239. function(process_flags lang input output)
  240. # The flags might contains compile language generator expressions that
  241. # look like this:
  242. # $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
  243. # $<$<COMPILE_LANGUAGE:CXX>:$<OTHER_EXPRESSION>>
  244. #
  245. # Flags that don't specify a language like this apply to all
  246. # languages.
  247. #
  248. # See COMPILE_LANGUAGE in
  249. # https://cmake.org/cmake/help/v3.3/manual/cmake-generator-expressions.7.html
  250. #
  251. # To deal with this, we apply a regex to extract the flag and also
  252. # to find out if the language matches.
  253. #
  254. # If this doesn't work out we might need to ban the use of
  255. # COMPILE_LANGUAGE and instead partition C, CXX, and ASM into
  256. # different libraries
  257. set(languages C CXX ASM)
  258. set(tmp_list "")
  259. foreach(flag ${${input}})
  260. set(is_compile_lang_generator_expression 0)
  261. foreach(l ${languages})
  262. if(flag MATCHES "<COMPILE_LANGUAGE:${l}>:([^>]+)>")
  263. set(updated_flag ${CMAKE_MATCH_1})
  264. set(is_compile_lang_generator_expression 1)
  265. if(${l} STREQUAL ${lang})
  266. # This test will match in case there are more generator expressions in the flag.
  267. # As example: $<$<COMPILE_LANGUAGE:C>:$<OTHER_EXPRESSION>>
  268. # $<$<OTHER_EXPRESSION:$<COMPILE_LANGUAGE:C>:something>>
  269. string(REGEX MATCH "(\\\$<)[^\\\$]*(\\\$<)[^\\\$]*(\\\$<)" IGNORE_RESULT ${flag})
  270. if(CMAKE_MATCH_2)
  271. # Nested generator expressions are used, just substitue `$<COMPILE_LANGUAGE:${l}>` to `1`
  272. string(REGEX REPLACE "\\\$<COMPILE_LANGUAGE:${l}>" "1" updated_flag ${flag})
  273. endif()
  274. list(APPEND tmp_list ${updated_flag})
  275. break()
  276. endif()
  277. endif()
  278. endforeach()
  279. if(NOT is_compile_lang_generator_expression)
  280. # SHELL is used to avoid de-deplucation, but when process flags
  281. # then this tag must be removed to return real compile/linker flags.
  282. if(flag MATCHES "SHELL:[ ]*(.*)")
  283. separate_arguments(flag UNIX_COMMAND ${CMAKE_MATCH_1})
  284. endif()
  285. # Flags may be placed inside generator expression, therefore any flag
  286. # which is not already a generator expression must have commas converted.
  287. if(NOT flag MATCHES "\\\$<.*>")
  288. string(REPLACE "," "$<COMMA>" flag "${flag}")
  289. endif()
  290. list(APPEND tmp_list ${flag})
  291. endif()
  292. endforeach()
  293. set(${output} ${tmp_list} PARENT_SCOPE)
  294. endfunction()
  295. function(convert_list_of_flags_to_string_of_flags ptr_list_of_flags string_of_flags)
  296. # Convert the list to a string so we can do string replace
  297. # operations on it and replace the ";" list separators with a
  298. # whitespace so the flags are spaced out
  299. string(REPLACE ";" " " locally_scoped_string_of_flags "${${ptr_list_of_flags}}")
  300. # Set the output variable in the parent scope
  301. set(${string_of_flags} ${locally_scoped_string_of_flags} PARENT_SCOPE)
  302. endfunction()
  303. macro(get_property_and_add_prefix result target property prefix)
  304. zephyr_get_parse_args(args ${ARGN})
  305. if(args_STRIP_PREFIX)
  306. set(maybe_prefix "")
  307. else()
  308. set(maybe_prefix ${prefix})
  309. endif()
  310. get_property(target_property TARGET ${target} PROPERTY ${property})
  311. foreach(x ${target_property})
  312. list(APPEND ${result} ${maybe_prefix}${x})
  313. endforeach()
  314. endmacro()
  315. # 1.2 zephyr_library_*
  316. #
  317. # Zephyr libraries use CMake's library concept and a set of
  318. # assumptions about how zephyr code is organized to cut down on
  319. # boilerplate code.
  320. #
  321. # A Zephyr library can be constructed by the function zephyr_library
  322. # or zephyr_library_named. The constructors create a CMake library
  323. # with a name accessible through the variable ZEPHYR_CURRENT_LIBRARY.
  324. #
  325. # The variable ZEPHYR_CURRENT_LIBRARY should seldom be needed since
  326. # the zephyr libraries have methods that modify the libraries. These
  327. # methods have the signature: zephyr_library_<target-function>
  328. #
  329. # The methods are wrappers around the CMake target_* functions. See
  330. # https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
  331. # documentation on the underlying target_* functions.
  332. #
  333. # The methods modify the CMake target_* API to reduce boilerplate;
  334. # PRIVATE is assumed
  335. # The target is assumed to be ZEPHYR_CURRENT_LIBRARY
  336. #
  337. # When a flag that is given through the zephyr_* API conflicts with
  338. # the zephyr_library_* API then precedence will be given to the
  339. # zephyr_library_* API. In other words, local configuration overrides
  340. # global configuration.
  341. # Constructor with a directory-inferred name
  342. macro(zephyr_library)
  343. zephyr_library_get_current_dir_lib_name(${ZEPHYR_BASE} lib_name)
  344. zephyr_library_named(${lib_name})
  345. endmacro()
  346. # Determines what the current directory's lib name would be according to the
  347. # provided base and writes it to the argument "lib_name"
  348. macro(zephyr_library_get_current_dir_lib_name base lib_name)
  349. # Remove the prefix (/home/sebo/zephyr/driver/serial/CMakeLists.txt => driver/serial/CMakeLists.txt)
  350. file(RELATIVE_PATH name ${base} ${CMAKE_CURRENT_LIST_FILE})
  351. # Remove the filename (driver/serial/CMakeLists.txt => driver/serial)
  352. get_filename_component(name ${name} DIRECTORY)
  353. # Replace / with __ (driver/serial => driver__serial)
  354. string(REGEX REPLACE "/" "__" name ${name})
  355. set(${lib_name} ${name})
  356. endmacro()
  357. # Constructor with an explicitly given name.
  358. macro(zephyr_library_named name)
  359. # This is a macro because we need add_library() to be executed
  360. # within the scope of the caller.
  361. set(ZEPHYR_CURRENT_LIBRARY ${name})
  362. add_library(${name} STATIC "")
  363. zephyr_append_cmake_library(${name})
  364. target_link_libraries(${name} PUBLIC zephyr_interface)
  365. endmacro()
  366. # Provides amend functionality to a Zephyr library for out-of-tree usage.
  367. #
  368. # When called from a Zephyr module, the corresponding zephyr library defined
  369. # within Zephyr will be looked up.
  370. #
  371. # Note, in order to ensure correct library when amending, the folder structure in the
  372. # Zephyr module must resemble the structure used in Zephyr, as example:
  373. #
  374. # Example: to amend the zephyr library created in
  375. # ZEPHYR_BASE/drivers/entropy/CMakeLists.txt
  376. # add the following file:
  377. # ZEPHYR_MODULE/drivers/entropy/CMakeLists.txt
  378. # with content:
  379. # zephyr_library_amend()
  380. # zephyr_libray_add_sources(...)
  381. #
  382. # It is also possible to use generator expression when amending to Zephyr
  383. # libraries.
  384. #
  385. # For example, in case it is required to expose the Zephyr library's folder as
  386. # include path then the following is possible:
  387. # zephyr_library_amend()
  388. # zephyr_library_include_directories($<TARGET_PROPERTY:SOURCE_DIR>)
  389. #
  390. # See the CMake documentation for more target properties or generator
  391. # expressions.
  392. #
  393. macro(zephyr_library_amend)
  394. # This is a macro because we need to ensure the ZEPHYR_CURRENT_LIBRARY and
  395. # following zephyr_library_* calls are executed within the scope of the
  396. # caller.
  397. if(NOT ZEPHYR_CURRENT_MODULE_DIR)
  398. message(FATAL_ERROR "Function only available for Zephyr modules.")
  399. endif()
  400. zephyr_library_get_current_dir_lib_name(${ZEPHYR_CURRENT_MODULE_DIR} lib_name)
  401. set(ZEPHYR_CURRENT_LIBRARY ${lib_name})
  402. endmacro()
  403. function(zephyr_link_interface interface)
  404. target_link_libraries(${interface} INTERFACE zephyr_interface)
  405. endfunction()
  406. #
  407. # zephyr_library versions of normal CMake target_<func> functions
  408. #
  409. function(zephyr_library_sources source)
  410. target_sources(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${source} ${ARGN})
  411. endfunction()
  412. function(zephyr_library_include_directories)
  413. target_include_directories(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${ARGN})
  414. endfunction()
  415. function(zephyr_library_link_libraries item)
  416. target_link_libraries(${ZEPHYR_CURRENT_LIBRARY} PUBLIC ${item} ${ARGN})
  417. endfunction()
  418. function(zephyr_library_compile_definitions item)
  419. target_compile_definitions(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${item} ${ARGN})
  420. endfunction()
  421. function(zephyr_library_compile_options item)
  422. # The compiler is relied upon for sane behaviour when flags are in
  423. # conflict. Compilers generally give precedence to flags given late
  424. # on the command line. So to ensure that zephyr_library_* flags are
  425. # placed late on the command line we create a dummy interface
  426. # library and link with it to obtain the flags.
  427. #
  428. # Linking with a dummy interface library will place flags later on
  429. # the command line than the the flags from zephyr_interface because
  430. # zephyr_interface will be the first interface library that flags
  431. # are taken from.
  432. string(MD5 uniqueness ${item})
  433. set(lib_name options_interface_lib_${uniqueness})
  434. if (TARGET ${lib_name})
  435. # ${item} already added, ignoring duplicate just like CMake does
  436. return()
  437. endif()
  438. add_library( ${lib_name} INTERFACE)
  439. target_compile_options(${lib_name} INTERFACE ${item} ${ARGN})
  440. target_link_libraries(${ZEPHYR_CURRENT_LIBRARY} PRIVATE ${lib_name})
  441. endfunction()
  442. function(zephyr_library_cc_option)
  443. foreach(option ${ARGV})
  444. string(MAKE_C_IDENTIFIER check${option} check)
  445. zephyr_check_compiler_flag(C ${option} ${check})
  446. if(${check})
  447. zephyr_library_compile_options(${option})
  448. endif()
  449. endforeach()
  450. endfunction()
  451. # Add the existing CMake library 'library' to the global list of
  452. # Zephyr CMake libraries. This is done automatically by the
  453. # constructor but must called explicitly on CMake libraries that do
  454. # not use a zephyr library constructor.
  455. function(zephyr_append_cmake_library library)
  456. if(TARGET zephyr_prebuilt)
  457. message(WARNING
  458. "zephyr_library() or zephyr_library_named() called in Zephyr CMake "
  459. "application mode. `${library}` will not be treated as a Zephyr library."
  460. "To create a Zephyr library in Zephyr CMake kernel mode consider "
  461. "creating a Zephyr module. See more here: "
  462. "https://docs.zephyrproject.org/latest/guides/modules.html"
  463. )
  464. endif()
  465. set_property(GLOBAL APPEND PROPERTY ZEPHYR_LIBS ${library})
  466. endfunction()
  467. # Add the imported library 'library_name', located at 'library_path' to the
  468. # global list of Zephyr CMake libraries.
  469. function(zephyr_library_import library_name library_path)
  470. add_library(${library_name} STATIC IMPORTED GLOBAL)
  471. set_target_properties(${library_name}
  472. PROPERTIES IMPORTED_LOCATION
  473. ${library_path}
  474. )
  475. zephyr_append_cmake_library(${library_name})
  476. endfunction()
  477. # Place the current zephyr library in the application memory partition.
  478. #
  479. # The partition argument is the name of the partition where the library shall
  480. # be placed.
  481. #
  482. # Note: Ensure the given partition has been define using
  483. # K_APPMEM_PARTITION_DEFINE in source code.
  484. function(zephyr_library_app_memory partition)
  485. set_property(TARGET zephyr_property_target
  486. APPEND PROPERTY COMPILE_OPTIONS
  487. "-l" $<TARGET_FILE_NAME:${ZEPHYR_CURRENT_LIBRARY}> "${partition}")
  488. endfunction()
  489. # Configure a Zephyr library specific property.
  490. #
  491. # Usage:
  492. # zephyr_library_property(<property> <value>)
  493. #
  494. # Current Zephyr library specific properties that are supported:
  495. # ALLOW_EMPTY <TRUE:FALSE>: Allow a Zephyr library to be empty.
  496. # An empty Zephyr library will generate a CMake
  497. # configure time warning unless `ALLOW_EMPTY` is TRUE.
  498. function(zephyr_library_property)
  499. set(single_args "ALLOW_EMPTY")
  500. cmake_parse_arguments(LIB_PROP "" "${single_args}" "" ${ARGN})
  501. if(LIB_PROP_UNPARSED_ARGUMENTS)
  502. message(FATAL_ERROR "zephyr_library_property(${ARGV0} ...) given unknown arguments: ${FILE_UNPARSED_ARGUMENTS}")
  503. endif()
  504. foreach(arg ${single_args})
  505. if(DEFINED LIB_PROP_${arg})
  506. set_property(TARGET ${ZEPHYR_CURRENT_LIBRARY} PROPERTY ${arg} ${LIB_PROP_${arg}})
  507. endif()
  508. endforeach()
  509. endfunction()
  510. # 1.2.1 zephyr_interface_library_*
  511. #
  512. # A Zephyr interface library is a thin wrapper over a CMake INTERFACE
  513. # library. The most important responsibility of this abstraction is to
  514. # ensure that when a user KConfig-enables a library then the header
  515. # files of this library will be accessible to the 'app' library.
  516. #
  517. # This is done because when a user uses Kconfig to enable a library he
  518. # expects to be able to include it's header files and call it's
  519. # functions out-of-the box.
  520. #
  521. # A Zephyr interface library should be used when there exists some
  522. # build information (include directories, defines, compiler flags,
  523. # etc.) that should be applied to a set of Zephyr libraries and 'app'
  524. # might be one of these libraries.
  525. #
  526. # Zephyr libraries must explicitly call
  527. # zephyr_library_link_libraries(<interface_library>) to use this build
  528. # information. 'app' is treated as a special case for usability
  529. # reasons; a Kconfig option (CONFIG_APP_LINK_WITH_<interface_library>)
  530. # should exist for each interface_library and will determine if 'app'
  531. # links with the interface_library.
  532. #
  533. # This API has a constructor like the zephyr_library API has, but it
  534. # does not have wrappers over the other cmake target functions.
  535. macro(zephyr_interface_library_named name)
  536. add_library(${name} INTERFACE)
  537. set_property(GLOBAL APPEND PROPERTY ZEPHYR_INTERFACE_LIBS ${name})
  538. endmacro()
  539. # 1.3 generate_inc_*
  540. # These functions are useful if there is a need to generate a file
  541. # that can be included into the application at build time. The file
  542. # can also be compressed automatically when embedding it.
  543. #
  544. # See tests/application_development/gen_inc_file for an example of
  545. # usage.
  546. function(generate_inc_file
  547. source_file # The source file to be converted to hex
  548. generated_file # The generated file
  549. )
  550. add_custom_command(
  551. OUTPUT ${generated_file}
  552. COMMAND
  553. ${PYTHON_EXECUTABLE}
  554. ${ZEPHYR_BASE}/scripts/file2hex.py
  555. ${ARGN} # Extra arguments are passed to file2hex.py
  556. --file ${source_file}
  557. > ${generated_file} # Does pipe redirection work on Windows?
  558. DEPENDS ${source_file}
  559. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  560. )
  561. endfunction()
  562. function(generate_inc_file_for_gen_target
  563. target # The cmake target that depends on the generated file
  564. source_file # The source file to be converted to hex
  565. generated_file # The generated file
  566. gen_target # The generated file target we depend on
  567. # Any additional arguments are passed on to file2hex.py
  568. )
  569. generate_inc_file(${source_file} ${generated_file} ${ARGN})
  570. # Ensure 'generated_file' is generated before 'target' by creating a
  571. # dependency between the two targets
  572. add_dependencies(${target} ${gen_target})
  573. endfunction()
  574. function(generate_inc_file_for_target
  575. target # The cmake target that depends on the generated file
  576. source_file # The source file to be converted to hex
  577. generated_file # The generated file
  578. # Any additional arguments are passed on to file2hex.py
  579. )
  580. # Ensure 'generated_file' is generated before 'target' by creating a
  581. # 'custom_target' for it and setting up a dependency between the two
  582. # targets
  583. # But first create a unique name for the custom target
  584. generate_unique_target_name_from_filename(${generated_file} generated_target_name)
  585. add_custom_target(${generated_target_name} DEPENDS ${generated_file})
  586. generate_inc_file_for_gen_target(${target} ${source_file} ${generated_file} ${generated_target_name} ${ARGN})
  587. endfunction()
  588. # 1.4. board_*
  589. #
  590. # This section is for extensions related to Zephyr board handling.
  591. #
  592. # Zephyr board extensions current contains:
  593. # - Board runners
  594. # - Board revision
  595. # Zephyr board runners:
  596. # Zephyr board runner extension functions control Zephyr's board runners
  597. # from the build system. The Zephyr build system has targets for
  598. # flashing and debugging supported boards. These are wrappers around a
  599. # "runner" Python subpackage that is part of Zephyr's "west" tool.
  600. #
  601. # This section provides glue between CMake and the Python code that
  602. # manages the runners.
  603. function(_board_check_runner_type type) # private helper
  604. if (NOT (("${type}" STREQUAL "FLASH") OR ("${type}" STREQUAL "DEBUG")))
  605. message(FATAL_ERROR "invalid type ${type}; should be FLASH or DEBUG")
  606. endif()
  607. endfunction()
  608. # This function sets the runner for the board unconditionally. It's
  609. # meant to be used from application CMakeLists.txt files.
  610. #
  611. # NOTE: Usually board_set_xxx_ifnset() is best in board.cmake files.
  612. # This lets the user set the runner at cmake time, or in their
  613. # own application's CMakeLists.txt.
  614. #
  615. # Usage:
  616. # board_set_runner(FLASH pyocd)
  617. #
  618. # This would set the board's flash runner to "pyocd".
  619. #
  620. # In general, "type" is FLASH or DEBUG, and "runner" is the name of a
  621. # runner.
  622. function(board_set_runner type runner)
  623. _board_check_runner_type(${type})
  624. if (DEFINED BOARD_${type}_RUNNER)
  625. message(STATUS "overriding ${type} runner ${BOARD_${type}_RUNNER}; it's now ${runner}")
  626. endif()
  627. set(BOARD_${type}_RUNNER ${runner} PARENT_SCOPE)
  628. endfunction()
  629. # This macro is like board_set_runner(), but will only make a change
  630. # if that runner is currently not set.
  631. #
  632. # See also board_set_flasher_ifnset() and board_set_debugger_ifnset().
  633. macro(board_set_runner_ifnset type runner)
  634. _board_check_runner_type(${type})
  635. # This is a macro because set_ifndef() works at parent scope.
  636. # If this were a function, that would be this function's scope,
  637. # which wouldn't work.
  638. set_ifndef(BOARD_${type}_RUNNER ${runner})
  639. endmacro()
  640. # A convenience macro for board_set_runner(FLASH ${runner}).
  641. macro(board_set_flasher runner)
  642. board_set_runner(FLASH ${runner})
  643. endmacro()
  644. # A convenience macro for board_set_runner(DEBUG ${runner}).
  645. macro(board_set_debugger runner)
  646. board_set_runner(DEBUG ${runner})
  647. endmacro()
  648. # A convenience macro for board_set_runner_ifnset(FLASH ${runner}).
  649. macro(board_set_flasher_ifnset runner)
  650. board_set_runner_ifnset(FLASH ${runner})
  651. endmacro()
  652. # A convenience macro for board_set_runner_ifnset(DEBUG ${runner}).
  653. macro(board_set_debugger_ifnset runner)
  654. board_set_runner_ifnset(DEBUG ${runner})
  655. endmacro()
  656. # This function is intended for board.cmake files and application
  657. # CMakeLists.txt files.
  658. #
  659. # Usage from board.cmake files:
  660. # board_runner_args(runner "--some-arg=val1" "--another-arg=val2")
  661. #
  662. # The build system will then ensure the command line used to
  663. # create the runner contains:
  664. # --some-arg=val1 --another-arg=val2
  665. #
  666. # Within application CMakeLists.txt files, ensure that all calls to
  667. # board_runner_args() are part of a macro named app_set_runner_args(),
  668. # like this, which is defined before including the boilerplate file:
  669. # macro(app_set_runner_args)
  670. # board_runner_args(runner "--some-app-setting=value")
  671. # endmacro()
  672. #
  673. # The build system tests for the existence of the macro and will
  674. # invoke it at the appropriate time if it is defined.
  675. #
  676. # Any explicitly provided settings given by this function override
  677. # defaults provided by the build system.
  678. function(board_runner_args runner)
  679. string(MAKE_C_IDENTIFIER ${runner} runner_id)
  680. # Note the "_EXPLICIT_" here, and see below.
  681. set_property(GLOBAL APPEND PROPERTY BOARD_RUNNER_ARGS_EXPLICIT_${runner_id} ${ARGN})
  682. endfunction()
  683. # This function is intended for internal use by
  684. # boards/common/runner.board.cmake files.
  685. #
  686. # Basic usage:
  687. # board_finalize_runner_args(runner)
  688. #
  689. # This ensures the build system captures all arguments added in any
  690. # board_runner_args() calls, and otherwise finishes registering a
  691. # runner for use.
  692. #
  693. # Extended usage:
  694. # board_runner_args(runner "--some-arg=default-value")
  695. #
  696. # This provides common or default values for arguments. These are
  697. # placed before board_runner_args() calls, so they generally take
  698. # precedence, except for arguments which can be given multiple times
  699. # (use these with caution).
  700. function(board_finalize_runner_args runner)
  701. # If the application provided a macro to add additional runner
  702. # arguments, handle them.
  703. if(COMMAND app_set_runner_args)
  704. app_set_runner_args()
  705. endif()
  706. # Retrieve the list of explicitly set arguments.
  707. string(MAKE_C_IDENTIFIER ${runner} runner_id)
  708. get_property(explicit GLOBAL PROPERTY "BOARD_RUNNER_ARGS_EXPLICIT_${runner_id}")
  709. # Note no _EXPLICIT_ here. This property contains the final list.
  710. set_property(GLOBAL APPEND PROPERTY BOARD_RUNNER_ARGS_${runner_id}
  711. # Default arguments from the common runner file come first.
  712. ${ARGN}
  713. # Arguments explicitly given with board_runner_args() come
  714. # next, so they take precedence over the common runner file.
  715. ${explicit}
  716. # Arguments given via the CMake cache come last of all. Users
  717. # can provide variables in this way from the CMake command line.
  718. ${BOARD_RUNNER_ARGS_${runner_id}}
  719. )
  720. # Add the finalized runner to the global property list.
  721. set_property(GLOBAL APPEND PROPERTY ZEPHYR_RUNNERS ${runner})
  722. endfunction()
  723. # Zephyr board revision:
  724. #
  725. # This section provides a function for revision checking.
  726. # Usage:
  727. # board_check_revision(FORMAT <LETTER | MAJOR.MINOR.PATCH>
  728. # [EXACT]
  729. # [DEFAULT_REVISION <revision>]
  730. # [HIGHEST_REVISION <revision>]
  731. # )
  732. #
  733. # Zephyr board extension function.
  734. #
  735. # This function can be used in `boards/<board>/revision.cmake` to check a user
  736. # requested revision against available board revisions.
  737. #
  738. # The function will check the revision from `-DBOARD=<board>@<revision>` that
  739. # is provided by the user according to the arguments.
  740. # When `EXACT` is not specified, this function will set the Zephyr build system
  741. # variable `ACTIVE_BOARD_REVISION` with the selected revision.
  742. #
  743. # FORMAT <LETTER | MAJOR.MINOR.PATCH>: Specify the revision format.
  744. # LETTER: Revision format is a single letter from A - Z.
  745. # MAJOR.MINOR.PATCH: Revision format is three numbers, separated by `.`,
  746. # `x.y.z`. Trailing zeroes may be omitted on the
  747. # command line, which means:
  748. # 1.0.0 == 1.0 == 1
  749. #
  750. # EXACT: Revision is required to be an exact match. As example, available revisions are:
  751. # 0.1.0 and 0.3.0, and user provides 0.2.0, then an error is reported
  752. # when `EXACT` is given.
  753. # If `EXACT` is not provided, then closest lower revision will be selected
  754. # as the active revision, which in the example will be `0.1.0`.
  755. #
  756. # DEFAULT_REVISION: Provides a default revision to use when user has not selected
  757. # a revision number. If no default revision is provided then
  758. # user will be printed with an error if no revision is given
  759. # on the command line.
  760. #
  761. # HIGHEST_REVISION: Allows to specify highest valid revision for a board.
  762. # This can be used to ensure that a newer board cannot be used
  763. # with an older Zephyr. As example, if current board supports
  764. # revisions 0.x.0-0.99.99 and 1.0.0-1.99.99, and it is expected
  765. # that current board implementation will not work with board
  766. # revision 2.0.0, then HIGHEST_REVISION can be set to 1.99.99,
  767. # and user will be printed with an error if using
  768. # `<board>@2.0.0` or higher.
  769. # This field is not needed when `EXACT` is used.
  770. #
  771. # VALID_REVISIONS: A list of valid revisions for this board.
  772. # If this argument is not provided, then each Kconfig fragment
  773. # of the form ``<board>_<revision>.conf`` in the board folder
  774. # will be used as a valid revision for the board.
  775. #
  776. function(board_check_revision)
  777. set(options EXACT)
  778. set(single_args FORMAT DEFAULT_REVISION HIGHEST_REVISION)
  779. set(multi_args VALID_REVISIONS)
  780. cmake_parse_arguments(BOARD_REV "${options}" "${single_args}" "${multi_args}" ${ARGN})
  781. string(TOUPPER ${BOARD_REV_FORMAT} BOARD_REV_FORMAT)
  782. if(NOT DEFINED BOARD_REVISION)
  783. if(DEFINED BOARD_REV_DEFAULT_REVISION)
  784. set(BOARD_REVISION ${BOARD_REV_DEFAULT_REVISION})
  785. set(BOARD_REVISION ${BOARD_REVISION} PARENT_SCOPE)
  786. else()
  787. message(FATAL_ERROR "No board revision specified, Board: `${BOARD}` \
  788. requires a revision. Please use: `-DBOARD=${BOARD}@<revision>`")
  789. endif()
  790. endif()
  791. if(DEFINED BOARD_REV_HIGHEST_REVISION)
  792. if(((BOARD_REV_FORMAT STREQUAL LETTER) AND
  793. (BOARD_REVISION STRGREATER BOARD_REV_HIGHEST_REVISION)) OR
  794. ((BOARD_REV_FORMAT MATCHES "^MAJOR\.MINOR\.PATCH$") AND
  795. (BOARD_REVISION VERSION_GREATER BOARD_REV_HIGHEST_REVISION))
  796. )
  797. message(FATAL_ERROR "Board revision `${BOARD_REVISION}` greater than \
  798. highest supported revision `${BOARD_REV_HIGHEST_REVISION}`. \
  799. Please specify a valid board revision.")
  800. endif()
  801. endif()
  802. if(BOARD_REV_FORMAT STREQUAL LETTER)
  803. set(revision_regex "([A-Z])")
  804. elseif(BOARD_REV_FORMAT MATCHES "^MAJOR\.MINOR\.PATCH$")
  805. set(revision_regex "((0|[1-9][0-9]*)(\.[0-9]+)(\.[0-9]+))")
  806. # We allow loose <board>@<revision> typing on command line.
  807. # so append missing zeroes.
  808. if(BOARD_REVISION MATCHES "((0|[1-9][0-9]*)(\.[0-9]+)?(\.[0-9]+)?)")
  809. if(NOT CMAKE_MATCH_3)
  810. set(BOARD_REVISION ${BOARD_REVISION}.0)
  811. set(BOARD_REVISION ${BOARD_REVISION} PARENT_SCOPE)
  812. endif()
  813. if(NOT CMAKE_MATCH_4)
  814. set(BOARD_REVISION ${BOARD_REVISION}.0)
  815. set(BOARD_REVISION ${BOARD_REVISION} PARENT_SCOPE)
  816. endif()
  817. endif()
  818. else()
  819. message(FATAL_ERROR "Invalid format specified for \
  820. `board_check_revision(FORMAT <LETTER | MAJOR.MINOR.PATCH>)`")
  821. endif()
  822. if(NOT (BOARD_REVISION MATCHES "^${revision_regex}$"))
  823. message(FATAL_ERROR "Invalid revision format used for `${BOARD_REVISION}`. \
  824. Board `${BOARD}` uses revision format: ${BOARD_REV_FORMAT}.")
  825. endif()
  826. if(NOT DEFINED BOARD_REV_VALID_REVISIONS)
  827. file(GLOB revision_candidates LIST_DIRECTORIES false RELATIVE ${BOARD_DIR}
  828. ${BOARD_DIR}/${BOARD}_*.conf
  829. )
  830. string(REPLACE "." "_" underscore_revision_regex ${revision_regex})
  831. set(file_revision_regex "${BOARD}_${underscore_revision_regex}.conf")
  832. foreach(candidate ${revision_candidates})
  833. if(${candidate} MATCHES "${file_revision_regex}")
  834. string(REPLACE "_" "." FOUND_BOARD_REVISION ${CMAKE_MATCH_1})
  835. list(APPEND BOARD_REV_VALID_REVISIONS ${FOUND_BOARD_REVISION})
  836. endif()
  837. endforeach()
  838. endif()
  839. if(${BOARD_REVISION} IN_LIST BOARD_REV_VALID_REVISIONS)
  840. # Found exact match.
  841. return()
  842. endif()
  843. if(NOT BOARD_REV_EXACT)
  844. foreach(TEST_REVISION ${BOARD_REV_VALID_REVISIONS})
  845. if((BOARD_REV_FORMAT MATCHES "^MAJOR\.MINOR\.PATCH$") AND
  846. (${BOARD_REVISION} VERSION_GREATER_EQUAL ${TEST_REVISION}) AND
  847. (${TEST_REVISION} VERSION_GREATER_EQUAL "${ACTIVE_BOARD_REVISION}")
  848. )
  849. set(ACTIVE_BOARD_REVISION ${TEST_REVISION})
  850. elseif((BOARD_REV_FORMAT STREQUAL LETTER) AND
  851. (${BOARD_REVISION} STRGREATER ${TEST_REVISION}) AND
  852. (${TEST_REVISION} STRGREATER "${ACTIVE_BOARD_REVISION}")
  853. )
  854. set(ACTIVE_BOARD_REVISION ${TEST_REVISION})
  855. endif()
  856. endforeach()
  857. endif()
  858. if(BOARD_REV_EXACT OR NOT DEFINED ACTIVE_BOARD_REVISION)
  859. message(FATAL_ERROR "Board revision `${BOARD_REVISION}` for board \
  860. `${BOARD}` not found. Please specify a valid board revision.")
  861. endif()
  862. set(ACTIVE_BOARD_REVISION ${ACTIVE_BOARD_REVISION} PARENT_SCOPE)
  863. endfunction()
  864. # 1.5. Misc.
  865. # zephyr_check_compiler_flag is a part of Zephyr's toolchain
  866. # infrastructure. It should be used when testing toolchain
  867. # capabilities and it should normally be used in place of the
  868. # functions:
  869. #
  870. # check_compiler_flag
  871. # check_c_compiler_flag
  872. # check_cxx_compiler_flag
  873. #
  874. # See check_compiler_flag() for API documentation as it has the same
  875. # API.
  876. #
  877. # It is implemented as a wrapper on top of check_compiler_flag, which
  878. # again wraps the CMake-builtin's check_c_compiler_flag and
  879. # check_cxx_compiler_flag.
  880. #
  881. # It takes time to check for compatibility of flags against toolchains
  882. # so we cache the capability test results in USER_CACHE_DIR (This
  883. # caching comes in addition to the caching that CMake does in the
  884. # build folder's CMakeCache.txt)
  885. function(zephyr_check_compiler_flag lang option check)
  886. # Check if the option is covered by any hardcoded check before doing
  887. # an automated test.
  888. zephyr_check_compiler_flag_hardcoded(${lang} "${option}" check exists)
  889. if(exists)
  890. set(check ${check} PARENT_SCOPE)
  891. return()
  892. endif()
  893. # Locate the cache directory
  894. set_ifndef(
  895. ZEPHYR_TOOLCHAIN_CAPABILITY_CACHE_DIR
  896. ${USER_CACHE_DIR}/ToolchainCapabilityDatabase
  897. )
  898. # The toolchain capability database/cache is maintained as a
  899. # directory of files. The filenames in the directory are keys, and
  900. # the file contents are the values in this key-value store.
  901. # We need to create a unique key wrt. testing the toolchain
  902. # capability. This key must include everything that can affect the
  903. # toolchain test.
  904. #
  905. # Also, to fit the key into a filename we calculate the MD5 sum of
  906. # the key.
  907. # The 'cacheformat' must be bumped if a bug in the caching mechanism
  908. # is detected and all old keys must be invalidated.
  909. set(cacheformat 3)
  910. set(key_string "")
  911. set(key_string "${key_string}${cacheformat}_")
  912. set(key_string "${key_string}${TOOLCHAIN_SIGNATURE}_")
  913. set(key_string "${key_string}${lang}_")
  914. set(key_string "${key_string}${option}_")
  915. set(key_string "${key_string}${CMAKE_REQUIRED_FLAGS}_")
  916. string(MD5 key ${key_string})
  917. # Check the cache
  918. set(key_path ${ZEPHYR_TOOLCHAIN_CAPABILITY_CACHE_DIR}/${key})
  919. if(EXISTS ${key_path})
  920. file(READ
  921. ${key_path} # File to be read
  922. key_value # Output variable
  923. LIMIT 1 # Read at most 1 byte ('0' or '1')
  924. )
  925. set(${check} ${key_value} PARENT_SCOPE)
  926. return()
  927. endif()
  928. # Flags that start with -Wno-<warning> can not be tested by
  929. # check_compiler_flag, they will always pass, but -W<warning> can be
  930. # tested, so to test -Wno-<warning> flags we test -W<warning>
  931. # instead.
  932. if("${option}" MATCHES "-Wno-(.*)")
  933. set(possibly_translated_option -W${CMAKE_MATCH_1})
  934. else()
  935. set(possibly_translated_option ${option})
  936. endif()
  937. check_compiler_flag(${lang} "${possibly_translated_option}" inner_check)
  938. set(${check} ${inner_check} PARENT_SCOPE)
  939. # Populate the cache
  940. if(NOT (EXISTS ${key_path}))
  941. # This is racy. As often with race conditions, this one can easily be
  942. # made worse and demonstrated with a simple delay:
  943. # execute_process(COMMAND "sleep" "5")
  944. # Delete the cache, add the sleep above and run twister with a
  945. # large number of JOBS. Once it's done look at the log.txt file
  946. # below and you will see that concurrent cmake processes created the
  947. # same files multiple times.
  948. # While there are a number of reasons why this race seems both very
  949. # unlikely and harmless, let's play it safe anyway and write to a
  950. # private, temporary file first. All modern filesystems seem to
  951. # support at least one atomic rename API and cmake's file(RENAME
  952. # ...) officially leverages that.
  953. string(RANDOM LENGTH 8 tempsuffix)
  954. file(
  955. WRITE
  956. "${key_path}_tmp_${tempsuffix}"
  957. ${inner_check}
  958. )
  959. file(
  960. RENAME
  961. "${key_path}_tmp_${tempsuffix}" "${key_path}"
  962. )
  963. # Populate a metadata file (only intended for trouble shooting)
  964. # with information about the hash, the toolchain capability
  965. # result, and the toolchain test.
  966. file(
  967. APPEND
  968. ${ZEPHYR_TOOLCHAIN_CAPABILITY_CACHE_DIR}/log.txt
  969. "${inner_check} ${key} ${key_string}\n"
  970. )
  971. endif()
  972. endfunction()
  973. function(zephyr_check_compiler_flag_hardcoded lang option check exists)
  974. # Various flags that are not supported for CXX may not be testable
  975. # because they would produce a warning instead of an error during
  976. # the test. Exclude them by toolchain-specific blocklist.
  977. if((${lang} STREQUAL CXX) AND ("${option}" IN_LIST CXX_EXCLUDED_OPTIONS))
  978. set(check 0 PARENT_SCOPE)
  979. set(exists 1 PARENT_SCOPE)
  980. else()
  981. # There does not exist a hardcoded check for this option.
  982. set(exists 0 PARENT_SCOPE)
  983. endif()
  984. endfunction(zephyr_check_compiler_flag_hardcoded)
  985. # zephyr_linker_sources(<location> [SORT_KEY <sort_key>] <files>)
  986. #
  987. # <files> is one or more .ld formatted files whose contents will be
  988. # copied/included verbatim into the given <location> in the global linker.ld.
  989. # Preprocessor directives work inside <files>. Relative paths are resolved
  990. # relative to the calling file, like zephyr_sources().
  991. # <location> is one of
  992. # NOINIT Inside the noinit output section.
  993. # RWDATA Inside the data output section.
  994. # RODATA Inside the rodata output section.
  995. # ROM_START Inside the first output section of the image. This option is
  996. # currently only available on ARM Cortex-M, ARM Cortex-R,
  997. # x86, ARC, openisa_rv32m1, and RISC-V.
  998. # Note: On RISC-V the rom_start section will be after vector section.
  999. # RAM_SECTIONS Inside the RAMABLE_REGION GROUP, not initialized.
  1000. # DATA_SECTIONS Inside the RAMABLE_REGION GROUP, initialized.
  1001. # SECTIONS Near the end of the file. Don't use this when linking into
  1002. # RAMABLE_REGION, use RAM_SECTIONS instead.
  1003. # <sort_key> is an optional key to sort by inside of each location. The key must
  1004. # be alphanumeric, and the keys are sorted alphabetically. If no key is
  1005. # given, the key 'default' is used. Keys are case-sensitive.
  1006. #
  1007. # Use NOINIT, RWDATA, and RODATA unless they don't work for your use case.
  1008. #
  1009. # When placing into NOINIT, RWDATA, RODATA, ROM_START, the contents of the files
  1010. # will be placed inside an output section, so assume the section definition is
  1011. # already present, e.g.:
  1012. # _mysection_start = .;
  1013. # KEEP(*(.mysection));
  1014. # _mysection_end = .;
  1015. # _mysection_size = ABSOLUTE(_mysection_end - _mysection_start);
  1016. #
  1017. # When placing into SECTIONS, RAM_SECTIONS or DATA_SECTIONS, the files must
  1018. # instead define their own output sections to achieve the same thing:
  1019. # SECTION_PROLOGUE(.mysection,,)
  1020. # {
  1021. # _mysection_start = .;
  1022. # KEEP(*(.mysection))
  1023. # _mysection_end = .;
  1024. # } GROUP_LINK_IN(ROMABLE_REGION)
  1025. # _mysection_size = _mysection_end - _mysection_start;
  1026. #
  1027. # Note about the above examples: If the first example was used with RODATA, and
  1028. # the second with SECTIONS, the two examples do the same thing from a user
  1029. # perspective.
  1030. #
  1031. # Friendly reminder: Beware of the different ways the location counter ('.')
  1032. # behaves inside vs. outside section definitions.
  1033. function(zephyr_linker_sources location)
  1034. # Set up the paths to the destination files. These files are #included inside
  1035. # the global linker.ld.
  1036. set(snippet_base "${__build_dir}/include/generated")
  1037. set(sections_path "${snippet_base}/snippets-sections.ld")
  1038. set(ram_sections_path "${snippet_base}/snippets-ram-sections.ld")
  1039. set(data_sections_path "${snippet_base}/snippets-data-sections.ld")
  1040. set(rom_start_path "${snippet_base}/snippets-rom-start.ld")
  1041. set(noinit_path "${snippet_base}/snippets-noinit.ld")
  1042. set(rwdata_path "${snippet_base}/snippets-rwdata.ld")
  1043. set(rodata_path "${snippet_base}/snippets-rodata.ld")
  1044. # Clear destination files if this is the first time the function is called.
  1045. get_property(cleared GLOBAL PROPERTY snippet_files_cleared)
  1046. if (NOT DEFINED cleared)
  1047. file(WRITE ${sections_path} "")
  1048. file(WRITE ${ram_sections_path} "")
  1049. file(WRITE ${data_sections_path} "")
  1050. file(WRITE ${rom_start_path} "")
  1051. file(WRITE ${noinit_path} "")
  1052. file(WRITE ${rwdata_path} "")
  1053. file(WRITE ${rodata_path} "")
  1054. set_property(GLOBAL PROPERTY snippet_files_cleared true)
  1055. endif()
  1056. # Choose destination file, based on the <location> argument.
  1057. if ("${location}" STREQUAL "SECTIONS")
  1058. set(snippet_path "${sections_path}")
  1059. elseif("${location}" STREQUAL "RAM_SECTIONS")
  1060. set(snippet_path "${ram_sections_path}")
  1061. elseif("${location}" STREQUAL "DATA_SECTIONS")
  1062. set(snippet_path "${data_sections_path}")
  1063. elseif("${location}" STREQUAL "ROM_START")
  1064. set(snippet_path "${rom_start_path}")
  1065. elseif("${location}" STREQUAL "NOINIT")
  1066. set(snippet_path "${noinit_path}")
  1067. elseif("${location}" STREQUAL "RWDATA")
  1068. set(snippet_path "${rwdata_path}")
  1069. elseif("${location}" STREQUAL "RODATA")
  1070. set(snippet_path "${rodata_path}")
  1071. else()
  1072. message(fatal_error "Must choose valid location for linker snippet.")
  1073. endif()
  1074. cmake_parse_arguments(L "" "SORT_KEY" "" ${ARGN})
  1075. set(SORT_KEY default)
  1076. if(DEFINED L_SORT_KEY)
  1077. set(SORT_KEY ${L_SORT_KEY})
  1078. endif()
  1079. foreach(file IN ITEMS ${L_UNPARSED_ARGUMENTS})
  1080. # Resolve path.
  1081. if(IS_ABSOLUTE ${file})
  1082. set(path ${file})
  1083. else()
  1084. set(path ${CMAKE_CURRENT_SOURCE_DIR}/${file})
  1085. endif()
  1086. if(IS_DIRECTORY ${path})
  1087. message(FATAL_ERROR "zephyr_linker_sources() was called on a directory")
  1088. endif()
  1089. # Find the relative path to the linker file from the include folder.
  1090. file(RELATIVE_PATH relpath ${ZEPHYR_BASE}/include ${path})
  1091. # Create strings to be written into the file
  1092. set (include_str "/* Sort key: \"${SORT_KEY}\" */#include \"${relpath}\"")
  1093. # Add new line to existing lines, sort them, and write them back.
  1094. file(STRINGS ${snippet_path} lines) # Get current lines (without newlines).
  1095. list(APPEND lines ${include_str})
  1096. list(SORT lines)
  1097. string(REPLACE ";" "\n;" lines "${lines}") # Add newline to each line.
  1098. file(WRITE ${snippet_path} ${lines} "\n")
  1099. endforeach()
  1100. endfunction(zephyr_linker_sources)
  1101. # Helper function for CONFIG_CODE_DATA_RELOCATION
  1102. # Call this function with 2 arguments file and then memory location
  1103. function(zephyr_code_relocate file location)
  1104. if(NOT IS_ABSOLUTE ${file})
  1105. set(file ${CMAKE_CURRENT_SOURCE_DIR}/${file})
  1106. endif()
  1107. set_property(TARGET code_data_relocation_target
  1108. APPEND PROPERTY COMPILE_DEFINITIONS
  1109. "${location}:${file}")
  1110. endfunction()
  1111. # Usage:
  1112. # check_dtc_flag("-Wtest" DTC_WARN_TEST)
  1113. #
  1114. # Writes 1 to the output variable 'ok' if
  1115. # the flag is supported, otherwise writes 0.
  1116. #
  1117. # using
  1118. function(check_dtc_flag flag ok)
  1119. execute_process(
  1120. COMMAND
  1121. ${DTC} ${flag} -v
  1122. ERROR_QUIET
  1123. OUTPUT_QUIET
  1124. RESULT_VARIABLE dtc_check_ret
  1125. )
  1126. if (dtc_check_ret EQUAL 0)
  1127. set(${ok} 1 PARENT_SCOPE)
  1128. else()
  1129. set(${ok} 0 PARENT_SCOPE)
  1130. endif()
  1131. endfunction()
  1132. # Function to round number to next power of two.
  1133. #
  1134. # Usage:
  1135. # pow2round(<variable>)
  1136. #
  1137. # Example:
  1138. # set(test 2)
  1139. # pow2round(test)
  1140. # # test is still 2
  1141. #
  1142. # set(test 5)
  1143. # pow2round(test)
  1144. # # test is now 8
  1145. #
  1146. # Arguments:
  1147. # n = Variable containing the number to round
  1148. function(pow2round n)
  1149. math(EXPR x "${${n}} & (${${n}} - 1)")
  1150. if(${x} EQUAL 0)
  1151. return()
  1152. endif()
  1153. math(EXPR ${n} "${${n}} | (${${n}} >> 1)")
  1154. math(EXPR ${n} "${${n}} | (${${n}} >> 2)")
  1155. math(EXPR ${n} "${${n}} | (${${n}} >> 4)")
  1156. math(EXPR ${n} "${${n}} | (${${n}} >> 8)")
  1157. math(EXPR ${n} "${${n}} | (${${n}} >> 16)")
  1158. math(EXPR ${n} "${${n}} | (${${n}} >> 32)")
  1159. math(EXPR ${n} "${${n}} + 1")
  1160. set(${n} ${${n}} PARENT_SCOPE)
  1161. endfunction()
  1162. ########################################################
  1163. # 2. Kconfig-aware extensions
  1164. ########################################################
  1165. #
  1166. # Kconfig is a configuration language developed for the Linux
  1167. # kernel. The below functions integrate CMake with Kconfig.
  1168. #
  1169. # 2.1 Misc
  1170. #
  1171. # import_kconfig(<prefix> <kconfig_fragment> [<keys>])
  1172. #
  1173. # Parse a KConfig fragment (typically with extension .config) and
  1174. # introduce all the symbols that are prefixed with 'prefix' into the
  1175. # CMake namespace. List all created variable names in the 'keys'
  1176. # output variable if present.
  1177. function(import_kconfig prefix kconfig_fragment)
  1178. # Parse the lines prefixed with 'prefix' in ${kconfig_fragment}
  1179. file(
  1180. STRINGS
  1181. ${kconfig_fragment}
  1182. DOT_CONFIG_LIST
  1183. REGEX "^${prefix}"
  1184. ENCODING "UTF-8"
  1185. )
  1186. foreach (CONFIG ${DOT_CONFIG_LIST})
  1187. # CONFIG could look like: CONFIG_NET_BUF=y
  1188. # Match the first part, the variable name
  1189. string(REGEX MATCH "[^=]+" CONF_VARIABLE_NAME ${CONFIG})
  1190. # Match the second part, variable value
  1191. string(REGEX MATCH "=(.+$)" CONF_VARIABLE_VALUE ${CONFIG})
  1192. # The variable name match we just did included the '=' symbol. To just get the
  1193. # part on the RHS we use match group 1
  1194. set(CONF_VARIABLE_VALUE ${CMAKE_MATCH_1})
  1195. if("${CONF_VARIABLE_VALUE}" MATCHES "^\"(.*)\"$") # Is surrounded by quotes
  1196. set(CONF_VARIABLE_VALUE ${CMAKE_MATCH_1})
  1197. endif()
  1198. set("${CONF_VARIABLE_NAME}" "${CONF_VARIABLE_VALUE}" PARENT_SCOPE)
  1199. list(APPEND keys "${CONF_VARIABLE_NAME}")
  1200. endforeach()
  1201. foreach(outvar ${ARGN})
  1202. set(${outvar} "${keys}" PARENT_SCOPE)
  1203. endforeach()
  1204. endfunction()
  1205. ########################################################
  1206. # 3. CMake-generic extensions
  1207. ########################################################
  1208. #
  1209. # These functions extend the CMake API in a way that is not particular
  1210. # to Zephyr. Primarily they work around limitations in the CMake
  1211. # language to allow cleaner build scripts.
  1212. # 3.1. *_ifdef
  1213. #
  1214. # Functions for conditionally executing CMake functions with oneliners
  1215. # e.g.
  1216. #
  1217. # if(CONFIG_FFT)
  1218. # zephyr_library_source(
  1219. # fft_32.c
  1220. # fft_utils.c
  1221. # )
  1222. # endif()
  1223. #
  1224. # Becomes
  1225. #
  1226. # zephyr_source_ifdef(
  1227. # CONFIG_FFT
  1228. # fft_32.c
  1229. # fft_utils.c
  1230. # )
  1231. #
  1232. # More Generally
  1233. # "<function-name>_ifdef(CONDITION args)"
  1234. # Becomes
  1235. # """
  1236. # if(CONDITION)
  1237. # <function-name>(args)
  1238. # endif()
  1239. # """
  1240. #
  1241. # ifdef functions are added on an as-need basis. See
  1242. # https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html for
  1243. # a list of available functions.
  1244. function(add_subdirectory_ifdef feature_toggle source_dir)
  1245. if(${${feature_toggle}})
  1246. add_subdirectory(${source_dir} ${ARGN})
  1247. endif()
  1248. endfunction()
  1249. function(target_sources_ifdef feature_toggle target scope item)
  1250. if(${${feature_toggle}})
  1251. target_sources(${target} ${scope} ${item} ${ARGN})
  1252. endif()
  1253. endfunction()
  1254. function(target_compile_definitions_ifdef feature_toggle target scope item)
  1255. if(${${feature_toggle}})
  1256. target_compile_definitions(${target} ${scope} ${item} ${ARGN})
  1257. endif()
  1258. endfunction()
  1259. function(target_include_directories_ifdef feature_toggle target scope item)
  1260. if(${${feature_toggle}})
  1261. target_include_directories(${target} ${scope} ${item} ${ARGN})
  1262. endif()
  1263. endfunction()
  1264. function(target_link_libraries_ifdef feature_toggle target item)
  1265. if(${${feature_toggle}})
  1266. target_link_libraries(${target} ${item} ${ARGN})
  1267. endif()
  1268. endfunction()
  1269. function(add_compile_option_ifdef feature_toggle option)
  1270. if(${${feature_toggle}})
  1271. add_compile_options(${option})
  1272. endif()
  1273. endfunction()
  1274. function(target_compile_option_ifdef feature_toggle target scope option)
  1275. if(${feature_toggle})
  1276. target_compile_options(${target} ${scope} ${option})
  1277. endif()
  1278. endfunction()
  1279. function(target_cc_option_ifdef feature_toggle target scope option)
  1280. if(${feature_toggle})
  1281. target_cc_option(${target} ${scope} ${option})
  1282. endif()
  1283. endfunction()
  1284. function(zephyr_library_sources_ifdef feature_toggle source)
  1285. if(${${feature_toggle}})
  1286. zephyr_library_sources(${source} ${ARGN})
  1287. endif()
  1288. endfunction()
  1289. function(zephyr_sources_ifdef feature_toggle)
  1290. if(${${feature_toggle}})
  1291. zephyr_sources(${ARGN})
  1292. endif()
  1293. endfunction()
  1294. function(zephyr_cc_option_ifdef feature_toggle)
  1295. if(${${feature_toggle}})
  1296. zephyr_cc_option(${ARGN})
  1297. endif()
  1298. endfunction()
  1299. function(zephyr_ld_option_ifdef feature_toggle)
  1300. if(${${feature_toggle}})
  1301. zephyr_ld_options(${ARGN})
  1302. endif()
  1303. endfunction()
  1304. function(zephyr_link_libraries_ifdef feature_toggle)
  1305. if(${${feature_toggle}})
  1306. zephyr_link_libraries(${ARGN})
  1307. endif()
  1308. endfunction()
  1309. function(zephyr_compile_options_ifdef feature_toggle)
  1310. if(${${feature_toggle}})
  1311. zephyr_compile_options(${ARGN})
  1312. endif()
  1313. endfunction()
  1314. function(zephyr_compile_definitions_ifdef feature_toggle)
  1315. if(${${feature_toggle}})
  1316. zephyr_compile_definitions(${ARGN})
  1317. endif()
  1318. endfunction()
  1319. function(zephyr_include_directories_ifdef feature_toggle)
  1320. if(${${feature_toggle}})
  1321. zephyr_include_directories(${ARGN})
  1322. endif()
  1323. endfunction()
  1324. function(zephyr_library_compile_definitions_ifdef feature_toggle item)
  1325. if(${${feature_toggle}})
  1326. zephyr_library_compile_definitions(${item} ${ARGN})
  1327. endif()
  1328. endfunction()
  1329. function(zephyr_library_include_directories_ifdef feature_toggle)
  1330. if(${${feature_toggle}})
  1331. zephyr_library_include_directories(${ARGN})
  1332. endif()
  1333. endfunction()
  1334. function(zephyr_library_compile_options_ifdef feature_toggle item)
  1335. if(${${feature_toggle}})
  1336. zephyr_library_compile_options(${item} ${ARGN})
  1337. endif()
  1338. endfunction()
  1339. function(zephyr_link_interface_ifdef feature_toggle interface)
  1340. if(${${feature_toggle}})
  1341. target_link_libraries(${interface} INTERFACE zephyr_interface)
  1342. endif()
  1343. endfunction()
  1344. function(zephyr_library_link_libraries_ifdef feature_toggle item)
  1345. if(${${feature_toggle}})
  1346. zephyr_library_link_libraries(${item})
  1347. endif()
  1348. endfunction()
  1349. function(zephyr_linker_sources_ifdef feature_toggle)
  1350. if(${${feature_toggle}})
  1351. zephyr_linker_sources(${ARGN})
  1352. endif()
  1353. endfunction()
  1354. macro(list_append_ifdef feature_toggle list)
  1355. if(${${feature_toggle}})
  1356. list(APPEND ${list} ${ARGN})
  1357. endif()
  1358. endmacro()
  1359. # 3.2. *_ifndef
  1360. # See 3.1 *_ifdef
  1361. function(set_ifndef variable value)
  1362. if(NOT ${variable})
  1363. set(${variable} ${value} ${ARGN} PARENT_SCOPE)
  1364. endif()
  1365. endfunction()
  1366. function(add_subdirectory_ifndef feature_toggle source_dir)
  1367. if(NOT ${feature_toggle})
  1368. add_subdirectory(${source_dir} ${ARGN})
  1369. endif()
  1370. endfunction()
  1371. function(target_sources_ifndef feature_toggle target scope item)
  1372. if(NOT ${feature_toggle})
  1373. target_sources(${target} ${scope} ${item} ${ARGN})
  1374. endif()
  1375. endfunction()
  1376. function(target_compile_definitions_ifndef feature_toggle target scope item)
  1377. if(NOT ${feature_toggle})
  1378. target_compile_definitions(${target} ${scope} ${item} ${ARGN})
  1379. endif()
  1380. endfunction()
  1381. function(target_include_directories_ifndef feature_toggle target scope item)
  1382. if(NOT ${feature_toggle})
  1383. target_include_directories(${target} ${scope} ${item} ${ARGN})
  1384. endif()
  1385. endfunction()
  1386. function(target_link_libraries_ifndef feature_toggle target item)
  1387. if(NOT ${feature_toggle})
  1388. target_link_libraries(${target} ${item} ${ARGN})
  1389. endif()
  1390. endfunction()
  1391. function(add_compile_option_ifndef feature_toggle option)
  1392. if(NOT ${feature_toggle})
  1393. add_compile_options(${option})
  1394. endif()
  1395. endfunction()
  1396. function(target_compile_option_ifndef feature_toggle target scope option)
  1397. if(NOT ${feature_toggle})
  1398. target_compile_options(${target} ${scope} ${option})
  1399. endif()
  1400. endfunction()
  1401. function(target_cc_option_ifndef feature_toggle target scope option)
  1402. if(NOT ${feature_toggle})
  1403. target_cc_option(${target} ${scope} ${option})
  1404. endif()
  1405. endfunction()
  1406. function(zephyr_library_sources_ifndef feature_toggle source)
  1407. if(NOT ${feature_toggle})
  1408. zephyr_library_sources(${source} ${ARGN})
  1409. endif()
  1410. endfunction()
  1411. function(zephyr_sources_ifndef feature_toggle)
  1412. if(NOT ${feature_toggle})
  1413. zephyr_sources(${ARGN})
  1414. endif()
  1415. endfunction()
  1416. function(zephyr_cc_option_ifndef feature_toggle)
  1417. if(NOT ${feature_toggle})
  1418. zephyr_cc_option(${ARGN})
  1419. endif()
  1420. endfunction()
  1421. function(zephyr_ld_option_ifndef feature_toggle)
  1422. if(NOT ${feature_toggle})
  1423. zephyr_ld_options(${ARGN})
  1424. endif()
  1425. endfunction()
  1426. function(zephyr_link_libraries_ifndef feature_toggle)
  1427. if(NOT ${feature_toggle})
  1428. zephyr_link_libraries(${ARGN})
  1429. endif()
  1430. endfunction()
  1431. function(zephyr_compile_options_ifndef feature_toggle)
  1432. if(NOT ${feature_toggle})
  1433. zephyr_compile_options(${ARGN})
  1434. endif()
  1435. endfunction()
  1436. function(zephyr_compile_definitions_ifndef feature_toggle)
  1437. if(NOT ${feature_toggle})
  1438. zephyr_compile_definitions(${ARGN})
  1439. endif()
  1440. endfunction()
  1441. function(zephyr_include_directories_ifndef feature_toggle)
  1442. if(NOT ${feature_toggle})
  1443. zephyr_include_directories(${ARGN})
  1444. endif()
  1445. endfunction()
  1446. function(zephyr_library_compile_definitions_ifndef feature_toggle item)
  1447. if(NOT ${feature_toggle})
  1448. zephyr_library_compile_definitions(${item} ${ARGN})
  1449. endif()
  1450. endfunction()
  1451. function(zephyr_library_include_directories_ifndef feature_toggle)
  1452. if(NOT ${feature_toggle})
  1453. zephyr_library_include_directories(${ARGN})
  1454. endif()
  1455. endfunction()
  1456. function(zephyr_library_compile_options_ifndef feature_toggle item)
  1457. if(NOT ${feature_toggle})
  1458. zephyr_library_compile_options(${item} ${ARGN})
  1459. endif()
  1460. endfunction()
  1461. function(zephyr_link_interface_ifndef feature_toggle interface)
  1462. if(NOT ${feature_toggle})
  1463. target_link_libraries(${interface} INTERFACE zephyr_interface)
  1464. endif()
  1465. endfunction()
  1466. function(zephyr_library_link_libraries_ifndef feature_toggle item)
  1467. if(NOT ${feature_toggle})
  1468. zephyr_library_link_libraries(${item})
  1469. endif()
  1470. endfunction()
  1471. function(zephyr_linker_sources_ifndef feature_toggle)
  1472. if(NOT ${feature_toggle})
  1473. zephyr_linker_sources(${ARGN})
  1474. endif()
  1475. endfunction()
  1476. macro(list_append_ifndef feature_toggle list)
  1477. if(NOT ${feature_toggle})
  1478. list(APPEND ${list} ${ARGN})
  1479. endif()
  1480. endmacro()
  1481. # 3.3. *_option Compiler-compatibility checks
  1482. #
  1483. # Utility functions for silently omitting compiler flags when the
  1484. # compiler lacks support. *_cc_option was ported from KBuild, see
  1485. # cc-option in
  1486. # https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt
  1487. # Writes 1 to the output variable 'ok' for the language 'lang' if
  1488. # the flag is supported, otherwise writes 0.
  1489. #
  1490. # lang must be C or CXX
  1491. #
  1492. # TODO: Support ASM
  1493. #
  1494. # Usage:
  1495. #
  1496. # check_compiler_flag(C "-Wall" my_check)
  1497. # print(my_check) # my_check is now 1
  1498. function(check_compiler_flag lang option ok)
  1499. if(NOT DEFINED CMAKE_REQUIRED_QUIET)
  1500. set(CMAKE_REQUIRED_QUIET 1)
  1501. endif()
  1502. string(MAKE_C_IDENTIFIER
  1503. check${option}_${lang}_${CMAKE_REQUIRED_FLAGS}
  1504. ${ok}
  1505. )
  1506. if(${lang} STREQUAL C)
  1507. check_c_compiler_flag("${option}" ${${ok}})
  1508. else()
  1509. check_cxx_compiler_flag("${option}" ${${ok}})
  1510. endif()
  1511. if(${${${ok}}})
  1512. set(ret 1)
  1513. else()
  1514. set(ret 0)
  1515. endif()
  1516. set(${ok} ${ret} PARENT_SCOPE)
  1517. endfunction()
  1518. function(target_cc_option target scope option)
  1519. target_cc_option_fallback(${target} ${scope} ${option} "")
  1520. endfunction()
  1521. # Support an optional second option for when the first option is not
  1522. # supported.
  1523. function(target_cc_option_fallback target scope option1 option2)
  1524. if(CONFIG_CPLUSPLUS)
  1525. foreach(lang C CXX)
  1526. # For now, we assume that all flags that apply to C/CXX also
  1527. # apply to ASM.
  1528. zephyr_check_compiler_flag(${lang} ${option1} check)
  1529. if(${check})
  1530. target_compile_options(${target} ${scope}
  1531. $<$<COMPILE_LANGUAGE:${lang}>:${option1}>
  1532. $<$<COMPILE_LANGUAGE:ASM>:${option1}>
  1533. )
  1534. elseif(option2)
  1535. target_compile_options(${target} ${scope}
  1536. $<$<COMPILE_LANGUAGE:${lang}>:${option2}>
  1537. $<$<COMPILE_LANGUAGE:ASM>:${option2}>
  1538. )
  1539. endif()
  1540. endforeach()
  1541. else()
  1542. zephyr_check_compiler_flag(C ${option1} check)
  1543. if(${check})
  1544. target_compile_options(${target} ${scope} ${option1})
  1545. elseif(option2)
  1546. target_compile_options(${target} ${scope} ${option2})
  1547. endif()
  1548. endif()
  1549. endfunction()
  1550. function(target_ld_options target scope)
  1551. zephyr_get_parse_args(args ${ARGN})
  1552. list(REMOVE_ITEM ARGN NO_SPLIT)
  1553. foreach(option ${ARGN})
  1554. if(args_NO_SPLIT)
  1555. set(option ${ARGN})
  1556. endif()
  1557. string(JOIN "" check_identifier "check" ${option})
  1558. string(MAKE_C_IDENTIFIER ${check_identifier} check)
  1559. set(SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
  1560. string(JOIN " " CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${option})
  1561. zephyr_check_compiler_flag(C "" ${check})
  1562. set(CMAKE_REQUIRED_FLAGS ${SAVED_CMAKE_REQUIRED_FLAGS})
  1563. target_link_libraries_ifdef(${check} ${target} ${scope} ${option})
  1564. if(args_NO_SPLIT)
  1565. break()
  1566. endif()
  1567. endforeach()
  1568. endfunction()
  1569. # 3.3.1 Toolchain integration
  1570. #
  1571. # 'toolchain_parse_make_rule' is a function that parses the output of
  1572. # 'gcc -M'.
  1573. #
  1574. # The argument 'input_file' is in input parameter with the path to the
  1575. # file with the dependency information.
  1576. #
  1577. # The argument 'include_files' is an output parameter with the result
  1578. # of parsing the include files.
  1579. function(toolchain_parse_make_rule input_file include_files)
  1580. file(STRINGS ${input_file} input)
  1581. # The file is formatted like this:
  1582. # empty_file.o: misc/empty_file.c \
  1583. # nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts \
  1584. # nrf52840_qiaa.dtsi
  1585. # The dep file will contain `\` for line continuation.
  1586. # This results in `\;` which is then treated a the char `;` instead of
  1587. # the element separator, so let's get the pure `;` back.
  1588. string(REPLACE "\;" ";" input_as_list ${input})
  1589. # Pop the first line and treat it specially
  1590. list(POP_FRONT input_as_list first_input_line)
  1591. string(FIND ${first_input_line} ": " index)
  1592. math(EXPR j "${index} + 2")
  1593. string(SUBSTRING ${first_input_line} ${j} -1 first_include_file)
  1594. # Remove whitespace before and after filename and convert to CMake path.
  1595. string(STRIP "${first_include_file}" first_include_file)
  1596. file(TO_CMAKE_PATH "${first_include_file}" first_include_file)
  1597. set(result "${first_include_file}")
  1598. # Remove whitespace before and after filename and convert to CMake path.
  1599. foreach(file ${input_as_list})
  1600. string(STRIP "${file}" file)
  1601. file(TO_CMAKE_PATH "${file}" file)
  1602. list(APPEND result "${file}")
  1603. endforeach()
  1604. set(${include_files} ${result} PARENT_SCOPE)
  1605. endfunction()
  1606. # 'check_set_linker_property' is a function that check the provided linker
  1607. # flag and only set the linker property if the check succeeds
  1608. #
  1609. # This function is similar in nature to the CMake set_property function, but
  1610. # with the extension that it will check that the linker supports the flag before
  1611. # setting the property.
  1612. #
  1613. # APPEND: Flag indicated that the property should be appended to the existing
  1614. # value list for the property.
  1615. # TARGET: Name of target on which to add the property (commonly: linker)
  1616. # PROPERTY: Name of property with the value(s) following immediately after
  1617. # property name
  1618. function(check_set_linker_property)
  1619. set(options APPEND)
  1620. set(single_args TARGET)
  1621. set(multi_args PROPERTY)
  1622. cmake_parse_arguments(LINKER_PROPERTY "${options}" "${single_args}" "${multi_args}" ${ARGN})
  1623. if(LINKER_PROPERTY_APPEND)
  1624. set(APPEND "APPEND")
  1625. endif()
  1626. list(GET LINKER_PROPERTY_PROPERTY 0 property)
  1627. list(REMOVE_AT LINKER_PROPERTY_PROPERTY 0)
  1628. set(option ${LINKER_PROPERTY_PROPERTY})
  1629. string(MAKE_C_IDENTIFIER check${option} check)
  1630. set(SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
  1631. set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${option}")
  1632. zephyr_check_compiler_flag(C "" ${check})
  1633. set(CMAKE_REQUIRED_FLAGS ${SAVED_CMAKE_REQUIRED_FLAGS})
  1634. if(${check})
  1635. set_property(TARGET ${LINKER_PROPERTY_TARGET} ${APPEND} PROPERTY ${property} ${option})
  1636. endif()
  1637. endfunction()
  1638. # 'set_compiler_property' is a function that sets the property for the C and
  1639. # C++ property targets used for toolchain abstraction.
  1640. #
  1641. # This function is similar in nature to the CMake set_property function, but
  1642. # with the extension that it will set the property on both the compile and
  1643. # compiler-cpp targets.
  1644. #
  1645. # APPEND: Flag indicated that the property should be appended to the existing
  1646. # value list for the property.
  1647. # PROPERTY: Name of property with the value(s) following immediately after
  1648. # property name
  1649. function(set_compiler_property)
  1650. set(options APPEND)
  1651. set(multi_args PROPERTY)
  1652. cmake_parse_arguments(COMPILER_PROPERTY "${options}" "${single_args}" "${multi_args}" ${ARGN})
  1653. if(COMPILER_PROPERTY_APPEND)
  1654. set(APPEND "APPEND")
  1655. set(APPEND-CPP "APPEND")
  1656. endif()
  1657. set_property(TARGET compiler ${APPEND} PROPERTY ${COMPILER_PROPERTY_PROPERTY})
  1658. set_property(TARGET compiler-cpp ${APPEND} PROPERTY ${COMPILER_PROPERTY_PROPERTY})
  1659. endfunction()
  1660. # 'check_set_compiler_property' is a function that check the provided compiler
  1661. # flag and only set the compiler or compiler-cpp property if the check succeeds
  1662. #
  1663. # This function is similar in nature to the CMake set_property function, but
  1664. # with the extension that it will check that the compiler supports the flag
  1665. # before setting the property on compiler or compiler-cpp targets.
  1666. #
  1667. # APPEND: Flag indicated that the property should be appended to the existing
  1668. # value list for the property.
  1669. # PROPERTY: Name of property with the value(s) following immediately after
  1670. # property name
  1671. function(check_set_compiler_property)
  1672. set(options APPEND)
  1673. set(multi_args PROPERTY)
  1674. cmake_parse_arguments(COMPILER_PROPERTY "${options}" "${single_args}" "${multi_args}" ${ARGN})
  1675. if(COMPILER_PROPERTY_APPEND)
  1676. set(APPEND "APPEND")
  1677. set(APPEND-CPP "APPEND")
  1678. endif()
  1679. list(GET COMPILER_PROPERTY_PROPERTY 0 property)
  1680. list(REMOVE_AT COMPILER_PROPERTY_PROPERTY 0)
  1681. foreach(option ${COMPILER_PROPERTY_PROPERTY})
  1682. if(CONFIG_CPLUSPLUS)
  1683. zephyr_check_compiler_flag(CXX ${option} check)
  1684. if(${check})
  1685. set_property(TARGET compiler-cpp ${APPEND-CPP} PROPERTY ${property} ${option})
  1686. set(APPEND-CPP "APPEND")
  1687. endif()
  1688. endif()
  1689. zephyr_check_compiler_flag(C ${option} check)
  1690. if(${check})
  1691. set_property(TARGET compiler ${APPEND} PROPERTY ${property} ${option})
  1692. set(APPEND "APPEND")
  1693. endif()
  1694. endforeach()
  1695. endfunction()
  1696. # 3.4. Debugging CMake
  1697. # Usage:
  1698. # print(BOARD)
  1699. #
  1700. # will print: "BOARD: nrf52dk_nrf52832"
  1701. function(print arg)
  1702. message(STATUS "${arg}: ${${arg}}")
  1703. endfunction()
  1704. # Usage:
  1705. # assert(ZEPHYR_TOOLCHAIN_VARIANT "ZEPHYR_TOOLCHAIN_VARIANT not set.")
  1706. #
  1707. # will cause a FATAL_ERROR and print an error message if the first
  1708. # expression is false
  1709. macro(assert test comment)
  1710. if(NOT ${test})
  1711. message(FATAL_ERROR "Assertion failed: ${comment}")
  1712. endif()
  1713. endmacro()
  1714. # Usage:
  1715. # assert_not(OBSOLETE_VAR "OBSOLETE_VAR has been removed; use NEW_VAR instead")
  1716. #
  1717. # will cause a FATAL_ERROR and print an error message if the first
  1718. # expression is true
  1719. macro(assert_not test comment)
  1720. if(${test})
  1721. message(FATAL_ERROR "Assertion failed: ${comment}")
  1722. endif()
  1723. endmacro()
  1724. # Usage:
  1725. # assert_exists(CMAKE_READELF)
  1726. #
  1727. # will cause a FATAL_ERROR if there is no file or directory behind the
  1728. # variable
  1729. macro(assert_exists var)
  1730. if(NOT EXISTS ${${var}})
  1731. message(FATAL_ERROR "No such file or directory: ${var}: '${${var}}'")
  1732. endif()
  1733. endmacro()
  1734. # 3.5. File system management
  1735. function(check_if_directory_is_writeable dir ok)
  1736. execute_process(
  1737. COMMAND
  1738. ${PYTHON_EXECUTABLE}
  1739. ${ZEPHYR_BASE}/scripts/dir_is_writeable.py
  1740. ${dir}
  1741. RESULT_VARIABLE ret
  1742. )
  1743. if("${ret}" STREQUAL "0")
  1744. # The directory is write-able
  1745. set(${ok} 1 PARENT_SCOPE)
  1746. else()
  1747. set(${ok} 0 PARENT_SCOPE)
  1748. endif()
  1749. endfunction()
  1750. function(find_appropriate_cache_directory dir)
  1751. set(env_suffix_LOCALAPPDATA .cache)
  1752. if(CMAKE_HOST_APPLE)
  1753. # On macOS, ~/Library/Caches is the preferred cache directory.
  1754. set(env_suffix_HOME Library/Caches)
  1755. else()
  1756. set(env_suffix_HOME .cache)
  1757. endif()
  1758. # Determine which env vars should be checked
  1759. if(CMAKE_HOST_APPLE)
  1760. set(dirs HOME)
  1761. elseif(CMAKE_HOST_WIN32)
  1762. set(dirs LOCALAPPDATA)
  1763. else()
  1764. # Assume Linux when we did not detect 'mac' or 'win'
  1765. #
  1766. # On Linux, freedesktop.org recommends using $XDG_CACHE_HOME if
  1767. # that is defined and defaulting to $HOME/.cache otherwise.
  1768. set(dirs
  1769. XDG_CACHE_HOME
  1770. HOME
  1771. )
  1772. endif()
  1773. foreach(env_var ${dirs})
  1774. if(DEFINED ENV{${env_var}})
  1775. set(env_dir $ENV{${env_var}})
  1776. set(test_user_dir ${env_dir}/${env_suffix_${env_var}})
  1777. check_if_directory_is_writeable(${test_user_dir} ok)
  1778. if(${ok})
  1779. # The directory is write-able
  1780. set(user_dir ${test_user_dir})
  1781. break()
  1782. else()
  1783. # The directory was not writeable, keep looking for a suitable
  1784. # directory
  1785. endif()
  1786. endif()
  1787. endforeach()
  1788. # Populate local_dir with a suitable directory for caching
  1789. # files. Prefer a directory outside of the git repository because it
  1790. # is good practice to have clean git repositories.
  1791. if(DEFINED user_dir)
  1792. # Zephyr's cache files go in the "zephyr" subdirectory of the
  1793. # user's cache directory.
  1794. set(local_dir ${user_dir}/zephyr)
  1795. else()
  1796. set(local_dir ${ZEPHYR_BASE}/.cache)
  1797. endif()
  1798. set(${dir} ${local_dir} PARENT_SCOPE)
  1799. endfunction()
  1800. function(generate_unique_target_name_from_filename filename target_name)
  1801. get_filename_component(basename ${filename} NAME)
  1802. string(REPLACE "." "_" x ${basename})
  1803. string(REPLACE "@" "_" x ${x})
  1804. string(MD5 unique_chars ${filename})
  1805. set(${target_name} gen_${x}_${unique_chars} PARENT_SCOPE)
  1806. endfunction()
  1807. # Usage:
  1808. # zephyr_file(<mode> <arg> ...)
  1809. #
  1810. # Zephyr file function extension.
  1811. # This function currently support the following <modes>
  1812. #
  1813. # APPLICATION_ROOT <path>: Check all paths in provided variable, and convert
  1814. # those paths that are defined with `-D<path>=<val>`
  1815. # to absolute path, relative from `APPLICATION_SOURCE_DIR`
  1816. # Issue an error for any relative path not specified
  1817. # by user with `-D<path>`
  1818. #
  1819. # CONF_FILES <path>: Find all configuration files in path and return them in a
  1820. # list. Configuration files will be:
  1821. # - DTS: Overlay files (.overlay)
  1822. # - Kconfig: Config fragments (.conf)
  1823. # The conf file search will return existing configuration
  1824. # files for the current board.
  1825. # CONF_FILES takes the following additional arguments:
  1826. # BOARD <board>: Find configuration files for specified board.
  1827. # BOARD_REVISION <revision>: Find configuration files for specified board
  1828. # revision. Requires BOARD to be specified.
  1829. #
  1830. # If no board is given the current BOARD and
  1831. # BOARD_REVISION will be used.
  1832. #
  1833. # DTS <list>: List to populate with DTS overlay files
  1834. # KCONF <list>: List to populate with Kconfig fragment files
  1835. # BUILD <type>: Build type to include for search.
  1836. # For example:
  1837. # BUILD debug, will look for <board>_debug.conf
  1838. # and <board>_debug.overlay, instead of <board>.conf
  1839. #
  1840. # returns an updated list of absolute paths
  1841. function(zephyr_file)
  1842. set(file_options APPLICATION_ROOT CONF_FILES)
  1843. if((ARGC EQUAL 0) OR (NOT (ARGV0 IN_LIST file_options)))
  1844. message(FATAL_ERROR "No <mode> given to `zephyr_file(<mode> <args>...)` function,\n \
  1845. Please provide one of following: APPLICATION_ROOT, CONF_FILES")
  1846. endif()
  1847. if(${ARGV0} STREQUAL APPLICATION_ROOT)
  1848. set(single_args APPLICATION_ROOT)
  1849. elseif(${ARGV0} STREQUAL CONF_FILES)
  1850. set(single_args CONF_FILES BOARD BOARD_REVISION DTS KCONF BUILD)
  1851. endif()
  1852. cmake_parse_arguments(FILE "" "${single_args}" "" ${ARGN})
  1853. if(FILE_UNPARSED_ARGUMENTS)
  1854. message(FATAL_ERROR "zephyr_file(${ARGV0} <path> ...) given unknown arguments: ${FILE_UNPARSED_ARGUMENTS}")
  1855. endif()
  1856. if(FILE_APPLICATION_ROOT)
  1857. # Note: user can do: `-D<var>=<relative-path>` and app can at same
  1858. # time specify `list(APPEND <var> <abs-path>)`
  1859. # Thus need to check and update only CACHED variables (-D<var>).
  1860. set(CACHED_PATH $CACHE{${FILE_APPLICATION_ROOT}})
  1861. foreach(path ${CACHED_PATH})
  1862. # The cached variable is relative path, i.e. provided by `-D<var>` or
  1863. # `set(<var> CACHE)`, so let's update current scope variable to absolute
  1864. # path from `APPLICATION_SOURCE_DIR`.
  1865. if(NOT IS_ABSOLUTE ${path})
  1866. set(abs_path ${APPLICATION_SOURCE_DIR}/${path})
  1867. list(FIND ${FILE_APPLICATION_ROOT} ${path} index)
  1868. if(NOT ${index} LESS 0)
  1869. list(REMOVE_AT ${FILE_APPLICATION_ROOT} ${index})
  1870. list(INSERT ${FILE_APPLICATION_ROOT} ${index} ${abs_path})
  1871. endif()
  1872. endif()
  1873. endforeach()
  1874. # Now all cached relative paths has been updated.
  1875. # Let's check if anyone uses relative path as scoped variable, and fail
  1876. foreach(path ${${FILE_APPLICATION_ROOT}})
  1877. if(NOT IS_ABSOLUTE ${path})
  1878. message(FATAL_ERROR
  1879. "Relative path encountered in scoped variable: ${FILE_APPLICATION_ROOT}, value=${path}\n \
  1880. Please adjust any `set(${FILE_APPLICATION_ROOT} ${path})` or `list(APPEND ${FILE_APPLICATION_ROOT} ${path})`\n \
  1881. to absolute path using `\${CMAKE_CURRENT_SOURCE_DIR}/${path}` or similar. \n \
  1882. Relative paths are only allowed with `-D${ARGV1}=<path>`")
  1883. endif()
  1884. endforeach()
  1885. # This updates the provided argument in parent scope (callers scope)
  1886. set(${FILE_APPLICATION_ROOT} ${${FILE_APPLICATION_ROOT}} PARENT_SCOPE)
  1887. endif()
  1888. if(FILE_CONF_FILES)
  1889. if(DEFINED FILE_BOARD_REVISION AND NOT FILE_BOARD)
  1890. message(FATAL_ERROR
  1891. "zephyr_file(${ARGV0} <path> BOARD_REVISION ${FILE_BOARD_REVISION} ...)"
  1892. " given without BOARD argument, please specify BOARD"
  1893. )
  1894. endif()
  1895. if(NOT DEFINED FILE_BOARD)
  1896. # Defaulting to system wide settings when BOARD is not given as argument
  1897. set(FILE_BOARD ${BOARD})
  1898. if(DEFINED BOARD_REVISION)
  1899. set(FILE_BOARD_REVISION ${BOARD_REVISION})
  1900. endif()
  1901. endif()
  1902. set(FILENAMES ${FILE_BOARD})
  1903. if(DEFINED FILE_BOARD_REVISION)
  1904. string(REPLACE "." "_" revision_string ${FILE_BOARD_REVISION})
  1905. list(APPEND FILENAMES "${FILE_BOARD}_${revision_string}")
  1906. endif()
  1907. if(FILE_DTS)
  1908. foreach(filename ${FILENAMES})
  1909. if(EXISTS ${FILE_CONF_FILES}/${filename}.overlay)
  1910. list(APPEND ${FILE_DTS} ${FILE_CONF_FILES}/${filename}.overlay)
  1911. endif()
  1912. endforeach()
  1913. # This updates the provided list in parent scope (callers scope)
  1914. set(${FILE_DTS} ${${FILE_DTS}} PARENT_SCOPE)
  1915. endif()
  1916. if(FILE_KCONF)
  1917. foreach(filename ${FILENAMES})
  1918. if(FILE_BUILD)
  1919. set(filename "${filename}_${FILE_BUILD}")
  1920. endif()
  1921. if(EXISTS ${FILE_CONF_FILES}/${filename}.conf)
  1922. list(APPEND ${FILE_KCONF} ${FILE_CONF_FILES}/${filename}.conf)
  1923. endif()
  1924. endforeach()
  1925. # This updates the provided list in parent scope (callers scope)
  1926. set(${FILE_KCONF} ${${FILE_KCONF}} PARENT_SCOPE)
  1927. endif()
  1928. endif()
  1929. endfunction()
  1930. # Usage:
  1931. # zephyr_string(<mode> <out-var> <input> ...)
  1932. #
  1933. # Zephyr string function extension.
  1934. # This function extends the CMake string function by providing additional
  1935. # manipulation arguments to CMake string.
  1936. #
  1937. # SANITIZE: Ensure that the output string does not contain any special
  1938. # characters. Special characters, such as -, +, =, $, etc. are
  1939. # converted to underscores '_'.
  1940. #
  1941. # SANITIZE TOUPPER: Ensure that the output string does not contain any special
  1942. # characters. Special characters, such as -, +, =, $, etc. are
  1943. # converted to underscores '_'.
  1944. # The sanitized string will be returned in UPPER case.
  1945. #
  1946. # returns the updated string
  1947. function(zephyr_string)
  1948. set(options SANITIZE TOUPPER)
  1949. cmake_parse_arguments(ZEPHYR_STRING "${options}" "" "" ${ARGN})
  1950. if (NOT ZEPHYR_STRING_UNPARSED_ARGUMENTS)
  1951. message(FATAL_ERROR "Function zephyr_string() called without a return variable")
  1952. endif()
  1953. list(GET ZEPHYR_STRING_UNPARSED_ARGUMENTS 0 return_arg)
  1954. list(REMOVE_AT ZEPHYR_STRING_UNPARSED_ARGUMENTS 0)
  1955. list(JOIN ZEPHYR_STRING_UNPARSED_ARGUMENTS "" work_string)
  1956. if(ZEPHYR_STRING_SANITIZE)
  1957. string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" work_string ${work_string})
  1958. endif()
  1959. if(ZEPHYR_STRING_TOUPPER)
  1960. string(TOUPPER ${work_string} work_string)
  1961. endif()
  1962. set(${return_arg} ${work_string} PARENT_SCOPE)
  1963. endfunction()
  1964. # Usage:
  1965. # zephyr_check_cache(<variable> [REQUIRED])
  1966. #
  1967. # Check the current CMake cache for <variable> and warn the user if the value
  1968. # is being modified.
  1969. #
  1970. # This can be used to ensure the user does not accidentally try to change
  1971. # Zephyr build variables, such as:
  1972. # - BOARD
  1973. # - SHIELD
  1974. #
  1975. # variable: Name of <variable> to check and set, for example BOARD.
  1976. # REQUIRED: Optional flag. If specified, then an unset <variable> will be
  1977. # treated as an error.
  1978. # WATCH: Optional flag. If specified, watch the variable and print a warning if
  1979. # the variable is later being changed.
  1980. #
  1981. # Details:
  1982. # <variable> can be set by 3 sources.
  1983. # - Using CMake argument, -D<variable>
  1984. # - Using an environment variable
  1985. # - In the project CMakeLists.txt before `find_package(Zephyr)`.
  1986. #
  1987. # CLI has the highest precedence, then comes environment variables,
  1988. # and then finally CMakeLists.txt.
  1989. #
  1990. # The value defined on the first CMake invocation will be stored in the CMake
  1991. # cache as CACHED_<variable>. This allows the Zephyr build system to detect
  1992. # when a user reconfigures a sticky variable.
  1993. #
  1994. # A user can ignore all the precedence rules if the same source is always used
  1995. # E.g. always specifies -D<variable>= on the command line,
  1996. # always has an environment <variable> set, or always has a set(<variable> foo)
  1997. # line in his CMakeLists.txt and avoids mixing sources.
  1998. #
  1999. # The selected <variable> can be accessed through the variable '<variable>' in
  2000. # following Zephyr CMake code.
  2001. #
  2002. # If the user tries to change <variable> to a new value, then a warning will
  2003. # be printed, and the previously cached value (CACHED_<variable>) will be
  2004. # used, as it has precedence.
  2005. #
  2006. # Together with the warning, user is informed that in order to change
  2007. # <variable> the build directory must be cleaned.
  2008. #
  2009. function(zephyr_check_cache variable)
  2010. cmake_parse_arguments(CACHE_VAR "REQUIRED;WATCH" "" "" ${ARGN})
  2011. string(TOLOWER ${variable} variable_text)
  2012. string(REPLACE "_" " " variable_text ${variable_text})
  2013. get_property(cached_value CACHE ${variable} PROPERTY VALUE)
  2014. # If the build has already been configured in an earlier CMake invocation,
  2015. # then CACHED_${variable} is set. The CACHED_${variable} setting takes
  2016. # precedence over any user or CMakeLists.txt input.
  2017. # If we detect that user tries to change the setting, then print a warning
  2018. # that a pristine build is needed.
  2019. # If user uses -D<variable>=<new_value>, then cli_argument will hold the new
  2020. # value, otherwise cli_argument will hold the existing (old) value.
  2021. set(cli_argument ${cached_value})
  2022. if(cli_argument STREQUAL CACHED_${variable})
  2023. # The is no changes to the <variable> value.
  2024. unset(cli_argument)
  2025. endif()
  2026. set(app_cmake_lists ${${variable}})
  2027. if(cached_value STREQUAL ${variable})
  2028. # The app build scripts did not set a default, The BOARD we are
  2029. # reading is the cached value from the CLI
  2030. unset(app_cmake_lists)
  2031. endif()
  2032. if(DEFINED CACHED_${variable})
  2033. # Warn the user if it looks like he is trying to change the board
  2034. # without cleaning first
  2035. if(cli_argument)
  2036. if(NOT ((CACHED_${variable} STREQUAL cli_argument) OR (${variable}_DEPRECATED STREQUAL cli_argument)))
  2037. message(WARNING "The build directory must be cleaned pristinely when "
  2038. "changing ${variable_text},\n"
  2039. "Current value=\"${CACHED_${variable}}\", "
  2040. "Ignored value=\"${cli_argument}\"")
  2041. endif()
  2042. endif()
  2043. if(CACHED_${variable})
  2044. set(${variable} ${CACHED_${variable}} PARENT_SCOPE)
  2045. # This resets the user provided value with previous (working) value.
  2046. set(${variable} ${CACHED_${variable}} CACHE STRING "Selected ${variable_text}" FORCE)
  2047. else()
  2048. unset(${variable} PARENT_SCOPE)
  2049. unset(${variable} CACHE)
  2050. endif()
  2051. elseif(cli_argument)
  2052. set(${variable} ${cli_argument})
  2053. elseif(DEFINED ENV{${variable}})
  2054. set(${variable} $ENV{${variable}})
  2055. elseif(app_cmake_lists)
  2056. set(${variable} ${app_cmake_lists})
  2057. elseif(${CACHE_VAR_REQUIRED})
  2058. message(FATAL_ERROR "${variable} is not being defined on the CMake command-line in the environment or by the app.")
  2059. endif()
  2060. # Store the specified variable in parent scope and the cache
  2061. set(${variable} ${${variable}} PARENT_SCOPE)
  2062. set(CACHED_${variable} ${${variable}} CACHE STRING "Selected ${variable_text}")
  2063. if(CACHE_VAR_WATCH)
  2064. # The variable is now set to its final value.
  2065. zephyr_boilerplate_watch(${variable})
  2066. endif()
  2067. endfunction(zephyr_check_cache variable)
  2068. # Usage:
  2069. # zephyr_boilerplate_watch(SOME_BOILERPLATE_VAR)
  2070. #
  2071. # Inform the build system that SOME_BOILERPLATE_VAR, a variable
  2072. # handled in cmake/app/boilerplate.cmake, is now fixed and should no
  2073. # longer be changed.
  2074. #
  2075. # This function uses variable_watch() to print a noisy warning
  2076. # if the variable is set after it returns.
  2077. function(zephyr_boilerplate_watch variable)
  2078. variable_watch(${variable} zephyr_variable_set_too_late)
  2079. endfunction()
  2080. function(zephyr_variable_set_too_late variable access value current_list_file)
  2081. if (access STREQUAL "MODIFIED_ACCESS")
  2082. message(WARNING
  2083. "
  2084. **********************************************************************
  2085. *
  2086. * WARNING
  2087. *
  2088. * CMake variable ${variable} set to \"${value}\" in:
  2089. * ${current_list_file}
  2090. *
  2091. * This is too late to make changes! The change was ignored.
  2092. *
  2093. * Hint: ${variable} must be set before calling find_package(Zephyr ...).
  2094. *
  2095. **********************************************************************
  2096. ")
  2097. endif()
  2098. endfunction()
  2099. # Usage:
  2100. # zephyr_get_targets(<directory> <types> <targets>)
  2101. #
  2102. # Get build targets for a given directory and sub-directories.
  2103. #
  2104. # This functions will traverse the build tree, starting from <directory>.
  2105. # It will read the `BUILDSYSTEM_TARGETS` for each directory in the build tree
  2106. # and return the build types matching the <types> list.
  2107. # Example of types: OBJECT_LIBRARY, STATIC_LIBRARY, INTERFACE_LIBRARY, UTILITY.
  2108. #
  2109. # returns a list of targets in <targets> matching the required <types>.
  2110. function(zephyr_get_targets directory types targets)
  2111. get_property(sub_directories DIRECTORY ${directory} PROPERTY SUBDIRECTORIES)
  2112. get_property(dir_targets DIRECTORY ${directory} PROPERTY BUILDSYSTEM_TARGETS)
  2113. foreach(dir_target ${dir_targets})
  2114. get_property(target_type TARGET ${dir_target} PROPERTY TYPE)
  2115. if(${target_type} IN_LIST types)
  2116. list(APPEND ${targets} ${dir_target})
  2117. endif()
  2118. endforeach()
  2119. foreach(directory ${sub_directories})
  2120. zephyr_get_targets(${directory} "${types}" ${targets})
  2121. endforeach()
  2122. set(${targets} ${${targets}} PARENT_SCOPE)
  2123. endfunction()
  2124. # Usage:
  2125. # target_byproducts(TARGET <target> BYPRODUCTS <file> [<file>...])
  2126. #
  2127. # Specify additional BYPRODUCTS that this target produces.
  2128. #
  2129. # This function allows the build system to specify additional byproducts to
  2130. # target created with `add_executable()`. When linking an executable the linker
  2131. # may produce additional files, like map files. Those files are not known to the
  2132. # build system. This function makes it possible to describe such additional
  2133. # byproducts in an easy manner.
  2134. function(target_byproducts)
  2135. cmake_parse_arguments(TB "" "TARGET" "BYPRODUCTS" ${ARGN})
  2136. if(NOT DEFINED TB_TARGET)
  2137. message(FATAL_ERROR "target_byproducts() missing parameter: TARGET <target>")
  2138. endif()
  2139. add_custom_command(TARGET ${TB_TARGET}
  2140. POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo ""
  2141. BYPRODUCTS ${TB_BYPRODUCTS}
  2142. COMMENT "Logical command for additional byproducts on target: ${TB_TARGET}"
  2143. )
  2144. endfunction()
  2145. ########################################################
  2146. # 4. Zephyr devicetree function
  2147. ########################################################
  2148. # 4.1. dt_*
  2149. #
  2150. # The following methods are for retrieving devicetree information in CMake.
  2151. #
  2152. # Note: In CMake we refer to the nodes using the node's path, therefore there
  2153. # is no dt_path(...) function for obtaining a node identifier.
  2154. # Usage:
  2155. # dt_nodelabel(<var> NODELABEL <label>)
  2156. #
  2157. # Function for retrieving the node path for the node having nodelabel
  2158. # <label>.
  2159. #
  2160. # Example devicetree fragment:
  2161. #
  2162. # / {
  2163. # soc {
  2164. # nvic: interrupt-controller@e000e100 { ... };
  2165. # };
  2166. # };
  2167. #
  2168. # Example usage:
  2169. #
  2170. # # Sets 'nvic_path' to "/soc/interrupt-controller@e000e100"
  2171. # dt_nodelabel(nvic_path NODELABEL "nvic")
  2172. #
  2173. # The node's path will be returned in the <var> parameter.
  2174. # <var> will be undefined if node does not exist.
  2175. #
  2176. # <var> : Return variable where the node path will be stored
  2177. # NODELABEL <label> : Node label
  2178. function(dt_nodelabel var)
  2179. set(req_single_args "NODELABEL")
  2180. cmake_parse_arguments(DT_LABEL "" "${req_single_args}" "" ${ARGN})
  2181. if(${ARGV0} IN_LIST req_single_args)
  2182. message(FATAL_ERROR "dt_nodelabel(${ARGV0} ...) missing return parameter.")
  2183. endif()
  2184. foreach(arg ${req_single_args})
  2185. if(NOT DEFINED DT_LABEL_${arg})
  2186. message(FATAL_ERROR "dt_nodelabel(${ARGV0} ...) "
  2187. "missing required argument: ${arg}"
  2188. )
  2189. endif()
  2190. endforeach()
  2191. get_target_property(${var} devicetree_target "DT_NODELABEL|${DT_LABEL_NODELABEL}")
  2192. if(${${var}} STREQUAL ${var}-NOTFOUND)
  2193. set(${var})
  2194. endif()
  2195. set(${var} ${${var}} PARENT_SCOPE)
  2196. endfunction()
  2197. # Usage:
  2198. # dt_node_exists(<var> PATH <path>)
  2199. #
  2200. # Tests whether a node with path <path> exists in the devicetree.
  2201. #
  2202. # The result of the check, either TRUE or FALSE, will be returned in
  2203. # the <var> parameter.
  2204. #
  2205. # <var> : Return variable where the check result will be returned
  2206. # PATH <path> : Node path
  2207. function(dt_node_exists var)
  2208. set(req_single_args "PATH")
  2209. cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
  2210. if(${ARGV0} IN_LIST req_single_args)
  2211. message(FATAL_ERROR "dt_node_existsl(${ARGV0} ...) missing return parameter.")
  2212. endif()
  2213. foreach(arg ${req_single_args})
  2214. if(NOT DEFINED DT_NODE_${arg})
  2215. message(FATAL_ERROR "dt_node_exists(${ARGV0} ...) "
  2216. "missing required argument: ${arg}"
  2217. )
  2218. endif()
  2219. endforeach()
  2220. get_target_property(${var} devicetree_target "DT_NODE|${DT_NODE_PATH}")
  2221. if(${var})
  2222. set(${var} ${${var}} PARENT_SCOPE)
  2223. else()
  2224. set(${var} FALSE PARENT_SCOPE)
  2225. endif()
  2226. endfunction()
  2227. # Usage:
  2228. # dt_node_has_status(<var> PATH <path> STATUS <status>)
  2229. #
  2230. # Tests whether <path> refers to a node which:
  2231. # - exists in the devicetree, and
  2232. # - has a status property matching the <status> argument
  2233. # (a missing status or an “ok” status is treated as if it
  2234. # were “okay” instead)
  2235. #
  2236. # The result of the check, either TRUE or FALSE, will be returned in
  2237. # the <var> parameter.
  2238. #
  2239. # <var> : Return variable where the check result will be returned
  2240. # PATH <path> : Node path
  2241. # STATUS <status> : Status to check
  2242. function(dt_node_has_status var)
  2243. set(req_single_args "PATH;STATUS")
  2244. cmake_parse_arguments(DT_NODE "" "${req_single_args}" "" ${ARGN})
  2245. if(${ARGV0} IN_LIST req_single_args)
  2246. message(FATAL_ERROR "dt_node_has_status(${ARGV0} ...) missing return parameter.")
  2247. endif()
  2248. foreach(arg ${req_single_args})
  2249. if(NOT DEFINED DT_NODE_${arg})
  2250. message(FATAL_ERROR "dt_node_has_status(${ARGV0} ...) "
  2251. "missing required argument: ${arg}"
  2252. )
  2253. endif()
  2254. endforeach()
  2255. dt_node_exists(${var} PATH ${DT_NODE_PATH})
  2256. if(NOT ${${var}})
  2257. set(${var} FALSE PARENT_SCOPE)
  2258. endif()
  2259. dt_prop(${var} PATH ${DT_NODE_PATH} PROPERTY status)
  2260. if(NOT DEFINED ${var} OR "${${var}}" STREQUAL ok)
  2261. set(${var} okay)
  2262. endif()
  2263. if(${var} STREQUAL ${DT_NODE_STATUS})
  2264. set(${var} TRUE PARENT_SCOPE)
  2265. else()
  2266. set(${var} FALSE PARENT_SCOPE)
  2267. endif()
  2268. endfunction()
  2269. # Usage:
  2270. #
  2271. # dt_prop(<var> PATH <path> PROPERTY <prop> [INDEX <idx>])
  2272. #
  2273. # Get a devicetree property value. The value will be returned in the
  2274. # <var> parameter.
  2275. #
  2276. # This function currently only supports properties with the following
  2277. # devicetree binding types: string, int, boolean, array, uint8-array,
  2278. # string-array, path.
  2279. #
  2280. # For array valued properties (including uint8-array and
  2281. # string-array), the entire array is returned as a CMake list unless
  2282. # INDEX is given. If INDEX is given, just the array element at index
  2283. # <idx> is returned.
  2284. #
  2285. # The property value will be returned in the <var> parameter if the
  2286. # node exists and has a property <prop> with one of the above types.
  2287. # <var> will be undefined otherwise.
  2288. #
  2289. # To test if the property is defined before using it, use DEFINED on
  2290. # the return <var>, like this:
  2291. #
  2292. # dt_prop(reserved_ranges PATH "/soc/gpio@deadbeef" PROPERTY "gpio-reserved-ranges")
  2293. # if(DEFINED reserved_ranges)
  2294. # # Node exists and has the "gpio-reserved-ranges" property.
  2295. # endif()
  2296. #
  2297. # To distinguish a missing node from a missing property, combine
  2298. # dt_prop() and dt_node_exists(), like this:
  2299. #
  2300. # dt_node_exists(node_exists PATH "/soc/gpio@deadbeef")
  2301. # dt_prop(reserved_ranges PATH "/soc/gpio@deadbeef" PROPERTY "gpio-reserved-ranges")
  2302. # if(DEFINED reserved_ranges)
  2303. # # Node "/soc/gpio@deadbeef" exists and has the "gpio-reserved-ranges" property
  2304. # elseif(node_exists)
  2305. # # Node exists, but doesn't have the property, or the property has an unsupported type.
  2306. # endif()
  2307. #
  2308. # <var> : Return variable where the property value will be stored
  2309. # PATH <path> : Node path
  2310. # PROPERTY <prop>: Property for which a value should be returned, as it
  2311. # appears in the DTS source
  2312. # INDEX <idx> : Optional index when retrieving a value in an array property
  2313. function(dt_prop var)
  2314. set(req_single_args "PATH;PROPERTY")
  2315. set(single_args "INDEX")
  2316. cmake_parse_arguments(DT_PROP "" "${req_single_args};${single_args}" "" ${ARGN})
  2317. if(${ARGV0} IN_LIST req_single_args)
  2318. message(FATAL_ERROR "dt_prop(${ARGV0} ...) missing return parameter.")
  2319. endif()
  2320. foreach(arg ${req_single_args})
  2321. if(NOT DEFINED DT_PROP_${arg})
  2322. message(FATAL_ERROR "dt_prop(${ARGV0} ...) "
  2323. "missing required argument: ${arg}"
  2324. )
  2325. endif()
  2326. endforeach()
  2327. get_property(exists TARGET devicetree_target
  2328. PROPERTY "DT_PROP|${DT_PROP_PATH}|${DT_PROP_PROPERTY}"
  2329. SET
  2330. )
  2331. if(NOT exists)
  2332. set(${var} PARENT_SCOPE)
  2333. return()
  2334. endif()
  2335. get_target_property(val devicetree_target
  2336. "DT_PROP|${DT_PROP_PATH}|${DT_PROP_PROPERTY}"
  2337. )
  2338. if(DEFINED DT_PROP_INDEX)
  2339. list(GET val ${DT_PROP_INDEX} element)
  2340. set(${var} "${element}" PARENT_SCOPE)
  2341. else()
  2342. set(${var} "${val}" PARENT_SCOPE)
  2343. endif()
  2344. endfunction()
  2345. # Usage:
  2346. # dt_num_regs(<var> PATH <path>)
  2347. #
  2348. # Get the number of register blocks in the node's reg property;
  2349. # this may be zero.
  2350. #
  2351. # The value will be returned in the <var> parameter.
  2352. #
  2353. # <var> : Return variable where the property value will be stored
  2354. # PATH <path> : Node path
  2355. function(dt_num_regs var)
  2356. set(req_single_args "PATH")
  2357. cmake_parse_arguments(DT_REG "" "${req_single_args}" "" ${ARGN})
  2358. if(${ARGV0} IN_LIST req_single_args)
  2359. message(FATAL_ERROR "dt_num_regs(${ARGV0} ...) missing return parameter.")
  2360. endif()
  2361. foreach(arg ${req_single_args})
  2362. if(NOT DEFINED DT_REG_${arg})
  2363. message(FATAL_ERROR "dt_num_regs(${ARGV0} ...) "
  2364. "missing required argument: ${arg}"
  2365. )
  2366. endif()
  2367. endforeach()
  2368. get_target_property(${var} devicetree_target "DT_REG|${DT_REG_PATH}|NUM")
  2369. set(${var} ${${var}} PARENT_SCOPE)
  2370. endfunction()
  2371. # Usage:
  2372. # dt_reg_addr(<var> PATH <path> [INDEX <idx>])
  2373. #
  2374. # Get the base address of the register block at index <idx>.
  2375. # If <idx> is omitted, then the value at index 0 will be returned.
  2376. #
  2377. # The value will be returned in the <var> parameter.
  2378. #
  2379. # Results can be:
  2380. # - The base address of the register block
  2381. # - <var> will be undefined if node does not exists or does not have a register
  2382. # block at the requested index.
  2383. #
  2384. # <var> : Return variable where the address value will be stored
  2385. # PATH <path> : Node path
  2386. # INDEX <idx> : Index number
  2387. function(dt_reg_addr var)
  2388. set(req_single_args "PATH")
  2389. set(single_args "INDEX")
  2390. cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
  2391. if(${ARGV0} IN_LIST req_single_args)
  2392. message(FATAL_ERROR "dt_reg_addr(${ARGV0} ...) missing return parameter.")
  2393. endif()
  2394. foreach(arg ${req_single_args})
  2395. if(NOT DEFINED DT_REG_${arg})
  2396. message(FATAL_ERROR "dt_reg_addr(${ARGV0} ...) "
  2397. "missing required argument: ${arg}"
  2398. )
  2399. endif()
  2400. endforeach()
  2401. if(NOT DEFINED DT_REG_INDEX)
  2402. set(DT_REG_INDEX 0)
  2403. endif()
  2404. get_target_property(${var}_list devicetree_target "DT_REG|${DT_REG_PATH}|ADDR")
  2405. list(GET ${var}_list ${DT_REG_INDEX} ${var})
  2406. if("${var}" STREQUAL NONE)
  2407. set(${var})
  2408. endif()
  2409. set(${var} ${${var}} PARENT_SCOPE)
  2410. endfunction()
  2411. # Usage:
  2412. # dt_reg_size(<var> PATH <path> [INDEX <idx>])
  2413. #
  2414. # Get the size of the register block at index <idx>.
  2415. # If INDEX is omitted, then the value at index 0 will be returned.
  2416. #
  2417. # The value will be returned in the <value> parameter.
  2418. #
  2419. # <var> : Return variable where the size value will be stored
  2420. # PATH <path> : Node path
  2421. # INDEX <idx> : Index number
  2422. function(dt_reg_size var)
  2423. set(req_single_args "PATH")
  2424. set(single_args "INDEX")
  2425. cmake_parse_arguments(DT_REG "" "${req_single_args};${single_args}" "" ${ARGN})
  2426. if(${ARGV0} IN_LIST req_single_args)
  2427. message(FATAL_ERROR "dt_reg_size(${ARGV0} ...) missing return parameter.")
  2428. endif()
  2429. foreach(arg ${req_single_args})
  2430. if(NOT DEFINED DT_REG_${arg})
  2431. message(FATAL_ERROR "dt_reg_size(${ARGV0} ...) "
  2432. "missing required argument: ${arg}"
  2433. )
  2434. endif()
  2435. endforeach()
  2436. if(NOT DEFINED DT_REG_INDEX)
  2437. set(DT_REG_INDEX 0)
  2438. endif()
  2439. get_target_property(${var}_list devicetree_target "DT_REG|${DT_REG_PATH}|SIZE")
  2440. list(GET ${var}_list ${DT_REG_INDEX} ${var})
  2441. if("${var}" STREQUAL NONE)
  2442. set(${var})
  2443. endif()
  2444. set(${var} ${${var}} PARENT_SCOPE)
  2445. endfunction()
  2446. # Usage:
  2447. # dt_has_chosen(<var> PROPERTY <prop>)
  2448. #
  2449. # Test if the devicetree's /chosen node has a given property
  2450. # <prop> which contains the path to a node.
  2451. #
  2452. # Example devicetree fragment:
  2453. #
  2454. # chosen {
  2455. # foo = &bar;
  2456. # };
  2457. #
  2458. # Example usage:
  2459. #
  2460. # # Sets 'result' to TRUE
  2461. # dt_has_chosen(result PROPERTY "foo")
  2462. #
  2463. # # Sets 'result' to FALSE
  2464. # dt_has_chosen(result PROPERTY "baz")
  2465. #
  2466. # The result of the check, either TRUE or FALSE, will be stored in the
  2467. # <var> parameter.
  2468. #
  2469. # <var> : Return variable
  2470. # PROPERTY <prop> : Chosen property
  2471. function(dt_has_chosen var)
  2472. set(req_single_args "PROPERTY")
  2473. cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
  2474. if(${ARGV0} IN_LIST req_single_args)
  2475. message(FATAL_ERROR "dt_has_chosen(${ARGV0} ...) missing return parameter.")
  2476. endif()
  2477. foreach(arg ${req_single_args})
  2478. if(NOT DEFINED DT_CHOSEN_${arg})
  2479. message(FATAL_ERROR "dt_has_chosen(${ARGV0} ...) "
  2480. "missing required argument: ${arg}"
  2481. )
  2482. endif()
  2483. endforeach()
  2484. get_target_property(exists devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
  2485. if(${exists} STREQUAL exists-NOTFOUND)
  2486. set(${var} FALSE PARENT_SCOPE)
  2487. else()
  2488. set(${var} TRUE PARENT_SCOPE)
  2489. endif()
  2490. endfunction()
  2491. # Usage:
  2492. # dt_chosen(<var> PROPERTY <prop>)
  2493. #
  2494. # Get a node path for a /chosen node property.
  2495. #
  2496. # the node path will be returned in the <value> parameter.
  2497. #
  2498. # <var> : Return variable where the node path will be stored
  2499. # PROPERTY <prop> : Chosen property
  2500. function(dt_chosen var)
  2501. set(req_single_args "PROPERTY")
  2502. cmake_parse_arguments(DT_CHOSEN "" "${req_single_args}" "" ${ARGN})
  2503. if(${ARGV0} IN_LIST req_single_args)
  2504. message(FATAL_ERROR "dt_has_chosen(${ARGV0} ...) missing return parameter.")
  2505. endif()
  2506. foreach(arg ${req_single_args})
  2507. if(NOT DEFINED DT_CHOSEN_${arg})
  2508. message(FATAL_ERROR "dt_chosen(${ARGV0} ...) "
  2509. "missing required argument: ${arg}"
  2510. )
  2511. endif()
  2512. endforeach()
  2513. get_target_property(${var} devicetree_target "DT_CHOSEN|${DT_CHOSEN_PROPERTY}")
  2514. if(${${var}} STREQUAL ${var}-NOTFOUND)
  2515. set(${var} PARENT_SCOPE)
  2516. else()
  2517. set(${var} ${${var}} PARENT_SCOPE)
  2518. endif()
  2519. endfunction()
  2520. ########################################################
  2521. # 5. Zephyr linker function
  2522. ########################################################
  2523. # 5.1. zephyr_linker*
  2524. #
  2525. # The following methods are for defining linker structure using CMake functions.
  2526. #
  2527. # This allows Zephyr developers to define linker sections and their content and
  2528. # have this configuration rendered into an appropriate linker script based on
  2529. # the toolchain in use.
  2530. # For example:
  2531. # ld linker scripts with GNU ld
  2532. # ARM scatter files with ARM linker.
  2533. #
  2534. # Example usage:
  2535. # zephyr_linker_section(
  2536. # NAME my_data
  2537. # VMA RAM
  2538. # LMA FLASH
  2539. # )
  2540. #
  2541. # and to configure special input sections for the section
  2542. # zephyr_linker_section_configure(
  2543. # SECTION my_data
  2544. # INPUT "my_custom_data"
  2545. # KEEP
  2546. # )
  2547. # Usage:
  2548. # zephyr_linker([FORMAT <format>]
  2549. # [ENTRY <entry symbol>]
  2550. # )
  2551. #
  2552. # Zephyr linker general settings.
  2553. # This function specifies general settings for the linker script to be generated.
  2554. #
  2555. # FORMAT <format>: The output format of the linked executable.
  2556. # ENTRY <entry symbolformat>: The code entry symbol.
  2557. #
  2558. function(zephyr_linker)
  2559. set(single_args "ENTRY;FORMAT")
  2560. cmake_parse_arguments(LINKER "" "${single_args}" "" ${ARGN})
  2561. if(LINKER_UNPARSED_ARGUMENTS)
  2562. message(FATAL_ERROR "zephyr_linker(${ARGV0} ...) given unknown "
  2563. "arguments: ${LINKER_UNPARSED_ARGUMENTS}"
  2564. )
  2565. endif()
  2566. if(DEFINED LINKER_FORMAT)
  2567. get_property(format_defined TARGET linker PROPERTY FORMAT SET)
  2568. if(format_defined)
  2569. message(FATAL_ERROR "zephyr_linker(FORMAT ...) already configured.")
  2570. else()
  2571. set_property(TARGET linker PROPERTY FORMAT ${LINKER_FORMAT})
  2572. endif()
  2573. endif()
  2574. if(DEFINED LINKER_ENTRY)
  2575. get_property(entry_defined TARGET linker PROPERTY ENTRY SET)
  2576. if(entry_defined)
  2577. message(FATAL_ERROR "zephyr_linker(ENTRY ...) already configured.")
  2578. else()
  2579. set_property(TARGET linker PROPERTY ENTRY ${LINKER_ENTRY})
  2580. endif()
  2581. endif()
  2582. endfunction()
  2583. # Usage:
  2584. # zephyr_linker_memory(NAME <name> START <address> SIZE <size> FLAGS <flags>)
  2585. #
  2586. # Zephyr linker memory.
  2587. # This function specifies a memory region for the platform in use.
  2588. #
  2589. # Note:
  2590. # This function should generally be called with values obtained from
  2591. # devicetree or Kconfig.
  2592. #
  2593. # NAME <name> : Name of the memory region, for example FLASH.
  2594. # START <address>: Start address of the memory region.
  2595. # Start address can be given as decimal or hex value.
  2596. # SIZE <size> : Size of the memory region.
  2597. # Size can be given as decimal value, hex value, or decimal with postfix k or m.
  2598. # All the following are valid values:
  2599. # 1048576, 0x10000, 1024k, 1024K, 1m, and 1M.
  2600. # FLAGS <flags> : Flags describing properties of the memory region.
  2601. # Currently supported:
  2602. # r: Read-only region
  2603. # w: Read-write region
  2604. # x: Executable region
  2605. # The flags r and x, or w and x may be combined like: rx, wx.
  2606. function(zephyr_linker_memory)
  2607. set(single_args "FLAGS;NAME;SIZE;START")
  2608. cmake_parse_arguments(MEMORY "" "${single_args}" "" ${ARGN})
  2609. if(MEMORY_UNPARSED_ARGUMENTS)
  2610. message(FATAL_ERROR "zephyr_linker_memory(${ARGV0} ...) given unknown "
  2611. "arguments: ${MEMORY_UNPARSED_ARGUMENTS}"
  2612. )
  2613. endif()
  2614. foreach(arg ${single_args})
  2615. if(NOT DEFINED MEMORY_${arg})
  2616. message(FATAL_ERROR "zephyr_linker_memory(${ARGV0} ...) missing required "
  2617. "argument: ${arg}"
  2618. )
  2619. endif()
  2620. endforeach()
  2621. set(MEMORY)
  2622. zephyr_linker_arg_val_list(MEMORY "${single_args}")
  2623. string(REPLACE ";" "\;" MEMORY "${MEMORY}")
  2624. set_property(TARGET linker
  2625. APPEND PROPERTY MEMORY_REGIONS "{${MEMORY}}"
  2626. )
  2627. endfunction()
  2628. # Usage:
  2629. # zephyr_linker_memory_ifdef(<setting> NAME <name> START <address> SIZE <size> FLAGS <flags>)
  2630. #
  2631. # Will create memory region if <setting> is enabled.
  2632. #
  2633. # <setting>: Setting to check for True value before invoking
  2634. # zephyr_linker_memory()
  2635. #
  2636. # See zephyr_linker_memory() description for other supported arguments.
  2637. #
  2638. macro(zephyr_linker_memory_ifdef feature_toggle)
  2639. if(${${feature_toggle}})
  2640. zephyr_linker_memory(${ARGN})
  2641. endif()
  2642. endmacro()
  2643. # Usage:
  2644. # zephyr_linker_dts_memory(NAME <name> PATH <path> FLAGS <flags>)
  2645. # zephyr_linker_dts_memory(NAME <name> NODELABEL <nodelabel> FLAGS <flags>)
  2646. # zephyr_linker_dts_memory(NAME <name> CHOSEN <prop> FLAGS <flags>)
  2647. #
  2648. # Zephyr linker devicetree memory.
  2649. # This function specifies a memory region for the platform in use based on its
  2650. # devicetree configuration.
  2651. #
  2652. # The memory will only be defined if the devicetree node or a devicetree node
  2653. # matching the nodelabel exists and has status okay.
  2654. #
  2655. # Only one of PATH, NODELABEL, and CHOSEN parameters may be given.
  2656. #
  2657. # NAME <name> : Name of the memory region, for example FLASH.
  2658. # PATH <path> : Devicetree node identifier.
  2659. # NODELABEL <label>: Node label
  2660. # CHOSEN <prop> : Chosen property, add memory section described by the
  2661. # /chosen property if it exists.
  2662. # FLAGS <flags> : Flags describing properties of the memory region.
  2663. # Currently supported:
  2664. # r: Read-only region
  2665. # w: Read-write region
  2666. # x: Executable region
  2667. # The flags r and x, or w and x may be combined like: rx, wx.
  2668. #
  2669. function(zephyr_linker_dts_memory)
  2670. set(single_args "CHOSEN;FLAGS;NAME;PATH;NODELABEL")
  2671. cmake_parse_arguments(DTS_MEMORY "" "${single_args}" "" ${ARGN})
  2672. if(DTS_MEMORY_UNPARSED_ARGUMENTS)
  2673. message(FATAL_ERROR "zephyr_linker_dts_memory(${ARGV0} ...) given unknown "
  2674. "arguments: ${DTS_MEMORY_UNPARSED_ARGUMENTS}"
  2675. )
  2676. endif()
  2677. if((DEFINED DTS_MEMORY_PATH AND (DEFINED DTS_MEMORY_NODELABEL OR DEFINED DTS_MEMORY_CHOSEN))
  2678. OR (DEFINED DTS_MEMORY_NODELABEL AND DEFINED DTS_MEMORY_CHOSEN))
  2679. message(FATAL_ERROR "zephyr_linker_dts_memory(${ARGV0} ...), only one of "
  2680. "PATH, NODELABEL, and CHOSEN is allowed."
  2681. )
  2682. endif()
  2683. if(DEFINED DTS_MEMORY_NODELABEL)
  2684. dt_nodelabel(DTS_MEMORY_PATH NODELABEL ${DTS_MEMORY_NODELABEL})
  2685. endif()
  2686. if(DEFINED DTS_MEMORY_CHOSEN)
  2687. dt_chosen(DTS_MEMORY_PATH PROPERTY ${DTS_MEMORY_CHOSEN})
  2688. endif()
  2689. if(NOT DEFINED DTS_MEMORY_PATH)
  2690. return()
  2691. endif()
  2692. dt_node_exists(exists PATH ${DTS_MEMORY_PATH})
  2693. if(NOT ${exists})
  2694. return()
  2695. endif()
  2696. dt_reg_addr(addr PATH ${DTS_MEMORY_PATH})
  2697. dt_reg_size(size PATH ${DTS_MEMORY_PATH})
  2698. zephyr_linker_memory(
  2699. NAME ${DTS_MEMORY_NAME}
  2700. START ${addr}
  2701. SIZE ${size}
  2702. FLAGS ${DTS_MEMORY_FLAGS}
  2703. )
  2704. endfunction()
  2705. # Usage:
  2706. # zephyr_linker_group(NAME <name> [VMA <region|group>] [LMA <region|group>] [SYMBOL <SECTION>])
  2707. # zephyr_linker_group(NAME <name> GROUP <group> [SYMBOL <SECTION>])
  2708. #
  2709. # Zephyr linker group.
  2710. # This function specifies a group inside a memory region or another group.
  2711. #
  2712. # The group ensures that all section inside the group are located together inside
  2713. # the specified group.
  2714. #
  2715. # This also allows for section placement inside a given group without the section
  2716. # itself needing the precise knowledge regarding the exact memory region this
  2717. # section will be placed in, as that will be determined by the group setup.
  2718. #
  2719. # Each group will define the following linker symbols:
  2720. # __<name>_start : Start address of the group
  2721. # __<name>_end : End address of the group
  2722. # __<name>_size : Size of the group
  2723. #
  2724. # Note: <name> will be converted to lower casing for linker symbols definitions.
  2725. #
  2726. # NAME <name> : Name of the group.
  2727. # VMA <region|group> : VMA Memory region or group to be used for this group.
  2728. # If a group is used then the VMA region of that group will be used.
  2729. # LMA <region|group> : Memory region or group to be used for this group.
  2730. # GROUP <group> : Place the new group inside the existing group <group>
  2731. # SYMBOL <SECTION> : Specify that start symbol of the region should be identical
  2732. # to the start address of the first section in the group.
  2733. #
  2734. # Note: VMA and LMA are mutual exclusive with GROUP
  2735. #
  2736. # Example:
  2737. # zephyr_linker_memory(NAME memA START ... SIZE ... FLAGS ...)
  2738. # zephyr_linker_group(NAME groupA LMA memA)
  2739. # zephyr_linker_group(NAME groupB LMA groupA)
  2740. #
  2741. # will create two groups in same memory region as groupB will inherit the LMA
  2742. # from groupA:
  2743. #
  2744. # +-----------------+
  2745. # | memory region A |
  2746. # | |
  2747. # | +-------------+ |
  2748. # | | groupA | |
  2749. # | +-------------+ |
  2750. # | |
  2751. # | +-------------+ |
  2752. # | | groupB | |
  2753. # | +-------------+ |
  2754. # | |
  2755. # +-----------------+
  2756. #
  2757. # whereas
  2758. # zephyr_linker_memory(NAME memA START ... SIZE ... FLAGS ...)
  2759. # zephyr_linker_group(NAME groupA LMA memA)
  2760. # zephyr_linker_group(NAME groupB GROUP groupA)
  2761. #
  2762. # will create groupB inside groupA:
  2763. #
  2764. # +---------------------+
  2765. # | memory region A |
  2766. # | |
  2767. # | +-----------------+ |
  2768. # | | groupA | |
  2769. # | | | |
  2770. # | | +-------------+ | |
  2771. # | | | groupB | | |
  2772. # | | +-------------+ | |
  2773. # | | | |
  2774. # | +-----------------+ |
  2775. # | |
  2776. # +---------------------+
  2777. function(zephyr_linker_group)
  2778. set(single_args "NAME;GROUP;LMA;SYMBOL;VMA")
  2779. set(symbol_values SECTION)
  2780. cmake_parse_arguments(GROUP "" "${single_args}" "" ${ARGN})
  2781. if(GROUP_UNPARSED_ARGUMENTS)
  2782. message(FATAL_ERROR "zephyr_linker_group(${ARGV0} ...) given unknown "
  2783. "arguments: ${GROUP_UNPARSED_ARGUMENTS}"
  2784. )
  2785. endif()
  2786. if(DEFINED GROUP_GROUP AND (DEFINED GROUP_VMA OR DEFINED GROUP_LMA))
  2787. message(FATAL_ERROR "zephyr_linker_group(GROUP ...) cannot be used with "
  2788. "VMA or LMA"
  2789. )
  2790. endif()
  2791. if(DEFINED GROUP_SYMBOL)
  2792. if(NOT ${GROUP_SYMBOL} IN_LIST symbol_values)
  2793. message(FATAL_ERROR "zephyr_linker_group(SYMBOL ...) given unknown value")
  2794. endif()
  2795. endif()
  2796. set(GROUP)
  2797. zephyr_linker_arg_val_list(GROUP "${single_args}")
  2798. string(REPLACE ";" "\;" GROUP "${GROUP}")
  2799. set_property(TARGET linker
  2800. APPEND PROPERTY GROUPS "{${GROUP}}"
  2801. )
  2802. endfunction()
  2803. # Usage:
  2804. # zephyr_linker_section(NAME <name> [GROUP <group>]
  2805. # [VMA <region|group>] [LMA <region|group>]
  2806. # [ADDRESS <address>] [ALIGN <alignment>]
  2807. # [SUBALIGN <alignment>] [FLAGS <flags>]
  2808. # [HIDDEN] [NOINPUT] [NOINIT]
  2809. # [PASS <no> [<no>...]
  2810. # )
  2811. #
  2812. # Zephyr linker output section.
  2813. # This function specifies an output section for the linker.
  2814. #
  2815. # When using zephyr_linker_section(NAME <name>) an output section with <name>
  2816. # will be configured. This section will default include input sections of the
  2817. # same name, unless NOINPUT is specified.
  2818. # This means the section named `foo` will default include the sections matching
  2819. # `foo` and `foo.*`
  2820. # Each output section will define the following linker symbols:
  2821. # __<name>_start : Start address of the section
  2822. # __<name>_end : End address of the section
  2823. # __<name>_size : Size of the section
  2824. # __<name>_load_start : Load address of the section, if VMA = LMA then this
  2825. # value will be identical to `__<name>_start`
  2826. #
  2827. # The location of the output section can be controlled using LMA, VMA, and
  2828. # address parameters
  2829. #
  2830. # NAME <name> : Name of the output section.
  2831. # VMA <region|group> : VMA Memory region or group where code / data is located runtime (VMA)
  2832. # If <group> is used here it means the section will use the
  2833. # same VMA memory region as <group> but will not be placed
  2834. # inside the group itself, see also GROUP argument.
  2835. # KVMA <region|group> : Kernel VMA Memory region or group where code / data is located runtime (VMA)
  2836. # When MMU is active and Kernel VM base and offset is different
  2837. # from SRAM base and offset, then the region defined by KVMA will
  2838. # be used as VMA.
  2839. # If <group> is used here it means the section will use the
  2840. # same VMA memory region as <group> but will not be placed
  2841. # inside the group itself, see also GROUP argument.
  2842. # LMA <region|group> : Memory region or group where code / data is loaded (LMA)
  2843. # If VMA is different from LMA, the code / data will be loaded
  2844. # from LMA into VMA at bootup, this is usually the case for
  2845. # global or static variables that are loaded in rom and copied
  2846. # to ram at boot time.
  2847. # If <group> is used here it means the section will use the
  2848. # same LMA memory region as <group> but will not be placed
  2849. # inside the group itself, see also GROUP argument.
  2850. # GROUP <group> : Place this section inside the group <group>
  2851. # ADDRESS <address> : Specific address to use for this section.
  2852. # ALIGN_WITH_INPUT : The alignment difference between VMA and LMA is kept
  2853. # intact for this section.
  2854. # ALIGN <alignment> : Align the execution address with alignment.
  2855. # SUBALIGN <alignment>: Align input sections with alignment value.
  2856. # ENDALIGN <alignment>: Align the end so that next output section will start aligned.
  2857. # This only has effect on Scatter scripts.
  2858. # Note: Regarding all alignment attributes. Not all linkers may handle alignment
  2859. # in identical way. For example the Scatter file will align both load and
  2860. # execution address (LMA and VMA) to be aligned when given the ALIGN attribute.
  2861. # NOINPUT : No default input sections will be defined, to setup input
  2862. # sections for section <name>, the corresponding
  2863. # `zephyr_linker_section_configure()` must be used.
  2864. # PASS <no> [<no> ..] : Linker pass iteration where this section should be active.
  2865. # Default a section will be present during all linker passes
  2866. # But in cases a section shall only be present at a specific
  2867. # pass, this argument can be used. For example to only have
  2868. # this section present on the first linker pass, use `PASS 1`.
  2869. #
  2870. # Note: VMA and LMA are mutual exclusive with GROUP
  2871. #
  2872. function(zephyr_linker_section)
  2873. set(options "ALIGN_WITH_INPUT;HIDDEN;NOINIT;NOINPUT")
  2874. set(single_args "ADDRESS;ALIGN;ENDALIGN;GROUP;KVMA;LMA;NAME;SUBALIGN;TYPE;VMA")
  2875. set(multi_args "PASS")
  2876. cmake_parse_arguments(SECTION "${options}" "${single_args}" "${multi_args}" ${ARGN})
  2877. if(SECTION_UNPARSED_ARGUMENTS)
  2878. message(WARNING "zephyr_linker_section(${ARGV0} ...) given unknown "
  2879. "arguments: ${SECTION_UNPARSED_ARGUMENTS}"
  2880. )
  2881. endif()
  2882. if(DEFINED SECTION_GROUP AND (DEFINED SECTION_VMA OR DEFINED SECTION_LMA))
  2883. message(FATAL_ERROR "zephyr_linker_section(GROUP ...) cannot be used with "
  2884. "VMA or LMA"
  2885. )
  2886. endif()
  2887. if(DEFINED SECTION_KVMA)
  2888. # If KVMA is set and the Kernel virtual memory settings reqs are met, we
  2889. # substitute the VMA setting with the specified KVMA value.
  2890. if(CONFIG_MMU)
  2891. math(EXPR KERNEL_MEM_VM_OFFSET
  2892. "(${CONFIG_KERNEL_VM_BASE} + ${CONFIG_KERNEL_VM_OFFSET})\
  2893. - (${CONFIG_SRAM_BASE_ADDRESS} + ${CONFIG_SRAM_OFFSET})"
  2894. )
  2895. if(NOT (${KERNEL_MEM_VM_OFFSET} EQUAL 0))
  2896. set(SECTION_VMA ${SECTION_KVMA})
  2897. set(SECTION_KVMA)
  2898. endif()
  2899. endif()
  2900. endif()
  2901. set(SECTION)
  2902. zephyr_linker_arg_val_list(SECTION "${single_args}")
  2903. zephyr_linker_arg_val_list(SECTION "${options}")
  2904. zephyr_linker_arg_val_list(SECTION "${multi_args}")
  2905. string(REPLACE ";" "\;" SECTION "${SECTION}")
  2906. set_property(TARGET linker
  2907. APPEND PROPERTY SECTIONS "{${SECTION}}"
  2908. )
  2909. endfunction()
  2910. # Usage:
  2911. # zephyr_linker_section_ifdef(<setting>
  2912. # NAME <name> [VMA <region>] [LMA <region>]
  2913. # [ADDRESS <address>] [ALIGN <alignment>]
  2914. # [SUBALIGN <alignment>] [FLAGS <flags>]
  2915. # [HIDDEN] [NOINPUT] [NOINIT]
  2916. # [PASS <no> [<no>...]
  2917. # )
  2918. #
  2919. # Will create an output section if <setting> is enabled.
  2920. #
  2921. # <setting>: Setting to check for True value before invoking
  2922. # zephyr_linker_section()
  2923. #
  2924. # See zephyr_linker_section() description for other supported arguments.
  2925. #
  2926. macro(zephyr_linker_section_ifdef feature_toggle)
  2927. if(${${feature_toggle}})
  2928. zephyr_linker_section(${ARGN})
  2929. endif()
  2930. endmacro()
  2931. # Usage:
  2932. # zephyr_iterable_section(NAME <name> [GROUP <group>]
  2933. # [VMA <region|group>] [LMA <region|group>]
  2934. # [ALIGN_WITH_INPUT] [SUBALIGN <alignment>]
  2935. # )
  2936. #
  2937. #
  2938. # Define an output section which will set up an iterable area
  2939. # of equally-sized data structures. For use with Z_STRUCT_SECTION_ITERABLE.
  2940. # Input sections will be sorted by name in lexicographical order.
  2941. #
  2942. # Each list for an input section will define the following linker symbols:
  2943. # _<name>_list_start: Start of the iterable list
  2944. # _<name>_list_end : End of the iterable list
  2945. #
  2946. # The output section will be named `<name>_area` and define the following linker
  2947. # symbols:
  2948. # __<name>_area_start : Start address of the section
  2949. # __<name>_area_end : End address of the section
  2950. # __<name>_area_size : Size of the section
  2951. # __<name>_area_load_start : Load address of the section, if VMA = LMA then this
  2952. # value will be identical to `__<name>_area_start`
  2953. #
  2954. # NAME <name> : Name of the struct type, the output section be named
  2955. # accordingly as: <name>_area.
  2956. # VMA <region|group> : VMA Memory region where code / data is located runtime (VMA)
  2957. # LMA <region|group> : Memory region where code / data is loaded (LMA)
  2958. # If VMA is different from LMA, the code / data will be loaded
  2959. # from LMA into VMA at bootup, this is usually the case for
  2960. # global or static variables that are loaded in rom and copied
  2961. # to ram at boot time.
  2962. # GROUP <group> : Place this section inside the group <group>
  2963. # ADDRESS <address> : Specific address to use for this section.
  2964. # ALIGN_WITH_INPUT : The alignment difference between VMA and LMA is kept
  2965. # intact for this section.
  2966. # SUBALIGN <alignment>: Force input alignment with size <alignment>
  2967. # Note: Regarding all alignment attributes. Not all linkers may handle alignment
  2968. # in identical way. For example the Scatter file will align both load and
  2969. # execution address (LMA and VMA) to be aligned when given the ALIGN attribute.
  2970. #/
  2971. function(zephyr_iterable_section)
  2972. # ToDo - Should we use ROM, RAM, etc as arguments ?
  2973. set(options "ALIGN_WITH_INPUT")
  2974. set(single_args "GROUP;LMA;NAME;SUBALIGN;VMA")
  2975. set(multi_args "")
  2976. set(align_input)
  2977. cmake_parse_arguments(SECTION "${options}" "${single_args}" "${multi_args}" ${ARGN})
  2978. if(NOT DEFINED SECTION_NAME)
  2979. message(FATAL_ERROR "zephyr_iterable_section(${ARGV0} ...) missing "
  2980. "required argument: NAME"
  2981. )
  2982. endif()
  2983. if(NOT DEFINED SECTION_SUBALIGN)
  2984. message(FATAL_ERROR "zephyr_iterable_section(${ARGV0} ...) missing "
  2985. "required argument: SUBALIGN"
  2986. )
  2987. endif()
  2988. if(SECTION_ALIGN_WITH_INPUT)
  2989. set(align_input ALIGN_WITH_INPUT)
  2990. endif()
  2991. zephyr_linker_section(
  2992. NAME ${SECTION_NAME}_area
  2993. GROUP "${SECTION_GROUP}"
  2994. VMA "${SECTION_VMA}" LMA "${SECTION_LMA}"
  2995. NOINPUT ${align_input} SUBALIGN ${SECTION_SUBALIGN}
  2996. )
  2997. zephyr_linker_section_configure(
  2998. SECTION ${SECTION_NAME}_area
  2999. INPUT "._${SECTION_NAME}.static.*"
  3000. SYMBOLS _${SECTION_NAME}_list_start _${SECTION_NAME}_list_end
  3001. KEEP SORT NAME
  3002. )
  3003. endfunction()
  3004. # Usage:
  3005. # zephyr_linker_section_obj_level(SECTION <section> LEVEL <level>)
  3006. #
  3007. # generate a symbol to mark the start of the objects array for
  3008. # the specified object and level, then link all of those objects
  3009. # (sorted by priority). Ensure the objects aren't discarded if there is
  3010. # no direct reference to them.
  3011. #
  3012. # This is useful content such as struct devices.
  3013. #
  3014. # For example: zephyr_linker_section_obj_level(SECTION init LEVEL PRE_KERNEL_1)
  3015. # will create an input section matching `.z_init_PRE_KERNEL_1?_` and
  3016. # `.z_init_PRE_KERNEL_1??_`.
  3017. #
  3018. # SECTION <section>: Section in which the objects shall be placed
  3019. # LEVEL <level> : Priority level, all input sections matching the level
  3020. # will be sorted.
  3021. #
  3022. function(zephyr_linker_section_obj_level)
  3023. set(single_args "SECTION;LEVEL")
  3024. cmake_parse_arguments(OBJ "" "${single_args}" "" ${ARGN})
  3025. if(NOT DEFINED OBJ_SECTION)
  3026. message(FATAL_ERROR "zephyr_linker_section_obj_level(${ARGV0} ...) "
  3027. "missing required argument: SECTION"
  3028. )
  3029. endif()
  3030. if(NOT DEFINED OBJ_LEVEL)
  3031. message(FATAL_ERROR "zephyr_linker_section_obj_level(${ARGV0} ...) "
  3032. "missing required argument: LEVEL"
  3033. )
  3034. endif()
  3035. zephyr_linker_section_configure(
  3036. SECTION ${OBJ_SECTION}
  3037. INPUT ".z_${OBJ_SECTION}_${OBJ_LEVEL}?_"
  3038. SYMBOLS __${OBJ_SECTION}_${OBJ_LEVEL}_start
  3039. KEEP SORT NAME
  3040. )
  3041. zephyr_linker_section_configure(
  3042. SECTION ${OBJ_SECTION}
  3043. INPUT ".z_${OBJ_SECTION}_${OBJ_LEVEL}??_"
  3044. KEEP SORT NAME
  3045. )
  3046. endfunction()
  3047. # Usage:
  3048. # zephyr_linker_section_configure(SECTION <section> [ALIGN <alignment>]
  3049. # [PASS <no>] [PRIO <no>] [SORT <sort>]
  3050. # [ANY] [FIRST] [KEEP]
  3051. # )
  3052. #
  3053. # Configure an output section with additional input sections.
  3054. # An output section can be configured with additional input sections besides its
  3055. # default section.
  3056. # For example, adding the input section `foo` to the output section bar, with KEEP
  3057. # attribute, then call:
  3058. # zephyr_linker_section_configure(SECTION bar INPUT foo KEEP)
  3059. #
  3060. # ALIGN <alignment> : Will align the input section placement inside the load
  3061. # region with <alignment>
  3062. # FIRST : The first input section in the list should be marked as
  3063. # first section in output.
  3064. # SORT <NAME> : Sort the input sections according to <type>.
  3065. # Currently only `NAME` is supported.
  3066. # KEEP : Do no eliminate input section during linking
  3067. # PRIO : The priority of the input section. Per default, input
  3068. # sections order is not guaranteed by all linkers, but
  3069. # using priority, then Zephyr CMake linker will create
  3070. # sections so order can be guaranteed. All unprioritized
  3071. # sections will internally be given a CMake process order
  3072. # priority counting from 100, so first unprioritized section
  3073. # is handles internal pri0 100, next 101, and so on.
  3074. # To ensure a specific input section come before those,
  3075. # you may use `PRIO 50`, `PRIO 20` and so on.
  3076. # To ensure an input section is at the end, it is advised
  3077. # to use `PRIO 200` and above.
  3078. # PASS <no> : The call should only be considered for linker pass number <no>.
  3079. # For example, `PASS 1` means the call is only effective
  3080. # on first linker pass iteration. `PASS 2` on second iteration,
  3081. # and so on.
  3082. # FLAGS <flags> : Special section flags such as "+RO", +XO, "+ZI".
  3083. # ANY : ANY section flag in scatter file.
  3084. # The FLAGS and ANY arguments only has effect for scatter files.
  3085. #
  3086. function(zephyr_linker_section_configure)
  3087. set(options "ANY;FIRST;KEEP")
  3088. set(single_args "ALIGN;OFFSET;PASS;PRIO;SECTION;SORT")
  3089. set(multi_args "FLAGS;INPUT;SYMBOLS")
  3090. cmake_parse_arguments(SECTION "${options}" "${single_args}" "${multi_args}" ${ARGN})
  3091. if(SECTION_UNPARSED_ARGUMENTS)
  3092. message(FATAL_ERROR "zephyr_linker_section_configure(${ARGV0} ...) given unknown arguments: ${SECTION_UNPARSED_ARGUMENTS}")
  3093. endif()
  3094. if(DEFINED SECTION_SYMBOLS)
  3095. list(LENGTH SECTION_SYMBOLS symbols_count)
  3096. if(${symbols_count} GREATER 2)
  3097. message(FATAL_ERROR "zephyr_linker_section_configure(SYMBOLS [start_sym [end_sym]]) takes maximum two symbol names (start and end).")
  3098. endif()
  3099. endif()
  3100. set(SECTION)
  3101. zephyr_linker_arg_val_list(SECTION "${single_args}")
  3102. zephyr_linker_arg_val_list(SECTION "${options}")
  3103. zephyr_linker_arg_val_list(SECTION "${multi_args}")
  3104. string(REPLACE ";" "\;" SECTION "${SECTION}")
  3105. set_property(TARGET linker
  3106. APPEND PROPERTY SECTION_SETTINGS "{${SECTION}}"
  3107. )
  3108. endfunction()
  3109. # Usage:
  3110. # zephyr_linker_symbol(SYMBOL <name> EXPR <expr>)
  3111. #
  3112. # Add additional user defined symbol to the generated linker script.
  3113. #
  3114. # SYMBOL <name>: Symbol name to be available.
  3115. # EXPR <expr> : Expression that defines the symbol. Due to linker limitations
  3116. # all expressions should only contain simple math, such as
  3117. # `+, -, *` and similar. The expression will go directly into the
  3118. # linker, and all `%<symbol>%` will be replaced with the referred
  3119. # symbol.
  3120. #
  3121. # Example:
  3122. # To create a new symbol `bar` pointing to the start VMA address of section
  3123. # `foo` + 1024, one can write:
  3124. # zephyr_linker_symbol(SYMBOL bar EXPR "(%foo% + 1024)")
  3125. #
  3126. function(zephyr_linker_symbol)
  3127. set(single_args "EXPR;SYMBOL")
  3128. cmake_parse_arguments(SYMBOL "" "${single_args}" "" ${ARGN})
  3129. if(SECTION_UNPARSED_ARGUMENTS)
  3130. message(WARNING "zephyr_linker_symbol(${ARGV0} ...) given unknown "
  3131. "arguments: ${SECTION_UNPARSED_ARGUMENTS}"
  3132. )
  3133. endif()
  3134. set(SYMBOL)
  3135. zephyr_linker_arg_val_list(SYMBOL "${single_args}")
  3136. string(REPLACE ";" "\;" SYMBOL "${SYMBOL}")
  3137. set_property(TARGET linker
  3138. APPEND PROPERTY SYMBOLS "{${SYMBOL}}"
  3139. )
  3140. endfunction()
  3141. # Internal helper macro for zephyr_linker*() functions.
  3142. # The macro will create a list of argument-value pairs for defined arguments
  3143. # that can be passed on to linker script generators and processed as a CMake
  3144. # function call using cmake_parse_arguments.
  3145. #
  3146. # For example, having the following argument and value:
  3147. # FOO: bar
  3148. # BAZ: <undefined>
  3149. # QUX: option set
  3150. #
  3151. # will create a list as: "FOO;bar;QUX:TRUE" which can then be parsed as argument
  3152. # list later.
  3153. macro(zephyr_linker_arg_val_list list arguments)
  3154. foreach(arg ${arguments})
  3155. if(DEFINED ${list}_${arg})
  3156. list(APPEND ${list} ${arg} "${${list}_${arg}}")
  3157. endif()
  3158. endforeach()
  3159. endmacro()