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