1# SPDX-License-Identifier: Apache-2.0
2
3# *DOCUMENTATION*
4#
5# Note that this is *NOT* the top-level CMakeLists.txt. That's in the
6# application. See the Application Development Primer documentation
7# for details.
8#
9# To see a list of typical targets execute "make usage"
10# More info can be located in ./README.rst
11# Comments in this file are targeted only to the developer, do not
12# expect to learn how to build the kernel reading this file.
13
14if(NOT DEFINED ZEPHYR_BINARY_DIR)
15  message(FATAL_ERROR "A user error has occurred.
16cmake was invoked with '${CMAKE_CURRENT_LIST_DIR}' specified as the source directory,
17but it must be invoked with an application source directory,
18such as '${CMAKE_CURRENT_LIST_DIR}/samples/hello_world'.
19Debug variables:
20CMAKE_CACHEFILE_DIR: ${CMAKE_CACHEFILE_DIR}
21")
22endif()
23
24
25# See https://gitlab.kitware.com/cmake/cmake/issues/16228
26# and https://cmake.org/pipermail/cmake/2019-May/thread.html#69496
27if(NOT ZEPHYR_BASE STREQUAL CMAKE_CURRENT_SOURCE_DIR)
28message(WARNING "ZEPHYR_BASE doesn't match CMAKE_CURRENT_SOURCE_DIR
29  ZEPHYR_BASE              = ${ZEPHYR_BASE}
30  PWD                      = $ENV{PWD}
31  CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}
32You may be using a mix of symbolic links and real paths which causes \
33subtle and hard to debug CMake issues.")
34endif()
35# For Zephyr more specifically this breaks (at least)
36#     -fmacro-prefix-map=${ZEPHYR_BASE}=
37
38
39# In some cases the "final" things are not used at all and "_prebuilt"
40# is the last station. See "logical_target_for_zephyr_elf" below for
41# details.
42set(CMAKE_EXECUTABLE_SUFFIX .elf)
43
44# Zephyr build system will use a dynamic number of linking stages based on build
45# configuration.
46#
47# Currently up to three linking stages may be executed:
48# zephyr_pre0:  First linking stage
49# zephyr_pre1:  Second linking stage
50# zephyr_final: Final linking stage
51#
52# There will at minimum be a single linking stage.
53# When only a single linking stage is required, the `zephyr_pre0` will be mapped
54# into the `zephyr_final` target.
55#
56# Multiple linking stages are required in the following cases:
57# - device dependencies structs must be generated (CONFIG_DEVICE_DEPS=y)
58# - ISR tables must be generated (CONFIG_GEN_ISR_TABLES=y)
59# - Kernel objects hash tables (CONFIG_USERSPACE=y)
60# - Application memory partitions (CONFIG_USERSPACE=y)
61#
62# Some generators require that memory locations has been fixed, thus those are
63# placed at the second linking stage.
64#
65# When all three linking stages are active, then the following properties applies:
66# - zephyr_pre0:  linker sections may resize / addresses may relocate
67# - zephyr_pre1:  All linker section sizes are fixed, addresses cannot change
68# - zephyr_final: Final image.
69#
70set(ZEPHYR_CURRENT_LINKER_PASS 0)
71set(ZEPHYR_CURRENT_LINKER_CMD    linker_zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS}.cmd)
72set(ZEPHYR_LINK_STAGE_EXECUTABLE zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS})
73
74# ZEPHYR_PREBUILT_EXECUTABLE is used outside of this file, therefore keep the
75# existing variable to allow slowly cleanup of linking stage handling.
76# Three stage linking active: pre0 -> pre1 -> final, this will correspond to `pre1`
77# Two stage linking active:   pre0 -> final, this will correspond to `pre0`
78if(CONFIG_USERSPACE OR CONFIG_DEVICE_DEPS)
79  set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre1)
80else()
81  set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre0)
82endif()
83set(ZEPHYR_FINAL_EXECUTABLE zephyr_final)
84
85# Set some phony targets to collect dependencies
86set(OFFSETS_H_TARGET           offsets_h)
87set(SYSCALL_LIST_H_TARGET      syscall_list_h_target)
88set(DRIVER_VALIDATION_H_TARGET driver_validation_h_target)
89set(KOBJ_TYPES_H_TARGET        kobj_types_h_target)
90set(PARSE_SYSCALLS_TARGET      parse_syscalls_target)
91set(DEVICE_API_LD_TARGET       device_api_ld_target)
92
93define_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT BRIEF_DOCS " " FULL_DOCS " ")
94set_property(   GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf32-little${ARCH}) # BFD format
95
96# Contains the list of files with syscall function prototypes.
97add_library(syscalls_interface INTERFACE)
98set(syscalls_file_list_output
99    ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_file_list.txt)
100
101# "zephyr_interface" is a source-less library that encapsulates all the global
102# compiler options needed by all source files. All zephyr libraries,
103# including the library named "zephyr" link with this library to
104# obtain these flags.
105# https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#interface-libraries
106add_library(zephyr_interface INTERFACE)
107
108# "zephyr" is a catch-all CMake library for source files that can be
109# built purely with the include paths, defines, and other compiler
110# flags that come with zephyr_interface.
111zephyr_library_named(zephyr)
112
113if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH)
114  zephyr_include_directories(${PROJECT_BINARY_DIR}/include/generated/zephyr)
115endif()
116
117zephyr_include_directories(
118  include
119  ${PROJECT_BINARY_DIR}/include/generated
120  ${USERINCLUDE}
121  ${STDINCLUDE}
122)
123
124include(${ZEPHYR_BASE}/cmake/linker_script/${ARCH}/linker.cmake OPTIONAL)
125
126zephyr_include_directories(${SOC_FULL_DIR})
127
128# Don't inherit compiler flags from the environment
129foreach(var AFLAGS CFLAGS CXXFLAGS CPPFLAGS LDFLAGS)
130  if(DEFINED ENV{${var}})
131    message(WARNING "The environment variable '${var}' was set to $ENV{${var}}, "
132                    "but Zephyr ignores flags from the environment. Use 'cmake "
133                    "-DEXTRA_${var}=$ENV{${var}}' instead."
134    )
135    unset(ENV{${var}})
136  endif()
137endforeach()
138
139zephyr_compile_definitions(
140  KERNEL
141  __ZEPHYR__=1
142)
143
144# Ensure that include/zephyr/toolchain.h includes toolchain/other.h for all off-tree toolchains
145if(TOOLCHAIN_USE_CUSTOM)
146  zephyr_compile_definitions(__TOOLCHAIN_CUSTOM__)
147endif()
148
149# @Intent: Set compiler specific flag for disabling strict aliasing rule
150zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,no_strict_aliasing>>)
151zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,no_strict_aliasing>>)
152
153# Extra warnings options for twister run
154if (CONFIG_COMPILER_WARNINGS_AS_ERRORS)
155  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warnings_as_errors>>)
156  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler,warnings_as_errors>>)
157  zephyr_compile_options($<$<COMPILE_LANGUAGE:ASM>:$<TARGET_PROPERTY:asm,warnings_as_errors>>)
158  zephyr_link_libraries($<TARGET_PROPERTY:linker,warnings_as_errors>)
159endif()
160
161# @Intent: Set compiler flags to enable buffer overflow checks in libc functions
162# @details:
163#  Kconfig.zephyr "Detect buffer overflows in libc calls" is a kconfig choice,
164#  ensuring at most *one* of CONFIG_FORTIFY_SOURCE_{COMPILE_TIME,RUN_TIME} is
165#  set. Refer to Kconfig.zephyr for selection logic and description of these
166#  choices. Toolchains set both of the security_fortify_{compile_time,run_time}
167#  properties and the Kconfig settings are used here to select between those.
168#
169if(CONFIG_FORTIFY_SOURCE_RUN_TIME)
170  zephyr_compile_definitions($<TARGET_PROPERTY:compiler,security_fortify_run_time> )
171elseif(CONFIG_FORTIFY_SOURCE_COMPILE_TIME)
172  zephyr_compile_definitions($<TARGET_PROPERTY:compiler,security_fortify_compile_time> )
173endif()
174
175# @Intent: Set compiler flags to detect general stack overflows across all functions
176if(CONFIG_STACK_CANARIES)
177  zephyr_compile_options($<TARGET_PROPERTY:compiler,security_canaries>)
178elseif(CONFIG_STACK_CANARIES_STRONG)
179  zephyr_compile_options($<TARGET_PROPERTY:compiler,security_canaries_strong>)
180elseif(CONFIG_STACK_CANARIES_ALL)
181  zephyr_compile_options($<TARGET_PROPERTY:compiler,security_canaries_all>)
182elseif(CONFIG_STACK_CANARIES_EXPLICIT)
183  zephyr_compile_options($<TARGET_PROPERTY:compiler,security_canaries_explicit>)
184endif()
185
186# @Intent: Obtain compiler optimizations flags and store in variables
187# @details:
188#   Kconfig.zephyr "Optimization level" is a kconfig choice, ensuring
189#   only *one* of CONFIG_{NO,DEBUG,SPEED,SIZE}_OPTIMIZATIONS is set.
190#   Refer to Kconfig.zephyr for selection logic and description of these choices.
191#   toolchain_cc_optimize_*() macros must provide the mapping from these kconfigs
192#   to compiler flags. Each macro will store the flags in a CMake variable, whose
193#   name is passed as argument (somewhat like by reference).
194#
195#   If the user wants to tweak the optimizations, there are two ways:
196#    1) Using EXTRA_CFLAGS which is applied regardless of kconfig choice, or
197#    2) Rely on override support being implemented by your toolchain_cc_optimize_*()
198#
199get_property(OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG TARGET compiler PROPERTY no_optimization)
200get_property(OPTIMIZE_FOR_DEBUG_FLAG TARGET compiler PROPERTY optimization_debug)
201get_property(OPTIMIZE_FOR_SPEED_FLAG TARGET compiler PROPERTY optimization_speed)
202get_property(OPTIMIZE_FOR_SIZE_FLAG  TARGET compiler PROPERTY optimization_size)
203get_property(OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG TARGET compiler PROPERTY optimization_size_aggressive)
204
205# From kconfig choice, pick the actual OPTIMIZATION_FLAG to use.
206# Kconfig choice ensures only one of these CONFIG_*_OPTIMIZATIONS is set.
207if(CONFIG_NO_OPTIMIZATIONS)
208  set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_NO_OPTIMIZATIONS_FLAG})
209elseif(CONFIG_DEBUG_OPTIMIZATIONS)
210  set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_DEBUG_FLAG})
211elseif(CONFIG_SPEED_OPTIMIZATIONS)
212  set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SPEED_FLAG})
213elseif(CONFIG_SIZE_OPTIMIZATIONS)
214  set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SIZE_FLAG}) # Default in kconfig
215elseif(CONFIG_SIZE_OPTIMIZATIONS_AGGRESSIVE)
216  set(OPTIMIZATION_FLAG ${OPTIMIZE_FOR_SIZE_AGGRESSIVE_FLAG})
217else()
218  message(FATAL_ERROR
219    "Unreachable code. Expected optimization level to have been chosen. See Kconfig.zephyr")
220endif()
221
222if(NOT CONFIG_ARCH_IS_SET)
223  message(WARNING "\
224None of the CONFIG_<arch> (e.g. CONFIG_X86) symbols are set. \
225Select one of them from the SOC_SERIES_* symbol or, lacking that, from the \
226SOC_* symbol.")
227endif()
228
229# Apply the final optimization flag(s)
230zephyr_compile_options(${OPTIMIZATION_FLAG})
231
232if(CONFIG_LTO)
233  zephyr_compile_options($<TARGET_PROPERTY:compiler,optimization_lto>)
234  add_link_options($<TARGET_PROPERTY:linker,lto_arguments>)
235endif()
236
237if(CONFIG_STD_C23)
238  set(CSTD c2x)
239elseif(CONFIG_STD_C17)
240  set(CSTD c17)
241elseif(CONFIG_STD_C11)
242  set(CSTD c11)
243elseif(CONFIG_STD_C99)
244  set(CSTD c99)
245elseif(CONFIG_STD_C90)
246  set(CSTD c90)
247else()
248  message(FATAL_ERROR "Unreachable code. Expected C standard to have been chosen.")
249endif()
250
251if(CONFIG_GNU_C_EXTENSIONS)
252  string(REPLACE "c" "gnu" CSTD "${CSTD}")
253endif()
254
255list(APPEND CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}})
256
257# @Intent: Obtain compiler specific flags related to C++ that are not influenced by kconfig
258zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,required>>)
259
260# @Intent: Obtain compiler specific flags for compiling under different ISO standards of C++
261if(CONFIG_CPP)
262  # From kconfig choice, pick a single dialect.
263  # Kconfig choice ensures only one of these CONFIG_STD_CPP* is set.
264  if(CONFIG_STD_CPP98)
265    set(STD_CPP_DIALECT_FLAGS $<TARGET_PROPERTY:compiler-cpp,dialect_cpp98>)
266    list(APPEND CMAKE_CXX_COMPILE_FEATURES ${compile_features_cpp98})
267  elseif(CONFIG_STD_CPP11)
268    set(STD_CPP_DIALECT_FLAGS $<TARGET_PROPERTY:compiler-cpp,dialect_cpp11>) # Default in kconfig
269    list(APPEND CMAKE_CXX_COMPILE_FEATURES ${compile_features_cpp11})
270  elseif(CONFIG_STD_CPP14)
271    set(STD_CPP_DIALECT_FLAGS $<TARGET_PROPERTY:compiler-cpp,dialect_cpp14>)
272    list(APPEND CMAKE_CXX_COMPILE_FEATURES ${compile_features_cpp14})
273  elseif(CONFIG_STD_CPP17)
274    set(STD_CPP_DIALECT_FLAGS $<TARGET_PROPERTY:compiler-cpp,dialect_cpp17>)
275    list(APPEND CMAKE_CXX_COMPILE_FEATURES ${compile_features_cpp17})
276  elseif(CONFIG_STD_CPP2A)
277    set(STD_CPP_DIALECT_FLAGS $<TARGET_PROPERTY:compiler-cpp,dialect_cpp2a>)
278    list(APPEND CMAKE_CXX_COMPILE_FEATURES ${compile_features_cpp20})
279  elseif(CONFIG_STD_CPP20)
280    set(STD_CPP_DIALECT_FLAGS $<TARGET_PROPERTY:compiler-cpp,dialect_cpp20>)
281    list(APPEND CMAKE_CXX_COMPILE_FEATURES ${compile_features_cpp20})
282  elseif(CONFIG_STD_CPP2B)
283    set(STD_CPP_DIALECT_FLAGS $<TARGET_PROPERTY:compiler-cpp,dialect_cpp2b>)
284    list(APPEND CMAKE_CXX_COMPILE_FEATURES ${compile_features_cpp20})
285  else()
286    message(FATAL_ERROR
287      "Unreachable code. Expected C++ standard to have been chosen. See Kconfig.zephyr.")
288  endif()
289  set(CMAKE_CXX_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES} PARENT_SCOPE)
290
291  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:${STD_CPP_DIALECT_FLAGS}>)
292endif()
293
294if(NOT CONFIG_CPP_EXCEPTIONS)
295  # @Intent: Obtain compiler specific flags related to C++ Exceptions
296  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,no_exceptions>>)
297endif()
298
299if(NOT CONFIG_CPP_RTTI)
300  # @Intent: Obtain compiler specific flags related to C++ Run Time Type Information
301  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,no_rtti>>)
302endif()
303
304if(CONFIG_MISRA_SANE)
305  # @Intent: Obtain toolchain compiler flags relating to MISRA.
306  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warning_error_misra_sane>>)
307  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,warning_error_misra_sane>>)
308endif()
309
310# This is intend to be temporary. Once we have fixed the violations that
311# prevents build Zephyr, these flags shall be part of the default flags.
312if(CONFIG_CODING_GUIDELINE_CHECK)
313  # @Intent: Obtain toolchain compiler flags relating to coding guideline
314  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warning_error_coding_guideline>>)
315endif()
316
317# @Intent: Set compiler specific macro inclusion of AUTOCONF_H
318zephyr_compile_options("SHELL: $<TARGET_PROPERTY:compiler,imacros> ${AUTOCONF_H}")
319
320if(CONFIG_COMPILER_FREESTANDING)
321  # @Intent: Set compiler specific flag for bare metal freestanding option
322  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,freestanding>>)
323  zephyr_compile_options($<$<COMPILE_LANGUAGE:ASM>:$<TARGET_PROPERTY:compiler,freestanding>>)
324endif()
325
326if (CONFIG_PICOLIBC AND NOT CONFIG_PICOLIBC_IO_FLOAT)
327  # @Intent: Set compiler specific flag to disable printf-related optimizations
328  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,no_printf_return_value>>)
329endif()
330
331# @Intent: Set compiler specific flag for tentative definitions, no-common
332zephyr_compile_options($<TARGET_PROPERTY:compiler,no_common>)
333
334# @Intent: Set compiler specific flag for production of debug information
335zephyr_compile_options($<TARGET_PROPERTY:compiler,debug>)
336
337if(CONFIG_COMPILER_SAVE_TEMPS)
338  # @Intent: Set compiler specific flag for saving temporary object files
339  zephyr_compile_options($<TARGET_PROPERTY:compiler,save_temps>)
340endif()
341
342if(NOT CONFIG_COMPILER_TRACK_MACRO_EXPANSION)
343  # @Intent: Set compiler specific flags to not track macro expansion
344  zephyr_compile_options($<TARGET_PROPERTY:compiler,no_track_macro_expansion>)
345endif()
346
347if(CONFIG_COMPILER_COLOR_DIAGNOSTICS)
348# @Intent: Set compiler specific flag for diagnostic messages
349zephyr_compile_options($<TARGET_PROPERTY:compiler,diagnostic>)
350endif()
351
352zephyr_compile_options(
353  ${TOOLCHAIN_C_FLAGS}
354)
355
356# @Intent: Obtain compiler specific flags related to assembly
357# ToDo: Remember to get feedback from Oticon on this, as they might use the `ASM_BASE_FLAG` since this is done this way.
358zephyr_compile_options($<$<COMPILE_LANGUAGE:ASM>:$<TARGET_PROPERTY:asm,required>>)
359
360# @Intent: Enforce standard integer type correspondence to match Zephyr usage.
361# (must be after compiler specific flags)
362if(CONFIG_ENFORCE_ZEPHYR_STDINT)
363  zephyr_compile_options("SHELL: $<TARGET_PROPERTY:compiler,imacros> ${ZEPHYR_BASE}/include/zephyr/toolchain/zephyr_stdint.h")
364endif()
365
366# Common toolchain-agnostic assembly flags
367zephyr_compile_options(
368  $<$<COMPILE_LANGUAGE:ASM>:-D_ASMLANGUAGE>
369)
370
371find_package(Deprecated COMPONENTS toolchain_ld_base)
372
373if(DEFINED TOOLCHAIN_LD_FLAGS)
374  zephyr_ld_options(${TOOLCHAIN_LD_FLAGS})
375endif()
376
377zephyr_link_libraries(PROPERTY base)
378
379zephyr_link_libraries_ifndef(CONFIG_LINKER_USE_RELAX PROPERTY no_relax)
380
381zephyr_link_libraries_ifdef(CONFIG_LINKER_USE_RELAX PROPERTY relax)
382
383# Sort the common symbols and each input section by alignment
384# in descending order to minimize padding between these symbols.
385zephyr_link_libraries_ifdef(CONFIG_LINKER_SORT_BY_ALIGNMENT PROPERTY sort_alignment)
386
387toolchain_ld_force_undefined_symbols(
388  _OffsetAbsSyms
389  _ConfigAbsSyms
390)
391
392if(NOT CONFIG_NATIVE_BUILD)
393  find_package(Deprecated COMPONENTS toolchain_ld_baremetal)
394
395  zephyr_link_libraries(PROPERTY baremetal)
396
397  # Note that some architectures will skip this flag if set to error, even
398  # though the compiler flag check passes (e.g. ARC and Xtensa). So warning
399  # should be the default for now.
400  #
401  # Skip this for native application as Zephyr only provides
402  # additions to the host toolchain linker script. The relocation
403  # sections (.rel*) requires us to override those provided
404  # by host toolchain. As we can't account for all possible
405  # combination of compiler and linker on all machines used
406  # for development, it is better to turn this off.
407  #
408  # CONFIG_LINKER_ORPHAN_SECTION_PLACE is to place the orphan sections
409  # without any warnings or errors, which is the default behavior.
410  # So there is no need to explicitly set a linker flag.
411  if(CONFIG_LINKER_ORPHAN_SECTION_WARN)
412    zephyr_link_libraries(PROPERTY orphan_warning)
413  elseif(CONFIG_LINKER_ORPHAN_SECTION_ERROR)
414    zephyr_link_libraries(PROPERTY orphan_error)
415  endif()
416endif()
417
418if(CONFIG_CPP)
419  if(NOT CONFIG_MINIMAL_LIBCPP AND NOT CONFIG_NATIVE_LIBRARY)
420    find_package(Deprecated COMPONENTS toolchain_ld_cpp)
421  endif()
422
423  zephyr_link_libraries(PROPERTY cpp_base)
424endif()
425
426# @Intent: Add the basic toolchain warning flags
427zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warning_base>>)
428zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,warning_base>>)
429
430# ==========================================================================
431#
432# cmake -DW=... settings
433#
434# W=1 - warnings that may be relevant and does not occur too often
435# W=2 - warnings that occur quite often but may still be relevant
436# W=3 - the more obscure warnings, can most likely be ignored
437# ==========================================================================
438# @Intent: Add cmake -DW toolchain supported warnings, if any
439if(W MATCHES "1")
440  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warning_dw_1>>)
441  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,warning_dw_1>>)
442endif()
443
444if(W MATCHES "2")
445  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warning_dw_2>>)
446  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,warning_dw_2>>)
447endif()
448
449if(W MATCHES "3")
450  zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warning_dw_3>>)
451  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,warning_dw_3>>)
452endif()
453
454# @Intent: Add extended, more specific, toolchain warning flags
455zephyr_compile_options($<TARGET_PROPERTY:compiler,warning_extended>)
456
457# @Intent: Trigger an error when a declaration does not specify a type
458zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,warning_error_implicit_int>>)
459zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,warning_error_implicit_int>>)
460
461# @Intent: Do not make position independent code / executable
462zephyr_compile_options($<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,no_position_independent>>)
463zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler,no_position_independent>>)
464
465# In case of CONFIG_NATIVE_LIBRARY we also don't want position independent code,
466# but we cannot tell that to the linker yet as we are first only doing a
467# relocatable link into a static library
468zephyr_link_libraries_ifndef(CONFIG_NATIVE_LIBRARY
469                             $<TARGET_PROPERTY:linker,no_position_independent>)
470
471# Allow the user to inject options when calling cmake, e.g.
472# 'cmake -DEXTRA_CFLAGS="-Werror -Wno-deprecated-declarations" ..'
473include(cmake/extra_flags.cmake)
474
475zephyr_cc_option(-fno-asynchronous-unwind-tables)
476
477if(CONFIG_USERSPACE)
478  zephyr_compile_options($<TARGET_PROPERTY:compiler,no_global_merge>)
479endif()
480
481if(CONFIG_THREAD_LOCAL_STORAGE)
482# Only support local exec TLS model at this point.
483zephyr_cc_option(-ftls-model=local-exec)
484endif()
485
486if(CONFIG_OVERRIDE_FRAME_POINTER_DEFAULT)
487  if(CONFIG_OMIT_FRAME_POINTER)
488    zephyr_cc_option(-fomit-frame-pointer)
489  else()
490    zephyr_cc_option(-fno-omit-frame-pointer)
491  endif()
492endif()
493
494separate_arguments(COMPILER_OPT_AS_LIST UNIX_COMMAND ${CONFIG_COMPILER_OPT})
495zephyr_compile_options(${COMPILER_OPT_AS_LIST})
496
497# TODO: Include arch compiler options at this point.
498
499if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" AND
500   NOT CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM" AND
501   NOT CMAKE_C_COMPILER_ID STREQUAL "ARMClang")
502  # GCC assumed
503  zephyr_cc_option(-fno-reorder-functions)
504
505  # GCC 11 and above may generate a warning when dereferencing a constant
506  # address pointer whose address is below the value specified by the
507  # `min-pagesize` parameter (defaults to 0x1000). The `min-pagesize` parameter
508  # is set to 0 such that GCC never generates any warnings for the constant
509  # address pointers. For more details, refer to the GCC PR99578.
510  zephyr_cc_option(--param=min-pagesize=0)
511
512  if(NOT ${ZEPHYR_TOOLCHAIN_VARIANT} STREQUAL "xcc")
513    zephyr_cc_option(-fno-defer-pop)
514  endif()
515else()
516  # Clang produces false positive vla warnings
517  zephyr_cc_option(-Wno-vla)
518endif()
519
520zephyr_cc_option_ifdef(CONFIG_STACK_USAGE            -fstack-usage)
521
522# If the compiler supports it, strip the ${ZEPHYR_BASE} prefix from the
523# __FILE__ macro used in __ASSERT*, in the
524# .noinit."/home/joe/zephyr/fu/bar.c" section names and in any
525# application code. This saves some memory, stops leaking user locations
526# in binaries, makes failure logs more deterministic and most
527# importantly makes builds more deterministic
528if(CONFIG_BUILD_OUTPUT_STRIP_PATHS)
529  # If several match then the last one wins. This matters for instances
530  # like tests/ and samples/: they're inside all of them! Then let's
531  # strip as little as possible.
532  zephyr_cc_option(-fmacro-prefix-map=${CMAKE_SOURCE_DIR}=CMAKE_SOURCE_DIR)
533  zephyr_cc_option(-fmacro-prefix-map=${ZEPHYR_BASE}=ZEPHYR_BASE)
534  if(WEST_TOPDIR)
535    zephyr_cc_option(-fmacro-prefix-map=${WEST_TOPDIR}=WEST_TOPDIR)
536  endif()
537endif()
538
539# TODO: Archiver arguments
540# ar_option(D)
541
542# Declare MPU userspace dependencies before the linker scripts to make
543# sure the order of dependencies are met
544if(CONFIG_USERSPACE)
545  add_custom_target(app_smem)
546  set(APP_SMEM_ALIGNED_DEP app_smem_aligned_linker)
547  set(APP_SMEM_UNALIGNED_DEP app_smem_unaligned_linker)
548endif()
549
550if(CONFIG_USERSPACE)
551  set(KOBJECT_LINKER_DEP kobject_linker)
552endif()
553
554if(DEFINED BUILD_VERSION)
555  set(build_version_argument "-DBUILD_VERSION=${BUILD_VERSION}")
556elseif(NOT ZEPHYR_GIT_INDEX)
557  if(EXISTS ${ZEPHYR_BASE}/.git/index)
558    set(ZEPHYR_GIT_INDEX ${ZEPHYR_BASE}/.git/index CACHE PATH
559      "Path to Zephyr git repository index file")
560  elseif(EXISTS ${ZEPHYR_BASE}/.git)
561    # Likely a git-submodule. Let's ask git where the real database is located.
562    find_package(Git QUIET)
563    if(GIT_FOUND)
564      execute_process(
565        COMMAND ${GIT_EXECUTABLE} rev-parse --absolute-git-dir
566        WORKING_DIRECTORY ${ZEPHYR_BASE}
567        OUTPUT_VARIABLE zephyr_git_dir
568        OUTPUT_STRIP_TRAILING_WHITESPACE
569        ERROR_STRIP_TRAILING_WHITESPACE
570        ERROR_VARIABLE stderr
571        RESULT_VARIABLE return_code)
572      if(return_code)
573        message(WARNING "BUILD_VERSION: git rev-parse failed: ${stderr}")
574      else()
575        if(NOT "${stderr}" STREQUAL "")
576          message(WARNING "BUILD_VERSION: git rev-parse warned: ${stderr}")
577        endif()
578        set(ZEPHYR_GIT_INDEX ${zephyr_git_dir}/index CACHE PATH
579          "Path to Zephyr git repository index file")
580      endif()
581    else()
582      message(WARNING "Could not find git installation, "
583        "please specify '-DBUILD_VERSION=<version>'")
584    endif()
585  else()
586    message(WARNING "ZEPHYR_BASE=${ZEPHYR_BASE} doesn't appear to be a git "
587      "repository, please specify '-DBUILD_VERSION=<version>'")
588  endif()
589endif()
590
591if(ZEPHYR_GIT_INDEX)
592  set(git_dependency ${ZEPHYR_GIT_INDEX})
593endif()
594
595add_custom_command(
596  OUTPUT ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h
597  COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE}
598    -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h
599    -DVERSION_TYPE=KERNEL
600    -DVERSION_FILE=${ZEPHYR_BASE}/VERSION
601    -DKERNEL_VERSION_CUSTOMIZATION="$<TARGET_PROPERTY:version_h,KERNEL_VERSION_CUSTOMIZATION>"
602    ${build_version_argument}
603    -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake
604  DEPENDS ${ZEPHYR_BASE}/VERSION ${git_dependency}
605  COMMAND_EXPAND_LISTS
606)
607add_custom_target(version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h)
608zephyr_get(KERNEL_VERSION_CUSTOMIZATION SYSBUILD LOCAL)
609set_property(TARGET version_h PROPERTY KERNEL_VERSION_CUSTOMIZATION ${KERNEL_VERSION_CUSTOMIZATION})
610
611if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION)
612  add_custom_command(
613    OUTPUT ${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h
614    COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE}
615      -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h
616      -DVERSION_TYPE=APP
617      -DVERSION_FILE=${APPLICATION_SOURCE_DIR}/VERSION
618      -DAPP_VERSION_CUSTOMIZATION="$<TARGET_PROPERTY:app_version_h,APP_VERSION_CUSTOMIZATION>"
619      ${build_version_argument}
620      -P ${ZEPHYR_BASE}/cmake/gen_version_h.cmake
621    DEPENDS ${APPLICATION_SOURCE_DIR}/VERSION ${git_dependency}
622    COMMAND_EXPAND_LISTS
623  )
624  add_custom_target(
625    app_version_h
626    DEPENDS ${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h)
627  add_dependencies(zephyr_interface app_version_h)
628  zephyr_get(APP_VERSION_CUSTOMIZATION SYSBUILD LOCAL)
629  set_property(TARGET app_version_h PROPERTY APP_VERSION_CUSTOMIZATION ${APP_VERSION_CUSTOMIZATION})
630endif()
631
632# Unfortunately, the order in which CMakeLists.txt code is processed
633# matters so we need to be careful about how we order the processing
634# of subdirectories. One example is "Compiler flags added late in the
635# build are not exported to external build systems #5605"; when we
636# integrate with an external build system we read out all compiler
637# flags when the external project is created. So an external project
638# defined in subsys or ext will not get global flags added by drivers/
639# or tests/ as the subdirectories are ordered now.
640#
641# Another example of when the order matters is the reading and writing
642# of global properties such as ZEPHYR_LIBS or
643# GENERATED_KERNEL_OBJECT_FILES.
644#
645# Arch is placed early because it defines important compiler flags
646# that must be exported to external build systems defined in
647# e.g. subsys/.
648add_subdirectory(arch)
649add_subdirectory(lib)
650# We use include instead of add_subdirectory to avoid creating a new directory scope.
651# This is because source file properties are directory scoped, including the GENERATED
652# property which is set implicitly for custom command outputs
653include(misc/generated/CMakeLists.txt)
654
655add_subdirectory(soc)
656add_subdirectory(boards)
657add_subdirectory(subsys)
658add_subdirectory(drivers)
659
660# Include zephyr modules generated CMake file.
661foreach(module_name ${ZEPHYR_MODULE_NAMES})
662  # Note the second, binary_dir parameter requires the added
663  # subdirectory to have its own, local cmake target(s). If not then
664  # this binary_dir is created but stays empty. Object files land in
665  # the main binary dir instead.
666  # https://cmake.org/pipermail/cmake/2019-June/069547.html
667  zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name})
668  if(NOT ${ZEPHYR_${MODULE_NAME_UPPER}_CMAKE_DIR} STREQUAL "")
669    set(ZEPHYR_CURRENT_MODULE_NAME ${ZEPHYR_${MODULE_NAME_UPPER}_MODULE_NAME})
670    set(ZEPHYR_CURRENT_MODULE_DIR ${ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR})
671    set(ZEPHYR_CURRENT_CMAKE_DIR ${ZEPHYR_${MODULE_NAME_UPPER}_CMAKE_DIR})
672    add_subdirectory(${ZEPHYR_CURRENT_CMAKE_DIR} ${CMAKE_BINARY_DIR}/modules/${module_name})
673  endif()
674endforeach()
675# Done processing modules, clear module variables
676set(ZEPHYR_CURRENT_MODULE_NAME)
677set(ZEPHYR_CURRENT_MODULE_DIR)
678set(ZEPHYR_CURRENT_CMAKE_DIR)
679
680get_property(LIBC_LINK_LIBRARIES TARGET zephyr_interface PROPERTY LIBC_LINK_LIBRARIES)
681zephyr_link_libraries(${LIBC_LINK_LIBRARIES})
682
683set(syscall_list_h   ${CMAKE_CURRENT_BINARY_DIR}/include/generated/zephyr/syscall_list.h)
684set(edk_syscall_list_h   ${CMAKE_CURRENT_BINARY_DIR}/edk/include/generated/zephyr/syscall_list.h)
685set(syscalls_json    ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls.json)
686set(struct_tags_json ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/struct_tags.json)
687
688# The syscalls subdirs txt file is constructed by python containing a list of folders to use for
689# dependency handling, including empty folders.
690# Windows:  The list is used to specify DIRECTORY list with CMAKE_CONFIGURE_DEPENDS attribute.
691# Other OS: The list will update whenever a file is added/removed/modified and ensure a re-build.
692set(syscalls_subdirs_txt ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_subdirs.txt)
693
694# As syscalls_subdirs_txt is updated whenever a file is modified, this file can not be used for
695# monitoring of added / removed folders. A trigger file is thus used for correct dependency
696# handling. The trigger file will update when a folder is added / removed.
697set(syscalls_subdirs_trigger ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_subdirs.trigger)
698
699if(NOT (${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows))
700  set(syscalls_links --create-links ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_links)
701endif()
702
703# When running CMake it must be ensured that all dependencies are correctly acquired.
704execute_process(
705  COMMAND
706  ${PYTHON_EXECUTABLE}
707  ${ZEPHYR_BASE}/scripts/build/subfolder_list.py
708  --directory        ${ZEPHYR_BASE}/include      # Walk this directory
709  --out-file         ${syscalls_subdirs_txt}     # Write file with discovered folder
710  --trigger-file     ${syscalls_subdirs_trigger} # Trigger file that is used for json generation
711  ${syscalls_links}                              # If defined, create symlinks for dependencies
712)
713file(STRINGS ${syscalls_subdirs_txt} PARSE_SYSCALLS_PATHS_DEPENDS ENCODING UTF-8)
714
715if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows)
716  # On windows only adding/removing files or folders will be reflected in depends.
717  # Hence adding a file requires CMake to re-run to add this file to the file list.
718  set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PARSE_SYSCALLS_PATHS_DEPENDS})
719
720  # Also On Windows each header file must be monitored as file modifications are not reflected
721  # on directory level.
722  file(GLOB_RECURSE PARSE_SYSCALLS_HEADER_DEPENDS ${ZEPHYR_BASE}/include/*.h)
723else()
724  # The syscall parsing depends on the folders in order to detect add/removed/modified files.
725  # When a folder is removed, CMake will try to find a target that creates that dependency.
726  # This command sets up the target for CMake to find.
727  # Without this code, CMake will fail with the following error:
728  #   <folder> needed by '<target>', missing and no known rule to make it
729  # when a folder is removed.
730  add_custom_command(OUTPUT ${PARSE_SYSCALLS_PATHS_DEPENDS}
731    COMMAND ${CMAKE_COMMAND} -E echo ""
732    COMMENT "Preparing syscall dependency handling"
733  )
734
735  add_custom_command(
736    OUTPUT
737    ${syscalls_subdirs_trigger}
738    COMMAND
739    ${PYTHON_EXECUTABLE}
740    ${ZEPHYR_BASE}/scripts/build/subfolder_list.py
741    --directory        ${ZEPHYR_BASE}/include      # Walk this directory
742    --out-file         ${syscalls_subdirs_txt}     # Write file with discovered folder
743    --trigger-file     ${syscalls_subdirs_trigger} # Trigger file that is used for json generation
744    ${syscalls_links}                              # If defined, create symlinks for dependencies
745    DEPENDS ${PARSE_SYSCALLS_PATHS_DEPENDS}
746  )
747
748  # Ensure subdir file always exists when specifying CMake dependency.
749  if(NOT EXISTS ${syscalls_subdirs_txt})
750    file(WRITE ${syscalls_subdirs_txt} "")
751  endif()
752
753  # On other OS'es, modifying a file is reflected on the folder timestamp and hence detected
754  # when using depend on directory level.
755  # Thus CMake only needs to re-run when sub-directories are added / removed, which is indicated
756  # using a trigger file.
757  set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${syscalls_subdirs_txt})
758endif()
759
760# syscall declarations are searched for in the SYSCALL_INCLUDE_DIRS
761if(CONFIG_APPLICATION_DEFINED_SYSCALL)
762  list(APPEND SYSCALL_INCLUDE_DIRS ${APPLICATION_SOURCE_DIR})
763endif()
764
765if(CONFIG_ZTEST)
766  list(APPEND SYSCALL_INCLUDE_DIRS ${ZEPHYR_BASE}/subsys/testsuite/ztest/include)
767
768  if(CONFIG_NO_OPTIMIZATIONS AND CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS)
769    message(WARNING "Running tests with CONFIG_NO_OPTIMIZATIONS is generally "
770    "not supported and known to break in many cases due to stack overflow or "
771    "other problems. Please do not file issues about it unless the test is "
772    "specifically tuned to run in this configuration. To disable this warning "
773    "set CONFIG_ZTEST_WARN_NO_OPTIMIZATIONS=n.")
774  endif()
775
776endif()
777
778get_property(
779  syscalls_include_list
780  TARGET syscalls_interface
781  PROPERTY INTERFACE_INCLUDE_DIRECTORIES
782)
783list(APPEND SYSCALL_INCLUDE_DIRS ${syscalls_include_list})
784
785foreach(d ${SYSCALL_INCLUDE_DIRS})
786  list(APPEND parse_syscalls_include_args
787    --include ${d}
788    )
789endforeach()
790
791add_custom_command(
792  OUTPUT
793  ${syscalls_json}
794  ${struct_tags_json}
795  COMMAND
796  ${PYTHON_EXECUTABLE}
797  ${ZEPHYR_BASE}/scripts/build/parse_syscalls.py
798  --scan             ${ZEPHYR_BASE}/include         # Read files from this dir
799  --scan             ${ZEPHYR_BASE}/drivers         # For net sockets
800  --scan             ${ZEPHYR_BASE}/subsys/net      # More net sockets
801  ${parse_syscalls_include_args}                    # Read files from these dirs also
802  --json-file        ${syscalls_json}               # Write this file
803  --tag-struct-file  ${struct_tags_json}            # Write subsystem list to this file
804  --file-list        ${syscalls_file_list_output}
805  $<$<BOOL:${CONFIG_EMIT_ALL_SYSCALLS}>:--emit-all-syscalls>
806  DEPENDS ${syscalls_subdirs_trigger} ${PARSE_SYSCALLS_HEADER_DEPENDS}
807          ${syscalls_file_list_output} ${syscalls_interface}
808  )
809
810# Make sure Picolibc is built before the rest of the system; there's no explicit
811# reference to any of the files as they're all picked up by various compiler
812# settings
813if(CONFIG_PICOLIBC_USE_MODULE)
814  set(picolibc_dependency PicolibcBuild)
815endif()
816
817add_custom_target(${SYSCALL_LIST_H_TARGET} DEPENDS ${syscall_list_h} ${picolibc_dependency})
818
819set_property(TARGET ${SYSCALL_LIST_H_TARGET}
820             APPEND PROPERTY
821             ADDITIONAL_CLEAN_FILES
822             ${CMAKE_CURRENT_BINARY_DIR}/include/generated/zephyr/syscalls
823)
824
825add_custom_target(${PARSE_SYSCALLS_TARGET}
826  DEPENDS
827  ${syscalls_json}
828  ${struct_tags_json}
829  )
830
831# 64-bit systems do not require special handling of 64-bit system call
832# parameters or return values, indicate this to the system call boilerplate
833# generation script.
834if(CONFIG_64BIT)
835  set(SYSCALL_LONG_REGISTERS_ARG --long-registers)
836endif()
837
838if(CONFIG_TIMEOUT_64BIT)
839  set(SYSCALL_SPLIT_TIMEOUT_ARG --split-type k_timeout_t --split-type k_ticks_t)
840endif()
841
842# percepio/TraceRecorder/kernelports/Zephyr/scripts/tz_parse_syscalls.py hardcodes the path
843# to the `syscall_list.h`, make a copy of the generated file so that percepio is able to build
844if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH)
845  set(LEGACY_SYSCALL_LIST_H_ARGS
846    ${CMAKE_COMMAND} -E copy
847    ${syscall_list_h}
848    ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h)
849endif()
850
851add_custom_command(
852  OUTPUT
853  include/generated/zephyr/syscall_dispatch.c
854  include/generated/zephyr/syscall_exports_llext.c
855  syscall_weakdefs_llext.c
856  ${syscall_list_h}
857  # Also, some files are written to include/generated/zephyr/syscalls/
858  COMMAND
859  ${PYTHON_EXECUTABLE}
860  ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py
861  --json-file        ${syscalls_json}                     # Read this file
862  --base-output      include/generated/zephyr/syscalls    # Write to this dir
863  --syscall-dispatch include/generated/zephyr/syscall_dispatch.c # Write this file
864  --syscall-exports-llext  include/generated/zephyr/syscall_exports_llext.c
865  --syscall-weakdefs-llext syscall_weakdefs_llext.c # compiled in CMake library 'syscall_weakdefs'
866  --syscall-list     ${syscall_list_h}
867  $<$<BOOL:${CONFIG_USERSPACE}>:--gen-mrsh-files>
868  ${SYSCALL_LONG_REGISTERS_ARG}
869  ${SYSCALL_SPLIT_TIMEOUT_ARG}
870  COMMAND
871  ${LEGACY_SYSCALL_LIST_H_ARGS}
872  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
873  DEPENDS ${PARSE_SYSCALLS_TARGET}
874  )
875
876# This is passed into all calls to the gen_kobject_list.py script.
877set(gen_kobject_list_include_args --include-subsystem-list ${struct_tags_json})
878
879set(DRV_VALIDATION ${PROJECT_BINARY_DIR}/include/generated/zephyr/driver-validation.h)
880add_custom_command(
881  OUTPUT ${DRV_VALIDATION}
882  COMMAND
883  ${PYTHON_EXECUTABLE}
884  ${ZEPHYR_BASE}/scripts/build/gen_kobject_list.py
885  --validation-output ${DRV_VALIDATION}
886  ${gen_kobject_list_include_args}
887  $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
888  DEPENDS
889  ${ZEPHYR_BASE}/scripts/build/gen_kobject_list.py
890  ${PARSE_SYSCALLS_TARGET}
891  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
892  )
893add_custom_target(${DRIVER_VALIDATION_H_TARGET} DEPENDS ${DRV_VALIDATION})
894
895include(${ZEPHYR_BASE}/cmake/kobj.cmake)
896gen_kobj(KOBJ_INCLUDE_PATH)
897
898# Generate sections for kernel device subsystems
899set(
900  DEVICE_API_LD_SECTIONS
901  ${CMAKE_CURRENT_BINARY_DIR}/include/generated/device-api-sections.ld
902  )
903
904set(DEVICE_API_LINKER_SECTIONS_CMAKE
905    ${CMAKE_CURRENT_BINARY_DIR}/include/generated/device-api-sections.cmake
906)
907
908add_custom_command(
909  OUTPUT ${DEVICE_API_LD_SECTIONS} ${DEVICE_API_LINKER_SECTIONS_CMAKE}
910  COMMAND
911    ${PYTHON_EXECUTABLE}
912    ${ZEPHYR_BASE}/scripts/build/gen_iter_sections.py
913    --alignment ${CONFIG_LINKER_ITERABLE_SUBALIGN}
914    --input ${struct_tags_json}
915    --tag __subsystem
916    --ld-output ${DEVICE_API_LD_SECTIONS}
917    --cmake-output ${DEVICE_API_LINKER_SECTIONS_CMAKE}
918  DEPENDS
919    ${ZEPHYR_BASE}/scripts/build/gen_iter_sections.py
920    ${struct_tags_json}
921  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
922  )
923
924add_custom_target(${DEVICE_API_LD_TARGET}
925                  DEPENDS ${DEVICE_API_LD_SECTIONS}
926                          ${DEVICE_API_LINKER_SECTIONS_CMAKE}
927)
928
929# Add a pseudo-target that is up-to-date when all generated headers
930# are up-to-date.
931
932add_custom_target(zephyr_generated_headers)
933add_dependencies(zephyr_generated_headers
934  offsets_h version_h
935  )
936
937# Generate offsets.c.obj from offsets.c
938# Generate offsets.h     from offsets.c.obj
939
940set(OFFSETS_LIB offsets)
941
942set(OFFSETS_C_PATH ${ARCH_DIR}/${ARCH}/core/offsets/offsets.c)
943set(OFFSETS_H_PATH ${PROJECT_BINARY_DIR}/include/generated/zephyr/offsets.h)
944
945add_library(          ${OFFSETS_LIB} OBJECT ${OFFSETS_C_PATH})
946target_include_directories(${OFFSETS_LIB} PRIVATE
947  kernel/include
948  ${ARCH_DIR}/${ARCH}/include
949  )
950
951# Make sure that LTO will never be enabled when compiling offsets.c
952set_source_files_properties(${OFFSETS_C_PATH} PROPERTIES COMPILE_OPTIONS $<TARGET_PROPERTY:compiler,prohibit_lto>)
953
954target_link_libraries(${OFFSETS_LIB} zephyr_interface)
955add_dependencies(zephyr_interface
956  ${SYSCALL_LIST_H_TARGET}
957  ${DRIVER_VALIDATION_H_TARGET}
958  ${KOBJ_TYPES_H_TARGET}
959  ${DEVICE_API_LD_TARGET}
960  )
961
962add_custom_command(
963  OUTPUT ${OFFSETS_H_PATH}
964  COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_offset_header.py
965  -i $<TARGET_OBJECTS:${OFFSETS_LIB}>
966  -o ${OFFSETS_H_PATH}
967  DEPENDS
968  ${OFFSETS_LIB}
969  $<TARGET_OBJECTS:${OFFSETS_LIB}>
970)
971add_custom_target(${OFFSETS_H_TARGET} DEPENDS ${OFFSETS_H_PATH})
972
973zephyr_get_include_directories_for_lang(C ZEPHYR_INCLUDES)
974
975add_subdirectory(kernel)
976
977get_property(
978  syscalls_file_list
979  TARGET syscalls_interface
980  PROPERTY INTERFACE_SOURCES
981)
982file(CONFIGURE OUTPUT ${syscalls_file_list_output}
983     CONTENT "@syscalls_file_list@" @ONLY)
984
985# Read list content
986get_property(ZEPHYR_LIBS_PROPERTY GLOBAL PROPERTY ZEPHYR_LIBS)
987
988foreach(zephyr_lib ${ZEPHYR_LIBS_PROPERTY})
989  get_property(lib_type     TARGET ${zephyr_lib} PROPERTY TYPE)
990  # To prevent CMake failure when a driver is enabled, for example: REGULATOR=y
991  # we disable any Zephyr libraries without sources and adds the `empty_file.c`.
992  if(${lib_type} STREQUAL STATIC_LIBRARY
993     AND NOT ${zephyr_lib} STREQUAL app
994  )
995    get_property(source_list  TARGET ${zephyr_lib} PROPERTY SOURCES)
996    get_property(lib_imported TARGET ${zephyr_lib} PROPERTY IMPORTED)
997    if(NOT source_list
998       AND NOT ${lib_imported}
999    )
1000      get_property(allow_empty TARGET ${zephyr_lib} PROPERTY ALLOW_EMPTY)
1001      if(NOT "${allow_empty}")
1002        message(WARNING
1003          "No SOURCES given to Zephyr library: ${zephyr_lib}\nExcluding target from build."
1004        )
1005      endif()
1006      target_sources(${zephyr_lib} PRIVATE ${ZEPHYR_BASE}/misc/empty_file.c)
1007      set_property(TARGET ${zephyr_lib} PROPERTY EXCLUDE_FROM_ALL TRUE)
1008      list(REMOVE_ITEM ZEPHYR_LIBS_PROPERTY ${zephyr_lib})
1009      continue()
1010    endif()
1011  endif()
1012
1013  # TODO: Could this become an INTERFACE property of zephyr_interface?
1014  add_dependencies(${zephyr_lib} zephyr_generated_headers)
1015endforeach()
1016
1017if(CONFIG_KERNEL_WHOLE_ARCHIVE)
1018  set(WHOLE_ARCHIVE_LIBS ${ZEPHYR_LIBS_PROPERTY} kernel)
1019else()
1020  set(WHOLE_ARCHIVE_LIBS ${ZEPHYR_LIBS_PROPERTY})
1021  set(NO_WHOLE_ARCHIVE_LIBS kernel)
1022endif()
1023
1024if(CONFIG_LLEXT)
1025  # LLEXT exports symbols for all syscalls, including unimplemented ones.
1026  # Weak definitions for these must be added at the end of the link order
1027  # to avoid shadowing actual implementations.
1028  add_library(syscall_weakdefs syscall_weakdefs_llext.c)
1029  add_dependencies(syscall_weakdefs zephyr_generated_headers)
1030  target_link_libraries(syscall_weakdefs zephyr_interface)
1031  list(APPEND NO_WHOLE_ARCHIVE_LIBS syscall_weakdefs)
1032endif()
1033
1034get_property(OUTPUT_FORMAT        GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT)
1035
1036if (CONFIG_CODE_DATA_RELOCATION)
1037  set(CODE_RELOCATION_DEP code_relocation_source_lib)
1038endif() # CONFIG_CODE_DATA_RELOCATION
1039
1040# Give the linker script targets all of the include directories so
1041# that cmake can successfully find the linker scripts' header
1042# dependencies.
1043zephyr_get_include_directories_for_lang(C
1044  ZEPHYR_INCLUDE_DIRS
1045  STRIP_PREFIX # Don't use a -I prefix
1046  )
1047
1048if(CONFIG_DEVICE_DEPS)
1049  if(CONFIG_DEVICE_DEPS_DYNAMIC)
1050    set(dynamic_deps --dynamic-deps)
1051  endif()
1052
1053  if(CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC)
1054    set(number_of_dynamic_devices ${CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM})
1055  else()
1056    set(number_of_dynamic_devices 0)
1057  endif()
1058
1059  # device_deps.c is generated from ${ZEPHYR_LINK_STAGE_EXECUTABLE} by
1060  # gen_device_deps.py
1061  add_custom_command(
1062    OUTPUT device_deps.c
1063    COMMAND
1064    ${PYTHON_EXECUTABLE}
1065    ${ZEPHYR_BASE}/scripts/build/gen_device_deps.py
1066    --output-source device_deps.c
1067    --output-graphviz dev_graph.dot
1068    ${dynamic_deps}
1069    --num-dynamic-devices ${number_of_dynamic_devices}
1070    --kernel $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}>
1071    --zephyr-base ${ZEPHYR_BASE}
1072    --start-symbol "$<TARGET_PROPERTY:linker,devices_start_symbol>"
1073    VERBATIM
1074    DEPENDS ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1075    )
1076  set_property(GLOBAL APPEND PROPERTY GENERATED_APP_SOURCE_FILES device_deps.c)
1077
1078  # gen_device_deps runs on `__device_deps_pass1` so pass this info to the linker script generator
1079  list(APPEND LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE "LINKER_DEVICE_DEPS_PASS1")
1080endif()
1081
1082if(CONFIG_CODE_DATA_RELOCATION)
1083  # @Intent: Linker script to relocate .text, data and .bss sections
1084  toolchain_ld_relocation()
1085endif()
1086
1087if(CONFIG_USERSPACE)
1088  zephyr_get_compile_options_for_lang_as_string(C compiler_flags_priv)
1089  string(REPLACE "$<TARGET_PROPERTY:compiler,coverage>" ""
1090         NO_COVERAGE_FLAGS "${compiler_flags_priv}"
1091  )
1092
1093  set(GEN_KOBJ_LIST ${ZEPHYR_BASE}/scripts/build/gen_kobject_list.py)
1094  set(PROCESS_GPERF ${ZEPHYR_BASE}/scripts/build/process_gperf.py)
1095endif()
1096
1097# @Intent: Obtain compiler specific flag for specifying the c standard
1098zephyr_compile_options(
1099  $<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,cstd>${CSTD}>
1100)
1101set(CMAKE_C_COMPILE_FEATURES ${CMAKE_C_COMPILE_FEATURES} PARENT_SCOPE)
1102
1103# @Intent: Configure linker scripts, i.e. generate linker scripts with variables substituted
1104toolchain_ld_configure_files()
1105
1106get_property(TOPT GLOBAL PROPERTY TOPT)
1107get_property(COMPILER_TOPT TARGET compiler PROPERTY linker_script)
1108set_ifndef(  TOPT "${COMPILER_TOPT}")
1109set_ifndef(  TOPT -Wl,-T) # Use this if the compiler driver doesn't set a value
1110
1111if(CONFIG_HAVE_CUSTOM_LINKER_SCRIPT)
1112  set(LINKER_SCRIPT ${APPLICATION_SOURCE_DIR}/${CONFIG_CUSTOM_LINKER_SCRIPT})
1113  if(NOT EXISTS ${LINKER_SCRIPT})
1114    set(LINKER_SCRIPT ${CONFIG_CUSTOM_LINKER_SCRIPT})
1115    assert_exists(CONFIG_CUSTOM_LINKER_SCRIPT)
1116  endif()
1117elseif(DEFINED BOARD_LINKER_SCRIPT)
1118  set(LINKER_SCRIPT ${BOARD_LINKER_SCRIPT})
1119elseif(DEFINED SOC_LINKER_SCRIPT)
1120  set(LINKER_SCRIPT ${SOC_LINKER_SCRIPT})
1121else()
1122  find_package(Deprecated COMPONENTS SEARCHED_LINKER_SCRIPT)
1123endif()
1124
1125if(NOT EXISTS ${LINKER_SCRIPT})
1126  message(FATAL_ERROR "Could not find linker script: '${LINKER_SCRIPT}'. Corrupted configuration?")
1127endif()
1128
1129if(CONFIG_USERSPACE)
1130  set(APP_SMEM_ALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_aligned.ld")
1131  set(APP_SMEM_UNALIGNED_LD "${PROJECT_BINARY_DIR}/include/generated/app_smem_unaligned.ld")
1132
1133  if(CONFIG_LINKER_USE_PINNED_SECTION)
1134    set(APP_SMEM_PINNED_ALIGNED_LD
1135        "${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_aligned.ld")
1136    set(APP_SMEM_PINNED_UNALIGNED_LD
1137        "${PROJECT_BINARY_DIR}/include/generated/app_smem_pinned_unaligned.ld")
1138
1139    if(NOT CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT)
1140      # The libc partition may hold symbols that are required during boot process,
1141      # for example, stack guard (if enabled). So the libc partition must be pinned
1142      # if not sections are in physical memory at boot, as the paging mechanism is
1143      # only initialized post-kernel.
1144      set_property(TARGET app_smem APPEND PROPERTY pinned_partitions "z_libc_partition")
1145    endif()
1146
1147    get_property(APP_SMEM_PINNED_PARTITION_LIST TARGET app_smem PROPERTY pinned_partitions)
1148    if(APP_SMEM_PINNED_PARTITION_LIST)
1149      list(JOIN APP_SMEM_PINNED_PARTITION_LIST "," APP_SMEM_PINNED_PARTITION_LIST_ARG_CSL)
1150      set(APP_SMEM_PINNED_PARTITION_LIST_ARG "--pinpartitions=${APP_SMEM_PINNED_PARTITION_LIST_ARG_CSL}")
1151    endif()
1152  endif()
1153
1154  set(OBJ_FILE_DIR "${PROJECT_BINARY_DIR}/../")
1155
1156  if(CONFIG_NEWLIB_LIBC)
1157    set(LIBC_PART -l libc.a z_libc_partition -l libm.a z_libc_partition)
1158  endif()
1159  if(CONFIG_NEWLIB_LIBC_NANO)
1160    set(LIBC_PART -l libc_nano.a z_libc_partition -l libm_nano.a z_libc_partition)
1161  endif()
1162  if(CONFIG_PICOLIBC)
1163    set(LIBC_PART -l libc.a z_libc_partition)
1164  endif()
1165
1166  add_custom_command(
1167    OUTPUT ${APP_SMEM_UNALIGNED_LD} ${APP_SMEM_PINNED_UNALIGNED_LD}
1168    COMMAND ${PYTHON_EXECUTABLE}
1169    ${ZEPHYR_BASE}/scripts/build/gen_app_partitions.py
1170    -f ${CMAKE_BINARY_DIR}/compile_commands.json
1171    -o ${APP_SMEM_UNALIGNED_LD}
1172    $<$<BOOL:${APP_SMEM_PINNED_UNALIGNED_LD}>:--pinoutput=${APP_SMEM_PINNED_UNALIGNED_LD}>
1173    ${APP_SMEM_PINNED_PARTITION_LIST_ARG}
1174    ${LIBC_PART}
1175    $<TARGET_PROPERTY:zephyr_property_target,COMPILE_OPTIONS>
1176    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
1177    DEPENDS
1178    kernel
1179    ${CMAKE_BINARY_DIR}/compile_commands.json
1180    ${ZEPHYR_LIBS_PROPERTY}
1181    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/
1182    COMMAND_EXPAND_LISTS
1183    COMMENT "Generating app_smem_unaligned linker section"
1184    )
1185
1186  add_custom_target(
1187    ${APP_SMEM_ALIGNED_DEP}
1188    DEPENDS
1189    ${APP_SMEM_ALIGNED_LD}
1190    ${APP_SMEM_PINNED_ALIGNED_LD}
1191    )
1192
1193  add_custom_target(
1194    ${APP_SMEM_UNALIGNED_DEP}
1195    DEPENDS
1196    ${APP_SMEM_UNALIGNED_LD}
1197    ${APP_SMEM_PINNED_UNALIGNED_LD}
1198    )
1199
1200  set(APP_SMEM_UNALIGNED_LIB app_smem_unaligned_output_obj_renamed_lib)
1201  list(APPEND LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE "LINKER_APP_SMEM_UNALIGNED")
1202endif()
1203
1204if (CONFIG_USERSPACE)
1205  add_custom_command(
1206    OUTPUT ${APP_SMEM_ALIGNED_LD} ${APP_SMEM_PINNED_ALIGNED_LD}
1207    COMMAND ${PYTHON_EXECUTABLE}
1208    ${ZEPHYR_BASE}/scripts/build/gen_app_partitions.py
1209    -e $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}>
1210    -o ${APP_SMEM_ALIGNED_LD}
1211    $<$<BOOL:${APP_SMEM_PINNED_ALIGNED_LD}>:--pinoutput=${APP_SMEM_PINNED_ALIGNED_LD}>
1212    ${APP_SMEM_PINNED_PARTITION_LIST_ARG}
1213    ${LIBC_PART}
1214    $<TARGET_PROPERTY:zephyr_property_target,COMPILE_OPTIONS>
1215    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
1216    DEPENDS
1217    kernel
1218    ${ZEPHYR_LIBS_PROPERTY}
1219    ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1220    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/
1221    COMMAND_EXPAND_LISTS
1222    COMMENT "Generating app_smem_aligned linker section"
1223    )
1224endif()
1225
1226if(CONFIG_USERSPACE)
1227  # This CONFIG_USERSPACE block is to create place holders to reserve space
1228  # for the gperf generated structures for zephyr_prebuilt.elf.
1229  # These place holders are there so that the placement of kobjects would be
1230  # the same between linking zephyr_prebuilt.elf and zephyr.elf, as
1231  # the gperf hash table is hashed on the addresses of kobjects.
1232  # The placeholders are generated from app_smem_unaligned_prebuilt.elf.
1233
1234  set(KOBJECT_PREBUILT_HASH_LIST           kobject_prebuilt_hash.gperf)
1235  set(KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE kobject_prebuilt_hash_preprocessed.c)
1236  set(KOBJECT_PREBUILT_HASH_OUTPUT_SRC     kobject_prebuilt_hash.c)
1237
1238  add_custom_command(
1239    OUTPUT ${KOBJECT_PREBUILT_HASH_LIST}
1240    COMMAND
1241    ${PYTHON_EXECUTABLE}
1242    ${GEN_KOBJ_LIST}
1243    --kernel $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}>
1244    --gperf-output ${KOBJECT_PREBUILT_HASH_LIST}
1245    ${gen_kobject_list_include_args}
1246    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
1247    DEPENDS
1248    ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1249    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1250    )
1251  add_custom_target(
1252    kobj_prebuilt_hash_list
1253    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_LIST}
1254  )
1255
1256  add_custom_command(
1257    OUTPUT ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE}
1258    COMMAND
1259    ${GPERF}
1260    --output-file ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE}
1261    --multiple-iterations 10
1262    ${KOBJECT_PREBUILT_HASH_LIST}
1263    DEPENDS kobj_prebuilt_hash_list ${KOBJECT_PREBUILT_HASH_LIST}
1264    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1265    )
1266  add_custom_target(
1267    kobj_prebuilt_hash_output_src_pre
1268    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE}
1269  )
1270
1271  add_custom_command(
1272    OUTPUT ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC}
1273    COMMAND
1274    ${PYTHON_EXECUTABLE}
1275    ${PROCESS_GPERF}
1276    -i ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE}
1277    -o ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC}
1278    -p "struct k_object"
1279    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
1280    DEPENDS kobj_prebuilt_hash_output_src_pre ${KOBJECT_PREBUILT_HASH_OUTPUT_SRC_PRE}
1281    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1282    )
1283  add_custom_target(
1284    kobj_prebuilt_hash_output_src
1285    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_OUTPUT_SRC}
1286  )
1287
1288  add_library(
1289    kobj_prebuilt_hash_output_lib
1290    OBJECT ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_PREBUILT_HASH_OUTPUT_SRC}
1291    )
1292
1293  set_source_files_properties(${KOBJECT_PREBUILT_HASH_OUTPUT_SRC}
1294    PROPERTIES COMPILE_FLAGS
1295    "${NO_COVERAGE_FLAGS} -fno-function-sections -fno-data-sections")
1296
1297  target_compile_definitions(kobj_prebuilt_hash_output_lib
1298    PRIVATE $<TARGET_PROPERTY:zephyr_interface,INTERFACE_COMPILE_DEFINITIONS>
1299  )
1300
1301  target_include_directories(kobj_prebuilt_hash_output_lib
1302    PUBLIC $<TARGET_PROPERTY:zephyr_interface,INTERFACE_INCLUDE_DIRECTORIES>
1303  )
1304
1305  target_include_directories(kobj_prebuilt_hash_output_lib SYSTEM
1306    PUBLIC $<TARGET_PROPERTY:zephyr_interface,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
1307  )
1308
1309  set(KOBJECT_LINKER_HEADER_DATA "${PROJECT_BINARY_DIR}/include/generated/zephyr/linker-kobject-prebuilt-data.h")
1310
1311  add_custom_command(
1312    OUTPUT ${KOBJECT_LINKER_HEADER_DATA}
1313    COMMAND
1314    ${PYTHON_EXECUTABLE}
1315    ${ZEPHYR_BASE}/scripts/build/gen_kobject_placeholders.py
1316    --object $<TARGET_OBJECTS:kobj_prebuilt_hash_output_lib>
1317    --outdir ${PROJECT_BINARY_DIR}/include/generated/zephyr
1318    --datapct ${CONFIG_KOBJECT_DATA_AREA_RESERVE_EXTRA_PERCENT}
1319    --rodata ${CONFIG_KOBJECT_RODATA_AREA_EXTRA_BYTES}
1320    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
1321    DEPENDS
1322    kobj_prebuilt_hash_output_lib $<TARGET_OBJECTS:kobj_prebuilt_hash_output_lib>
1323    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1324    )
1325
1326  add_custom_target(
1327    ${KOBJECT_LINKER_DEP}
1328    DEPENDS
1329    ${KOBJECT_LINKER_HEADER_DATA}
1330  )
1331endif()
1332
1333if(CONFIG_USERSPACE OR CONFIG_DEVICE_DEPS)
1334  configure_linker_script(
1335    ${ZEPHYR_CURRENT_LINKER_CMD}
1336    "${LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE}"
1337    ${CODE_RELOCATION_DEP}
1338    ${APP_SMEM_UNALIGNED_DEP}
1339    ${APP_SMEM_UNALIGNED_LD}
1340    ${APP_SMEM_PINNED_UNALIGNED_LD}
1341    zephyr_generated_headers
1342    )
1343
1344  add_custom_target(
1345    linker_zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS}_script
1346    DEPENDS
1347    ${ZEPHYR_CURRENT_LINKER_CMD}
1348    )
1349
1350  set_property(TARGET
1351    linker_zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS}_script
1352    PROPERTY INCLUDE_DIRECTORIES
1353    ${ZEPHYR_INCLUDE_DIRS}
1354    )
1355
1356  add_executable(${ZEPHYR_LINK_STAGE_EXECUTABLE} misc/empty_file.c)
1357  toolchain_ld_link_elf(
1358    TARGET_ELF            ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1359    OUTPUT_MAP            ${PROJECT_BINARY_DIR}/${ZEPHYR_LINK_STAGE_EXECUTABLE}.map
1360    LIBRARIES_PRE_SCRIPT  ""
1361    LINKER_SCRIPT         ${PROJECT_BINARY_DIR}/${ZEPHYR_CURRENT_LINKER_CMD}
1362    LIBRARIES_POST_SCRIPT ""
1363    DEPENDENCIES          ${CODE_RELOCATION_DEP}
1364  )
1365  target_link_libraries_ifdef(CONFIG_NATIVE_LIBRARY ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1366                              $<TARGET_PROPERTY:linker,no_position_independent>)
1367  target_byproducts(TARGET ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1368                    BYPRODUCTS ${PROJECT_BINARY_DIR}/${ZEPHYR_LINK_STAGE_EXECUTABLE}.map
1369  )
1370  set_property(TARGET ${ZEPHYR_LINK_STAGE_EXECUTABLE} PROPERTY LINK_DEPENDS ${PROJECT_BINARY_DIR}/${ZEPHYR_CURRENT_LINKER_CMD})
1371  add_dependencies(${ZEPHYR_LINK_STAGE_EXECUTABLE} linker_zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS}_script ${OFFSETS_LIB})
1372
1373  math(EXPR ZEPHYR_CURRENT_LINKER_PASS "1 + ${ZEPHYR_CURRENT_LINKER_PASS}")
1374endif()
1375
1376set(ZEPHYR_CURRENT_LINKER_CMD  linker_zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS}.cmd)
1377set(ZEPHYR_LINK_STAGE_EXECUTABLE zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS})
1378list(APPEND LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE "LINKER_ZEPHYR_PREBUILT")
1379
1380if(CONFIG_GEN_ISR_TABLES)
1381  if(CONFIG_GEN_SW_ISR_TABLE)
1382    list(APPEND GEN_ISR_TABLE_EXTRA_ARG --sw-isr-table)
1383  endif()
1384
1385  if(CONFIG_GEN_IRQ_VECTOR_TABLE)
1386    list(APPEND GEN_ISR_TABLE_EXTRA_ARG --vector-table)
1387  endif()
1388
1389  # isr_tables.c is generated from ${ZEPHYR_LINK_STAGE_EXECUTABLE} by
1390  # gen_isr_tables.py
1391  add_custom_command(
1392    OUTPUT isr_tables.c isr_tables_vt.ld isr_tables_swi.ld
1393    COMMAND ${PYTHON_EXECUTABLE}
1394    ${ZEPHYR_BASE}/scripts/build/gen_isr_tables.py
1395    --output-source isr_tables.c
1396    --linker-output-files isr_tables_vt.ld isr_tables_swi.ld
1397    --kernel $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}>
1398    --intlist-section .intList
1399    --intlist-section intList
1400    $<$<BOOL:${CONFIG_BIG_ENDIAN}>:--big-endian>
1401    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--debug>
1402    ${GEN_ISR_TABLE_EXTRA_ARG}
1403    DEPENDS ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1404    COMMAND_EXPAND_LISTS
1405    )
1406  set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES isr_tables.c)
1407endif()
1408
1409if(CONFIG_SYMTAB)
1410  add_custom_command(
1411    OUTPUT symtab.c
1412    COMMAND
1413    ${PYTHON_EXECUTABLE}
1414    ${ZEPHYR_BASE}/scripts/build/gen_symtab.py
1415    -k $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}>
1416    -o symtab.c
1417    DEPENDS ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1418    COMMAND_EXPAND_LISTS
1419  )
1420  set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES symtab.c)
1421endif()
1422
1423if(CONFIG_USERSPACE)
1424  set(KOBJECT_HASH_LIST               kobject_hash.gperf)
1425  set(KOBJECT_HASH_OUTPUT_SRC_PRE     kobject_hash_preprocessed.c)
1426  set(KOBJECT_HASH_OUTPUT_SRC         kobject_hash.c)
1427  set(KOBJECT_HASH_OUTPUT_OBJ_RENAMED kobject_hash_renamed.o)
1428
1429  # Essentially what we are doing here is extracting some information
1430  # out of the nearly finished elf file, generating the source code
1431  # for a hash table based on that information, and then compiling and
1432  # linking the hash table back into a now even more nearly finished
1433  # elf file. More information in gen_kobject_list.py --help.
1434
1435  # Use the script GEN_KOBJ_LIST to scan the kernel binary's
1436  # (${ZEPHYR_LINK_STAGE_EXECUTABLE}) DWARF information to produce a table of kernel
1437  # objects (KOBJECT_HASH_LIST) which we will then pass to gperf
1438  add_custom_command(
1439    OUTPUT ${KOBJECT_HASH_LIST}
1440    COMMAND
1441    ${PYTHON_EXECUTABLE}
1442    ${GEN_KOBJ_LIST}
1443    --kernel $<TARGET_FILE:${ZEPHYR_LINK_STAGE_EXECUTABLE}>
1444    --gperf-output ${KOBJECT_HASH_LIST}
1445    ${gen_kobject_list_include_args}
1446    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
1447    DEPENDS
1448    ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1449    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1450    )
1451  add_custom_target(
1452    kobj_hash_list
1453    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_LIST}
1454  )
1455
1456  # Use gperf to generate C code (KOBJECT_HASH_OUTPUT_SRC_PRE) which implements a
1457  # perfect hashtable based on KOBJECT_HASH_LIST
1458  add_custom_command(
1459    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_SRC_PRE}
1460    COMMAND
1461    ${GPERF}
1462    --output-file ${KOBJECT_HASH_OUTPUT_SRC_PRE}
1463    --multiple-iterations 10
1464    ${KOBJECT_HASH_LIST}
1465    DEPENDS kobj_hash_list ${KOBJECT_HASH_LIST}
1466    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1467    )
1468  add_custom_target(
1469    kobj_hash_output_src_pre
1470    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_SRC_PRE}
1471  )
1472
1473  # For our purposes the code/data generated by gperf is not optimal.
1474  #
1475  # The script PROCESS_GPERF creates a new c file KOBJECT_HASH_OUTPUT_SRC based on
1476  # KOBJECT_HASH_OUTPUT_SRC_PRE to greatly reduce the amount of code/data generated
1477  # since we know we are always working with pointer values
1478  add_custom_command(
1479    OUTPUT ${KOBJECT_HASH_OUTPUT_SRC}
1480    COMMAND
1481    ${PYTHON_EXECUTABLE}
1482    ${PROCESS_GPERF}
1483    -i ${KOBJECT_HASH_OUTPUT_SRC_PRE}
1484    -o ${KOBJECT_HASH_OUTPUT_SRC}
1485    -p "struct k_object"
1486    $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
1487    DEPENDS kobj_hash_output_src_pre ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_SRC_PRE}
1488    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1489    )
1490  add_custom_target(
1491    kobj_hash_output_src
1492    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_SRC}
1493  )
1494
1495  # We need precise control of where generated text/data ends up in the final
1496  # kernel image. Disable function/data sections and use objcopy to move
1497  # generated data into special section names
1498  add_library(
1499    kobj_hash_output_lib
1500    OBJECT ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_SRC}
1501    )
1502
1503  set_source_files_properties(${KOBJECT_HASH_OUTPUT_SRC}
1504    PROPERTIES COMPILE_FLAGS
1505    "${NO_COVERAGE_FLAGS} -fno-function-sections -fno-data-sections")
1506
1507  target_compile_definitions(kobj_hash_output_lib
1508    PRIVATE $<TARGET_PROPERTY:zephyr_interface,INTERFACE_COMPILE_DEFINITIONS>
1509  )
1510
1511  target_include_directories(kobj_hash_output_lib
1512    PUBLIC $<TARGET_PROPERTY:zephyr_interface,INTERFACE_INCLUDE_DIRECTORIES>
1513  )
1514
1515  target_include_directories(kobj_hash_output_lib SYSTEM
1516    PUBLIC $<TARGET_PROPERTY:zephyr_interface,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
1517  )
1518
1519  add_custom_command(
1520    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_OBJ_RENAMED}
1521    COMMAND $<TARGET_PROPERTY:bintools,elfconvert_command>
1522            $<TARGET_PROPERTY:bintools,elfconvert_flag>
1523            $<TARGET_PROPERTY:bintools,elfconvert_flag_section_rename>.literal=.kobject_data.literal
1524            $<TARGET_PROPERTY:bintools,elfconvert_flag_section_rename>.data=.kobject_data.data
1525            $<TARGET_PROPERTY:bintools,elfconvert_flag_section_rename>.sdata=.kobject_data.sdata
1526            $<TARGET_PROPERTY:bintools,elfconvert_flag_section_rename>.text=.kobject_data.text
1527            $<TARGET_PROPERTY:bintools,elfconvert_flag_section_rename>.rodata=.kobject_data.rodata
1528            $<TARGET_PROPERTY:bintools,elfconvert_flag_infile>$<TARGET_OBJECTS:kobj_hash_output_lib>
1529            $<TARGET_PROPERTY:bintools,elfconvert_flag_outfile>${KOBJECT_HASH_OUTPUT_OBJ_RENAMED}
1530            $<TARGET_PROPERTY:bintools,elfconvert_flag_final>
1531    DEPENDS kobj_hash_output_lib $<TARGET_OBJECTS:kobj_hash_output_lib>
1532    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
1533    COMMAND_EXPAND_LISTS
1534    )
1535  add_custom_target(
1536    kobj_hash_output_obj_renamed
1537    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_OBJ_RENAMED}
1538  )
1539
1540  add_library(kobj_hash_output_obj_renamed_lib STATIC IMPORTED GLOBAL)
1541  set_property(
1542    TARGET kobj_hash_output_obj_renamed_lib
1543    PROPERTY
1544    IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${KOBJECT_HASH_OUTPUT_OBJ_RENAMED}
1545    )
1546  add_dependencies(
1547    kobj_hash_output_obj_renamed_lib
1548    kobj_hash_output_obj_renamed
1549    )
1550
1551  set_property(
1552    GLOBAL APPEND PROPERTY
1553    GENERATED_KERNEL_OBJECT_FILES kobj_hash_output_obj_renamed_lib
1554  )
1555endif()
1556
1557configure_linker_script(
1558  ${ZEPHYR_CURRENT_LINKER_CMD}
1559  "${LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE}"
1560  ${APP_SMEM_ALIGNED_DEP}
1561  ${KOBJECT_LINKER_DEP}
1562  ${CODE_RELOCATION_DEP}
1563  zephyr_generated_headers
1564  )
1565
1566add_custom_target(
1567  linker_zephyr_prebuilt_script_target
1568  DEPENDS
1569  ${ZEPHYR_CURRENT_LINKER_CMD}
1570  )
1571
1572set_property(TARGET
1573  linker_zephyr_prebuilt_script_target
1574  PROPERTY INCLUDE_DIRECTORIES
1575  ${ZEPHYR_INCLUDE_DIRS}
1576  )
1577
1578# Read global variables into local variables
1579get_property(GASF GLOBAL PROPERTY GENERATED_APP_SOURCE_FILES)
1580get_property(GKOF GLOBAL PROPERTY GENERATED_KERNEL_OBJECT_FILES)
1581get_property(GKSF GLOBAL PROPERTY GENERATED_KERNEL_SOURCE_FILES)
1582
1583# FIXME: Is there any way to get rid of empty_file.c?
1584add_executable(       ${ZEPHYR_LINK_STAGE_EXECUTABLE} misc/empty_file.c ${GASF})
1585toolchain_ld_link_elf(
1586  TARGET_ELF            ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1587  OUTPUT_MAP            ${PROJECT_BINARY_DIR}/${ZEPHYR_LINK_STAGE_EXECUTABLE}.map
1588  LIBRARIES_PRE_SCRIPT  ""
1589  LINKER_SCRIPT         ${PROJECT_BINARY_DIR}/${ZEPHYR_CURRENT_LINKER_CMD}
1590  DEPENDENCIES          ${CODE_RELOCATION_DEP}
1591)
1592target_link_libraries_ifdef(CONFIG_NATIVE_LIBRARY ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1593                            $<TARGET_PROPERTY:linker,partial_linking>)
1594target_byproducts(TARGET ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1595                  BYPRODUCTS ${PROJECT_BINARY_DIR}/${ZEPHYR_LINK_STAGE_EXECUTABLE}.map
1596)
1597set(BYPRODUCT_KERNEL_ELF_NAME "${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}" CACHE FILEPATH "Kernel elf file" FORCE)
1598set_property(TARGET
1599  ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1600  PROPERTY LINK_DEPENDS ${PROJECT_BINARY_DIR}/${ZEPHYR_CURRENT_LINKER_CMD}
1601  )
1602add_dependencies(
1603  ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1604  linker_zephyr_prebuilt_script_target
1605  ${OFFSETS_LIB}
1606  )
1607
1608set(generated_kernel_files ${GKSF} ${GKOF})
1609if(NOT generated_kernel_files)
1610  # Use the prebuilt elf as the final elf since we don't have a
1611  # generation stage.
1612  set(logical_target_for_zephyr_elf ${ZEPHYR_LINK_STAGE_EXECUTABLE})
1613else()
1614  # The final linker pass uses the same source linker script of the
1615  # previous passes, but this time with a different output
1616  # file and preprocessed with the define LINKER_ZEPHYR_FINAL.
1617  configure_linker_script(
1618    linker.cmd
1619    "LINKER_ZEPHYR_FINAL"
1620    ${CODE_RELOCATION_DEP}
1621    ${ZEPHYR_LINK_STAGE_EXECUTABLE}
1622    zephyr_generated_headers
1623    )
1624
1625  add_custom_target(
1626    linker_zephyr_final_script_target
1627    DEPENDS
1628    linker.cmd
1629    )
1630  set_property(TARGET
1631    linker_zephyr_final_script_target
1632    PROPERTY INCLUDE_DIRECTORIES
1633    ${ZEPHYR_INCLUDE_DIRS}
1634  )
1635
1636  add_executable(       ${ZEPHYR_FINAL_EXECUTABLE} misc/empty_file.c ${GASF} ${GKSF})
1637  toolchain_ld_link_elf(
1638    TARGET_ELF            ${ZEPHYR_FINAL_EXECUTABLE}
1639    OUTPUT_MAP            ${PROJECT_BINARY_DIR}/${ZEPHYR_FINAL_EXECUTABLE}.map
1640    LIBRARIES_PRE_SCRIPT  ${GKOF}
1641    LINKER_SCRIPT         ${PROJECT_BINARY_DIR}/linker.cmd
1642    LIBRARIES_POST_SCRIPT ""
1643    DEPENDENCIES          ${CODE_RELOCATION_DEP}
1644  )
1645  set_property(TARGET   ${ZEPHYR_FINAL_EXECUTABLE} PROPERTY LINK_DEPENDS ${PROJECT_BINARY_DIR}/linker.cmd)
1646  add_dependencies(     ${ZEPHYR_FINAL_EXECUTABLE} linker_zephyr_final_script_target)
1647
1648  # Use the pass2 elf as the final elf
1649  set(logical_target_for_zephyr_elf ${ZEPHYR_FINAL_EXECUTABLE})
1650endif()
1651
1652# Export the variable to the application's scope to allow the
1653# application to know what the name of the final elf target is.
1654set(logical_target_for_zephyr_elf ${logical_target_for_zephyr_elf} PARENT_SCOPE)
1655
1656# Override the base name of the last, "logical" .elf output (and last .map) so:
1657# 1. it doesn't depend on the number of passes above and the
1658#    post_build_commands below can always find it no matter which is it;
1659# 2. it can be defined in Kconfig
1660set_target_properties(${logical_target_for_zephyr_elf} PROPERTIES OUTPUT_NAME ${KERNEL_NAME})
1661
1662set(post_build_commands "")
1663set(post_build_byproducts "")
1664
1665list(APPEND
1666  post_build_commands
1667  COMMAND
1668  ${CMAKE_COMMAND} -E copy ${logical_target_for_zephyr_elf}.map ${KERNEL_MAP_NAME}
1669)
1670list(APPEND post_build_byproducts ${KERNEL_MAP_NAME})
1671
1672# Use ';' as separator to get proper space in resulting command.
1673set(gap_fill_prop "$<TARGET_PROPERTY:bintools,elfconvert_flag_gapfill>")
1674set(gap_fill "$<$<BOOL:${gap_fill_prop}>:${gap_fill_prop}${CONFIG_BUILD_GAP_FILL_PATTERN}>")
1675
1676if(CONFIG_OUTPUT_PRINT_MEMORY_USAGE)
1677  target_link_libraries(${logical_target_for_zephyr_elf} $<TARGET_PROPERTY:linker,memusage>)
1678
1679  get_property(memusage_build_command TARGET bintools PROPERTY memusage_command)
1680  if(memusage_build_command)
1681    # Note: The use of generator expressions allows downstream extensions to add/change the post build.
1682    # Unfortunately, the BYPRODUCTS does not allow for generator expression, so question is if we
1683    # should remove the downstream ability from start.
1684    # Or fix the output name, by the use of `get_property`
1685    list(APPEND
1686      post_build_commands
1687      COMMAND $<TARGET_PROPERTY:bintools,memusage_command>
1688              $<TARGET_PROPERTY:bintools,memusage_flag>
1689              $<TARGET_PROPERTY:bintools,memusage_infile>${KERNEL_ELF_NAME}
1690      )
1691
1692    # For now, the byproduct can only be supported upstream on byproducts name,
1693    # cause byproduct does not support generator expressions
1694    get_property(memusage_byproducts TARGET bintools PROPERTY memusage_byproducts)
1695    list(APPEND
1696      post_build_byproducts
1697      ${memusage_byproducts}
1698      )
1699  endif()
1700endif()
1701
1702if(CONFIG_BUILD_OUTPUT_ADJUST_LMA)
1703  math(EXPR adjustment "${CONFIG_BUILD_OUTPUT_ADJUST_LMA}" OUTPUT_FORMAT DECIMAL)
1704  set(args_adjustment ${CONFIG_BUILD_OUTPUT_ADJUST_LMA_SECTIONS})
1705  list(TRANSFORM args_adjustment PREPEND $<TARGET_PROPERTY:bintools,elfconvert_flag_lma_adjust>)
1706  list(TRANSFORM args_adjustment APPEND +${adjustment})
1707  list(APPEND
1708    post_build_commands
1709    COMMAND $<TARGET_PROPERTY:bintools,elfconvert_command>
1710            $<TARGET_PROPERTY:bintools,elfconvert_flag_final>
1711            ${args_adjustment}
1712            $<TARGET_PROPERTY:bintools,elfconvert_flag_infile>${KERNEL_ELF_NAME}
1713            $<TARGET_PROPERTY:bintools,elfconvert_flag_outfile>${KERNEL_ELF_NAME}
1714    )
1715endif()
1716
1717if(NOT CONFIG_CPP_EXCEPTIONS)
1718  set(eh_frame_section ".eh_frame")
1719else()
1720  set(eh_frame_section "")
1721endif()
1722set(remove_sections_argument_list "")
1723foreach(section .comment COMMON ${eh_frame_section})
1724  list(APPEND remove_sections_argument_list
1725    $<TARGET_PROPERTY:bintools,elfconvert_flag_section_remove>${section})
1726endforeach()
1727
1728if(CONFIG_BUILD_OUTPUT_HEX OR BOARD_FLASH_RUNNER STREQUAL openocd)
1729  get_property(elfconvert_formats TARGET bintools PROPERTY elfconvert_formats)
1730  if(ihex IN_LIST elfconvert_formats)
1731    list(APPEND
1732      post_build_commands
1733      COMMAND $<TARGET_PROPERTY:bintools,elfconvert_command>
1734              $<TARGET_PROPERTY:bintools,elfconvert_flag>
1735              $<$<BOOL:${CONFIG_BUILD_OUTPUT_HEX_GAP_FILL}>:${gap_fill}>
1736              $<TARGET_PROPERTY:bintools,elfconvert_flag_outtarget>ihex
1737              ${remove_sections_argument_list}
1738              $<TARGET_PROPERTY:bintools,elfconvert_flag_infile>${KERNEL_ELF_NAME}
1739              $<TARGET_PROPERTY:bintools,elfconvert_flag_outfile>${KERNEL_HEX_NAME}
1740              $<TARGET_PROPERTY:bintools,elfconvert_flag_final>
1741      )
1742    list(APPEND
1743      post_build_byproducts
1744      ${KERNEL_HEX_NAME}
1745      )
1746    set(BYPRODUCT_KERNEL_HEX_NAME "${PROJECT_BINARY_DIR}/${KERNEL_HEX_NAME}" CACHE FILEPATH "Kernel hex file" FORCE)
1747  endif()
1748endif()
1749
1750if(CONFIG_BUILD_OUTPUT_BIN)
1751  get_property(elfconvert_formats TARGET bintools PROPERTY elfconvert_formats)
1752  if(binary IN_LIST elfconvert_formats)
1753    list(APPEND
1754      post_build_commands
1755      COMMAND $<TARGET_PROPERTY:bintools,elfconvert_command>
1756              $<TARGET_PROPERTY:bintools,elfconvert_flag>
1757              ${gap_fill}
1758              $<TARGET_PROPERTY:bintools,elfconvert_flag_outtarget>binary
1759              ${remove_sections_argument_list}
1760              $<TARGET_PROPERTY:bintools,elfconvert_flag_infile>${KERNEL_ELF_NAME}
1761              $<TARGET_PROPERTY:bintools,elfconvert_flag_outfile>${KERNEL_BIN_NAME}
1762              $<TARGET_PROPERTY:bintools,elfconvert_flag_final>
1763      )
1764    list(APPEND
1765      post_build_byproducts
1766      ${KERNEL_BIN_NAME}
1767      )
1768    set(BYPRODUCT_KERNEL_BIN_NAME "${PROJECT_BINARY_DIR}/${KERNEL_BIN_NAME}" CACHE FILEPATH "Kernel binary file" FORCE)
1769  endif()
1770endif()
1771
1772if(CONFIG_BUILD_OUTPUT_BIN AND CONFIG_BUILD_OUTPUT_UF2)
1773  if(CONFIG_BUILD_OUTPUT_UF2_USE_FLASH_BASE)
1774    set(flash_addr "${CONFIG_FLASH_BASE_ADDRESS}")
1775  else()
1776    set(flash_addr "${CONFIG_FLASH_LOAD_OFFSET}")
1777  endif()
1778
1779  if(CONFIG_BUILD_OUTPUT_UF2_USE_FLASH_OFFSET)
1780    # Note, the `+ 0` in formula below avoids errors in cases where a Kconfig
1781    #       variable is undefined and thus expands to nothing.
1782    math(EXPR flash_addr
1783        "${flash_addr} + ${CONFIG_FLASH_LOAD_OFFSET} + 0"
1784         OUTPUT_FORMAT HEXADECIMAL
1785    )
1786  endif()
1787
1788  list(APPEND
1789    post_build_commands
1790    COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/uf2conv.py
1791            -c
1792            -f ${CONFIG_BUILD_OUTPUT_UF2_FAMILY_ID}
1793            -b ${flash_addr}
1794            -o ${KERNEL_UF2_NAME}
1795            ${KERNEL_BIN_NAME}
1796  )
1797  list(APPEND
1798    post_build_byproducts
1799    ${KERNEL_UF2_NAME}
1800  )
1801  set(BYPRODUCT_KERNEL_UF2_NAME "${PROJECT_BINARY_DIR}/${KERNEL_UF2_NAME}" CACHE FILEPATH "Kernel uf2 file" FORCE)
1802endif()
1803
1804set(KERNEL_META_PATH  ${PROJECT_BINARY_DIR}/${KERNEL_META_NAME} CACHE INTERNAL "")
1805if(CONFIG_BUILD_OUTPUT_META)
1806  list(APPEND
1807    post_build_commands
1808    COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/zephyr_module.py
1809            ${ZEPHYR_MODULES_ARG}
1810            ${EXTRA_ZEPHYR_MODULES_ARG}
1811            --meta-out ${KERNEL_META_PATH}
1812            --zephyr-base=${ZEPHYR_BASE}
1813            $<$<BOOL:${CONFIG_BUILD_OUTPUT_META_STATE_PROPAGATE}>:--meta-state-propagate>
1814  )
1815  list(APPEND
1816    post_build_byproducts
1817    ${KERNEL_META_PATH}
1818  )
1819else(CONFIG_BUILD_OUTPUT_META)
1820  # Prevent spdx to use invalid data
1821  file(REMOVE ${KERNEL_META_PATH})
1822endif()
1823
1824# Cleanup intermediate files
1825if(CONFIG_CLEANUP_INTERMEDIATE_FILES)
1826  foreach(index RANGE ${ZEPHYR_CURRENT_LINKER_PASS})
1827    # Those files can be very large in some cases, delete them as we do not need them.
1828    list(APPEND
1829      post_build_commands
1830      COMMAND
1831      ${CMAKE_COMMAND} -E remove zephyr_pre${index}.elf
1832      )
1833  endforeach()
1834endif()
1835
1836if(CONFIG_BUILD_OUTPUT_S19)
1837  get_property(elfconvert_formats TARGET bintools PROPERTY elfconvert_formats)
1838  if(srec IN_LIST elfconvert_formats)
1839    # Should we print a warning if case the tools does not support converting to s19 ?
1840    list(APPEND
1841      post_build_commands
1842      COMMAND $<TARGET_PROPERTY:bintools,elfconvert_command>
1843              $<TARGET_PROPERTY:bintools,elfconvert_flag>
1844              $<$<BOOL:${CONFIG_BUILD_OUTPUT_S19_GAP_FILL}>:${gap_fill}>
1845              $<TARGET_PROPERTY:bintools,elfconvert_flag_outtarget>srec
1846              $<TARGET_PROPERTY:bintools,elfconvert_flag_srec_len>1
1847              $<TARGET_PROPERTY:bintools,elfconvert_flag_infile>${KERNEL_ELF_NAME}
1848              $<TARGET_PROPERTY:bintools,elfconvert_flag_outfile>${KERNEL_S19_NAME}
1849              $<TARGET_PROPERTY:bintools,elfconvert_flag_final>
1850      )
1851    list(APPEND
1852      post_build_byproducts
1853      ${KERNEL_S19_NAME}
1854      )
1855    set(BYPRODUCT_KERNEL_S19_NAME "${PROJECT_BINARY_DIR}/${KERNEL_S19_NAME}" CACHE FILEPATH "Kernel s19 file" FORCE)
1856  endif()
1857endif()
1858
1859if(CONFIG_OUTPUT_DISASSEMBLY)
1860if(CONFIG_OUTPUT_DISASSEMBLE_ALL)
1861    set(disassembly_type "$<TARGET_PROPERTY:bintools,disassembly_flag_all>")
1862  elseif (CONFIG_OUTPUT_DISASSEMBLY_WITH_SOURCE)
1863    set(disassembly_type "$<TARGET_PROPERTY:bintools,disassembly_flag_inline_source>")
1864  endif()
1865  list(APPEND
1866    post_build_commands
1867    COMMAND $<TARGET_PROPERTY:bintools,disassembly_command>
1868            $<TARGET_PROPERTY:bintools,disassembly_flag>
1869            ${disassembly_type}
1870            $<TARGET_PROPERTY:bintools,disassembly_flag_infile>${KERNEL_ELF_NAME}
1871            $<TARGET_PROPERTY:bintools,disassembly_flag_outfile>${KERNEL_LST_NAME}
1872            $<TARGET_PROPERTY:bintools,disassembly_flag_final>
1873    )
1874  list(APPEND
1875    post_build_byproducts
1876    ${KERNEL_LST_NAME}
1877    )
1878endif()
1879
1880if(CONFIG_OUTPUT_SYMBOLS)
1881  list(APPEND
1882    post_build_commands
1883    COMMAND $<TARGET_PROPERTY:bintools,symbols_command>
1884            $<TARGET_PROPERTY:bintools,symbols_flag>
1885            $<TARGET_PROPERTY:bintools,symbols_infile>${KERNEL_ELF_NAME}
1886            $<TARGET_PROPERTY:bintools,symbols_outfile>${KERNEL_SYMBOLS_NAME}
1887            $<TARGET_PROPERTY:bintools,symbols_final>
1888    )
1889  list(APPEND
1890    post_build_byproducts
1891    ${KERNEL_SYMBOLS_NAME}
1892    )
1893endif()
1894
1895if(CONFIG_OUTPUT_STAT)
1896  list(APPEND
1897    post_build_commands
1898    COMMAND $<TARGET_PROPERTY:bintools,readelf_command>
1899            $<TARGET_PROPERTY:bintools,readelf_flag>
1900            $<TARGET_PROPERTY:bintools,readelf_flag_headers>
1901            $<TARGET_PROPERTY:bintools,readelf_flag_infile>${KERNEL_ELF_NAME}
1902            $<TARGET_PROPERTY:bintools,readelf_flag_outfile>${KERNEL_STAT_NAME}
1903            $<TARGET_PROPERTY:bintools,readelf_flag_final>
1904    )
1905  list(APPEND
1906    post_build_byproducts
1907    ${KERNEL_STAT_NAME}
1908    )
1909endif()
1910
1911if(CONFIG_BUILD_OUTPUT_STRIPPED)
1912  list(APPEND
1913    post_build_commands
1914    COMMAND $<TARGET_PROPERTY:bintools,strip_command>
1915            $<TARGET_PROPERTY:bintools,strip_flag>
1916            $<TARGET_PROPERTY:bintools,strip_flag_all>
1917            $<TARGET_PROPERTY:bintools,strip_flag_infile>${KERNEL_ELF_NAME}
1918            $<TARGET_PROPERTY:bintools,strip_flag_outfile>${KERNEL_STRIP_NAME}
1919            $<TARGET_PROPERTY:bintools,strip_flag_final>
1920    )
1921  list(APPEND
1922    post_build_byproducts
1923    ${KERNEL_STRIP_NAME}
1924    )
1925endif()
1926
1927if(CONFIG_BUILD_OUTPUT_COMPRESS_DEBUG_SECTIONS)
1928  list(APPEND
1929    post_build_commands
1930    COMMAND $<TARGET_PROPERTY:bintools,elfconvert_command>
1931            $<TARGET_PROPERTY:bintools,elfconvert_flag>
1932            $<TARGET_PROPERTY:bintools,elfconvert_flag_compress_debug_sections>
1933            $<TARGET_PROPERTY:bintools,elfconvert_flag_infile>${KERNEL_ELF_NAME}
1934            $<TARGET_PROPERTY:bintools,elfconvert_flag_final>
1935)
1936endif()
1937
1938if(CONFIG_BUILD_OUTPUT_EXE)
1939  if (NOT CONFIG_NATIVE_LIBRARY)
1940    list(APPEND
1941      post_build_commands
1942      COMMAND
1943      ${CMAKE_COMMAND} -E copy ${KERNEL_ELF_NAME} ${KERNEL_EXE_NAME}
1944      )
1945    list(APPEND
1946      post_build_byproducts
1947      ${KERNEL_EXE_NAME}
1948      )
1949  else()
1950    if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
1951      set(MAKE "${CMAKE_MAKE_PROGRAM}" CACHE FILEPATH "cmake defined make")
1952    endif()
1953    find_program(MAKE make REQUIRED)
1954    add_custom_target(native_runner_executable
1955      ALL
1956      COMMENT "Building native simulator runner, and linking final executable"
1957      COMMAND
1958      ${MAKE} -f ${ZEPHYR_BASE}/scripts/native_simulator/Makefile all --warn-undefined-variables
1959        -r NSI_CONFIG_FILE=${APPLICATION_BINARY_DIR}/zephyr/NSI/nsi_config
1960      # nsi_config is created by the board cmake file
1961      DEPENDS ${logical_target_for_zephyr_elf}
1962      BYPRODUCTS ${KERNEL_EXE_NAME}
1963    )
1964  endif()
1965  set(BYPRODUCT_KERNEL_EXE_NAME "${PROJECT_BINARY_DIR}/${KERNEL_EXE_NAME}" CACHE FILEPATH "Kernel exe file" FORCE)
1966endif()
1967
1968if(CONFIG_BUILD_OUTPUT_INFO_HEADER)
1969  list(APPEND
1970    post_build_commands
1971    COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_image_info.py
1972    --elf-file=${KERNEL_ELF_NAME}
1973    --header-file=${PROJECT_BINARY_DIR}/include/public/zephyr_image_info.h
1974    $<$<BOOL:${adjustment}>:--adjusted-lma=${adjustment}>
1975    )
1976  list(APPEND
1977    post_build_byproducts
1978    ${PROJECT_BINARY_DIR}/include/public/zephyr_image_info.h
1979    )
1980endif()
1981
1982if (CONFIG_LLEXT AND CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID)
1983  #slidgen must be the first post-build command to be executed
1984  #on the Zephyr ELF to ensure that all other commands, such as
1985  #binary file generation, are operating on a preparated ELF.
1986  list(PREPEND
1987    post_build_commands
1988    COMMAND ${PYTHON_EXECUTABLE}
1989    ${ZEPHYR_BASE}/scripts/build/llext_prepare_exptab.py
1990    --elf-file ${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}
1991    --slid-listing ${PROJECT_BINARY_DIR}/slid_listing.txt
1992  )
1993
1994endif()
1995
1996if(NOT CMAKE_C_COMPILER_ID STREQUAL "ARMClang")
1997  set(check_init_priorities_input
1998      $<IF:$<TARGET_EXISTS:native_runner_executable>,${BYPRODUCT_KERNEL_EXE_NAME},${BYPRODUCT_KERNEL_ELF_NAME}>
1999  )
2000  set(check_init_priorities_command
2001      ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/check_init_priorities.py
2002      --elf-file=${check_init_priorities_input}
2003  )
2004  set(check_init_priorities_dependencies
2005      ${logical_target_for_zephyr_elf}
2006      $<$<TARGET_EXISTS:native_runner_executable>:native_runner_executable>
2007  )
2008
2009  if(CONFIG_CHECK_INIT_PRIORITIES)
2010    if(TARGET native_runner_executable)
2011      add_custom_command(TARGET native_runner_executable POST_BUILD
2012                         COMMAND ${check_init_priorities_command}
2013      )
2014    else()
2015      list(APPEND post_build_commands COMMAND ${check_init_priorities_command})
2016    endif()
2017  endif()
2018
2019  add_custom_target(
2020    initlevels
2021    COMMAND ${check_init_priorities_command} --initlevels
2022    DEPENDS ${check_init_priorities_dependencies}
2023    USES_TERMINAL
2024  )
2025endif()
2026
2027# Generate signed (MCUboot or other) related artifacts as needed. Priority is:
2028# * Sysbuild (if set)
2029# * SIGNING_SCRIPT target property (if set)
2030# * MCUboot signing script (if MCUboot is enabled)
2031zephyr_get(signing_script VAR SIGNING_SCRIPT SYSBUILD)
2032
2033if(NOT signing_script)
2034  get_target_property(signing_script zephyr_property_target SIGNING_SCRIPT)
2035
2036  if(NOT signing_script AND CONFIG_BOOTLOADER_MCUBOOT)
2037    set(signing_script ${CMAKE_CURRENT_LIST_DIR}/cmake/mcuboot.cmake)
2038  endif()
2039endif()
2040
2041# Include signing script, if set
2042if(signing_script)
2043  message(STATUS "Including signing script: ${signing_script}")
2044
2045  include(${signing_script})
2046endif()
2047
2048# Generate USB-C VIF policies in XML format
2049if (CONFIG_BUILD_OUTPUT_VIF)
2050  include(${CMAKE_CURRENT_LIST_DIR}/cmake/vif.cmake)
2051endif()
2052
2053get_property(extra_post_build_commands
2054  GLOBAL PROPERTY
2055  extra_post_build_commands
2056  )
2057
2058list(APPEND
2059  post_build_commands
2060  ${extra_post_build_commands}
2061  )
2062
2063get_property(extra_post_build_byproducts
2064  GLOBAL PROPERTY
2065  extra_post_build_byproducts
2066  )
2067
2068list(APPEND
2069  post_build_byproducts
2070  ${extra_post_build_byproducts}
2071  )
2072
2073if(CONFIG_LOG_DICTIONARY_DB)
2074  set(LOG_DICT_DB_NAME ${PROJECT_BINARY_DIR}/log_dictionary.json)
2075  set(LOG_DICT_DB_NAME_ARG --json)
2076elseif(CONFIG_LOG_MIPI_SYST_USE_CATALOG)
2077  set(LOG_DICT_DB_NAME ${PROJECT_BINARY_DIR}/mipi_syst_collateral.xml)
2078  set(LOG_DICT_DB_NAME_ARG --syst)
2079endif()
2080
2081if(LOG_DICT_DB_NAME_ARG)
2082  set(log_dict_gen_command
2083      ${PYTHON_EXECUTABLE}
2084      ${ZEPHYR_BASE}/scripts/logging/dictionary/database_gen.py
2085      ${KERNEL_ELF_NAME}
2086      ${LOG_DICT_DB_NAME_ARG}=${LOG_DICT_DB_NAME}
2087      --build-header ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h
2088  )
2089
2090  if (NOT CONFIG_LOG_DICTIONARY_DB_TARGET)
2091    # If not using a separate target for generating logging dictionary
2092    # database, add the generation to post build command to make sure
2093    # the database is actually being generated.
2094    list(APPEND
2095      post_build_commands
2096      COMMAND ${CMAKE_COMMAND} -E echo "Generating logging dictionary database: ${LOG_DICT_DB_NAME}"
2097      COMMAND ${log_dict_gen_command}
2098    )
2099    list(APPEND
2100      post_build_byproducts
2101      ${LOG_DICT_DB_NAME}
2102    )
2103  else()
2104    # Seprate build target for generating logging dictionary database.
2105    # This needs to be explicitly called/used to generate the database.
2106    add_custom_command(
2107      OUTPUT ${LOG_DICT_DB_NAME}
2108      COMMAND ${log_dict_gen_command}
2109      WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
2110      COMMENT "Generating logging dictionary database: ${LOG_DICT_DB_NAME}"
2111      DEPENDS ${logical_target_for_zephyr_elf}
2112    )
2113    add_custom_target(log_dict_db_gen DEPENDS ${LOG_DICT_DB_NAME})
2114  endif()
2115endif()
2116
2117# Add post_build_commands to post-process the final .elf file produced by
2118# either the ZEPHYR_LINK_STAGE_EXECUTABLE or the KERNEL_ELF executable
2119# targets above.
2120add_custom_command(
2121  TARGET ${logical_target_for_zephyr_elf}
2122  POST_BUILD
2123  COMMAND ${CMAKE_COMMAND} -E echo "Generating files from ${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME} for board: ${BOARD}"
2124  ${post_build_commands}
2125  BYPRODUCTS
2126  ${post_build_byproducts}
2127  COMMAND_EXPAND_LISTS
2128  )
2129
2130# To populate with hex files to merge, do the following:
2131#  set_property(GLOBAL APPEND PROPERTY HEX_FILES_TO_MERGE ${my_local_list})
2132# Note that the zephyr.hex file will not be included automatically.
2133get_property(HEX_FILES_TO_MERGE GLOBAL PROPERTY HEX_FILES_TO_MERGE)
2134if(HEX_FILES_TO_MERGE)
2135  # Merge in out-of-tree hex files.
2136  set(MERGED_HEX_NAME merged.hex)
2137
2138  add_custom_command(
2139    OUTPUT ${MERGED_HEX_NAME}
2140    COMMAND
2141    ${PYTHON_EXECUTABLE}
2142    ${ZEPHYR_BASE}/scripts/build/mergehex.py
2143    -o ${MERGED_HEX_NAME}
2144    ${HEX_FILES_TO_MERGE}
2145    DEPENDS ${HEX_FILES_TO_MERGE} ${logical_target_for_zephyr_elf}
2146    )
2147
2148  add_custom_target(mergehex ALL DEPENDS ${MERGED_HEX_NAME})
2149  list(APPEND RUNNERS_DEPS mergehex)
2150
2151  message(VERBOSE "Merging hex files: ${HEX_FILES_TO_MERGE}")
2152endif()
2153
2154if(SUPPORTED_EMU_PLATFORMS)
2155  list(GET SUPPORTED_EMU_PLATFORMS 0 default_emu)
2156  if(EXISTS ${ZEPHYR_BASE}/cmake/emu/${default_emu}.cmake)
2157    add_custom_target(run DEPENDS run_${default_emu})
2158  endif()
2159
2160  foreach(EMU_PLATFORM ${SUPPORTED_EMU_PLATFORMS})
2161    if(EXISTS ${ZEPHYR_BASE}/cmake/emu/${EMU_PLATFORM}.cmake)
2162      include(${ZEPHYR_BASE}/cmake/emu/${EMU_PLATFORM}.cmake)
2163    endif()
2164  endforeach()
2165
2166  if(TARGET debugserver_${default_emu})
2167    add_custom_target(debugserver DEPENDS debugserver_${default_emu})
2168  endif()
2169else()
2170  add_custom_target(run
2171    COMMAND
2172    ${CMAKE_COMMAND} -E echo
2173    "==================================================="
2174    "Emulation/Simulation not supported with this board."
2175    "==================================================="
2176    )
2177endif()
2178
2179add_subdirectory(cmake/flash)
2180add_subdirectory(cmake/usage)
2181add_subdirectory(cmake/reports)
2182
2183if(NOT CONFIG_TEST)
2184if(CONFIG_ASSERT AND (NOT CONFIG_FORCE_NO_ASSERT))
2185  message(WARNING "__ASSERT() statements are globally ENABLED")
2186endif()
2187endif()
2188
2189if(CONFIG_BOARD_DEPRECATED_RELEASE)
2190  message(WARNING "
2191      WARNING:  The board '${BOARD}' is deprecated and will be
2192      removed in version ${CONFIG_BOARD_DEPRECATED_RELEASE}"
2193  )
2194endif()
2195
2196if(CONFIG_SOC_DEPRECATED_RELEASE)
2197  message(WARNING "
2198      WARNING:  The SoC '${SOC_NAME}' is deprecated and will be
2199      removed in version ${CONFIG_SOC_DEPRECATED_RELEASE}"
2200  )
2201endif()
2202
2203# In CMake projects, 'CMAKE_BUILD_TYPE' usually determines the
2204# optimization flag, but in Zephyr it is determined through
2205# Kconfig. Here we give a warning when there is a mismatch between the
2206# two in case the user is not aware of this.
2207set(build_types None Debug Release RelWithDebInfo MinSizeRel)
2208
2209if((CMAKE_BUILD_TYPE IN_LIST build_types) AND (NOT NO_BUILD_TYPE_WARNING))
2210  string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_uppercase)
2211  # The CMAKE_C_FLAGS_<build_type> is a string, so we do a regex to see if the
2212  # optimization flag is present in that string.
2213  # To avoid false-positive matches, the flag must either be matched first
2214  # or last in string, or come after / followed by minimum a space.
2215  if(NOT (CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_uppercase} MATCHES "(^| )${OPTIMIZATION_FLAG}($| )"))
2216    message(WARNING "
2217      The CMake build type was set to '${CMAKE_BUILD_TYPE}', but the optimization flag was set to '${OPTIMIZATION_FLAG}'.
2218      This may be intentional and the warning can be turned off by setting the CMake variable 'NO_BUILD_TYPE_WARNING'"
2219      )
2220  endif()
2221endif()
2222
2223# Extension Development Kit (EDK) generation.
2224set(llext_edk_file ${PROJECT_BINARY_DIR}/${CONFIG_LLEXT_EDK_NAME}.tar.xz)
2225
2226# TODO maybe generate flags for C CXX ASM
2227zephyr_get_compile_definitions_for_lang(C zephyr_defs)
2228zephyr_get_compile_options_for_lang(C zephyr_flags)
2229
2230# Filter out non LLEXT and LLEXT_EDK flags - and add required ones
2231llext_filter_zephyr_flags(LLEXT_REMOVE_FLAGS ${zephyr_flags} llext_filt_flags)
2232llext_filter_zephyr_flags(LLEXT_EDK_REMOVE_FLAGS ${llext_filt_flags} llext_filt_flags)
2233
2234set(llext_edk_cflags ${zephyr_defs} -DLL_EXTENSION_BUILD)
2235list(APPEND llext_edk_cflags ${llext_filt_flags})
2236list(APPEND llext_edk_cflags ${LLEXT_APPEND_FLAGS})
2237list(APPEND llext_edk_cflags ${LLEXT_EDK_APPEND_FLAGS})
2238
2239add_custom_command(
2240    OUTPUT ${llext_edk_file}
2241    # Regenerate syscalls in case CONFIG_LLEXT_EDK_USERSPACE_ONLY
2242    COMMAND ${CMAKE_COMMAND}
2243        -E make_directory edk/include/generated/zephyr
2244    COMMAND
2245        ${PYTHON_EXECUTABLE}
2246        ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py
2247        --json-file        ${syscalls_json}                     # Read this file
2248        --base-output      edk/include/generated/zephyr/syscalls           # Write to this dir
2249        --syscall-dispatch edk/include/generated/zephyr/syscall_dispatch.c # Write this file
2250        --syscall-list     ${edk_syscall_list_h}
2251        $<$<BOOL:${CONFIG_LLEXT_EDK_USERSPACE_ONLY}>:--userspace-only>
2252        ${SYSCALL_LONG_REGISTERS_ARG}
2253        ${SYSCALL_SPLIT_TIMEOUT_ARG}
2254    COMMAND ${CMAKE_COMMAND}
2255        -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}
2256        -DAPPLICATION_SOURCE_DIR=${APPLICATION_SOURCE_DIR}
2257        -DINTERFACE_INCLUDE_DIRECTORIES="$<TARGET_PROPERTY:zephyr_interface,INTERFACE_INCLUDE_DIRECTORIES>"
2258        -Dllext_edk_file=${llext_edk_file}
2259        -Dllext_edk_cflags="${llext_edk_cflags}"
2260        -Dllext_edk_name=${CONFIG_LLEXT_EDK_NAME}
2261        -DWEST_TOPDIR=${WEST_TOPDIR}
2262        -DZEPHYR_BASE=${ZEPHYR_BASE}
2263        -DCONFIG_LLEXT_EDK_USERSPACE_ONLY=${CONFIG_LLEXT_EDK_USERSPACE_ONLY}
2264        -P ${ZEPHYR_BASE}/cmake/llext-edk.cmake
2265    DEPENDS ${logical_target_for_zephyr_elf}
2266    COMMAND_EXPAND_LISTS
2267)
2268add_custom_target(llext-edk DEPENDS ${llext_edk_file})
2269
2270# @Intent: Set compiler specific flags for standard C/C++ includes
2271# Done at the very end, so any other system includes which may
2272# be added by Zephyr components were first in list.
2273# Note, the compile flags are moved, but the system include is still present here.
2274zephyr_compile_options($<TARGET_PROPERTY:compiler,nostdinc>)
2275target_include_directories(zephyr_interface SYSTEM INTERFACE $<TARGET_PROPERTY:compiler,nostdinc_include>)
2276
2277if(CONFIG_MINIMAL_LIBCPP)
2278  zephyr_compile_options($<$<COMPILE_LANGUAGE:CXX>:$<TARGET_PROPERTY:compiler-cpp,nostdincxx>>)
2279endif()
2280
2281# Finally export all build flags from Zephyr
2282add_subdirectory_ifdef(
2283  CONFIG_MAKEFILE_EXPORTS
2284  cmake/makefile_exports
2285  )
2286
2287toolchain_linker_finalize()
2288
2289yaml_context(EXISTS NAME build_info result)
2290if(result)
2291  build_info(zephyr version VALUE ${PROJECT_VERSION_STR})
2292  build_info(zephyr zephyr-base VALUE ${ZEPHYR_BASE})
2293  yaml_save(NAME build_info)
2294endif()
2295