build/cmake/index.html · build/cmake/index.rst 공식 원문 ↗

Zephyr 3.7.0 · Build · CMake

Zephyr Build System(CMake)

CMake·Kconfig·Devicetree configuration과 intermediate link, reflection, final image 생성 흐름을 단계별로 설명합니다.

Official pathbuild/cmake/index.html
Source filebuild/cmake/index.rst
Source versionZephyr 3.7.0
TranslationFull · reviewed

본문 기준: Zephyr 3.7.0 LTS3 · 이후 유지보수 패치는 별도입니다.

Part 1

요약·해설

공식 흐름도 11개와 target_sources 예제, build 지원 script 11개의 입력·출력 역할을 보존했습니다.

Configure

CMake · DTS · Kconfig

Build

Ninja · Make

Link

Intermediate · Final

Diagrams

11 official SVGs

Part 2

접을 수 있는 영어 원문 전체

영어 원문 전체 펼치기
원문 SHA-256 4366A8930F9EE82D9015533988194CFF24CC3DDB8DEE5A5924F975FE3063E254
.. _cmake-details:

Build System (CMake)
********************


CMake is used to build your application together with the Zephyr kernel. A
CMake build is done in two stages. The first stage is called
**configuration**. During configuration, the CMakeLists.txt build scripts are
executed. After configuration is finished, CMake has an internal model of the
Zephyr build, and can generate build scripts that are native to the host
platform.

CMake supports generating scripts for several build systems, but only Ninja and
Make are tested and supported by Zephyr. After configuration, you begin the
**build** stage by executing the generated build scripts. These build scripts
can recompile the application without involving CMake following
most code changes. However, after certain changes, the configuration step must
be executed again before building. The build scripts can detect some of these
situations and reconfigure automatically, but there are cases when this must be
done manually.

Zephyr uses CMake's concept of a 'target' to organize the build. A
target can be an executable, a library, or a generated file. For
application developers, the library target is the most important to
understand. All source code that goes into a Zephyr build does so by
being included in a library target, even application code.

Library targets have source code, that is added through CMakeLists.txt
build scripts like this:

.. code-block:: cmake

   target_sources(app PRIVATE src/main.c)

In the above :file:`CMakeLists.txt`, an existing library target named ``app``
is configured to include the source file :file:`src/main.c`. The ``PRIVATE``
keyword indicates that we are modifying the internals of how the library is
being built. Using the keyword ``PUBLIC`` would modify how other
libraries that link with app are built. In this case, using ``PUBLIC``
would cause libraries that link with ``app`` to also include the
source file :file:`src/main.c`, behavior that we surely do not want. The
``PUBLIC`` keyword could however be useful when modifying the include
paths of a target library.


Build and Configuration Phases
==============================

The Zephyr build process can be divided into two main phases: a configuration
phase (driven by CMake) and a build phase (driven by Make or Ninja).

.. _build_configuration_phase:

Configuration Phase
-------------------

The configuration phase begins when the user invokes *CMake* to generate a
build system, specifying a source application directory and a board target.

.. figure:: ../../../../build/cmake/build-config-phase.svg
    :align: center
    :alt: Zephyr's build configuration phase
    :figclass: align-center
    :width: 80%

CMake begins by processing the :file:`CMakeLists.txt` file in the application
directory, which refers to the :file:`CMakeLists.txt` file in the Zephyr
top-level directory, which in turn refers to :file:`CMakeLists.txt` files
throughout the build tree (directly and indirectly). Its primary output is a
set of Makefiles or Ninja files to drive the build process, but the CMake
scripts also do some processing of their own, which is explained here.

Note that paths beginning with :file:`build/` below refer to the build
directory you create when running CMake.

Devicetree
   :file:`*.dts` (*devicetree source*) and :file:`*.dtsi` (*devicetree source
   include*) files are collected from the target's architecture, SoC, board,
   and application directories.

   :file:`*.dtsi` files are included by :file:`*.dts` files via the C
   preprocessor (often abbreviated *cpp*, which should not be confused with
   C++). The C preprocessor is also used to merge in any devicetree
   :file:`*.overlay` files, and to expand macros in :file:`*.dts`,
   :file:`*.dtsi`, and :file:`*.overlay` files. The preprocessor output is
   placed in :file:`build/zephyr/zephyr.dts.pre`.

   The preprocessed devicetree sources are parsed by
   :zephyr_file:`gen_defines.py <scripts/dts/gen_defines.py>` to generate a
   :file:`build/zephyr/include/generated/zephyr/devicetree_generated.h` header with
   preprocessor macros.

   Source code should access preprocessor macros generated from devicetree by
   including the :zephyr_file:`devicetree.h <include/zephyr/devicetree.h>` header,
   which includes :file:`devicetree_generated.h`.

   :file:`gen_defines.py` also writes the final devicetree to
   :file:`build/zephyr/zephyr.dts` in the build directory. This file's contents
   may be useful for debugging.

   If the devicetree compiler ``dtc`` is installed, it is run on
   :file:`build/zephyr/zephyr.dts` to catch any extra warnings and errors
   generated by this tool. The output from ``dtc`` is unused otherwise, and
   this step is skipped if ``dtc`` is not installed.

   The above is just a brief overview. For more information on devicetree, see
   :ref:`dt-guide`.

Kconfig
   :file:`Kconfig` files define available configuration options for the
   target architecture, SoC, board, and application, as well as dependencies
   between options.

   Kconfig configurations are stored in *configuration files*. The initial
   configuration is generated by merging configuration fragments from the board
   and application (e.g. :file:`prj.conf`).

   The output from Kconfig is an :file:`autoconf.h` header with preprocessor
   assignments, and a :file:`.config` file that acts both as a saved
   configuration and as configuration output (used by CMake). The definitions in
   :file:`autoconf.h` are automatically exposed at compile time, so there is no
   need to include this header.

   Information from devicetree is available to Kconfig, through the functions
   defined in :zephyr_file:`kconfigfunctions.py
   <scripts/kconfig/kconfigfunctions.py>`.

   See :ref:`the Kconfig section of the manual <kconfig>` for more information.

Build Phase
-----------

The build phase begins when the user invokes ``make`` or ``ninja``. Its
ultimate output is a complete Zephyr application in a format suitable for
loading/flashing on the desired target board (:file:`zephyr.elf`,
:file:`zephyr.hex`, etc.) The build phase can be broken down, conceptually,
into four stages: the pre-build, first-pass binary, final binary, and
post-processing.

Pre-build
+++++++++

Pre-build occurs before any source files are compiled, because during
this phase header files used by the source files are generated.

Offset generation
   Access to high-level data structures and members is sometimes
   required when the definitions of those structures is not
   immediately accessible (e.g., assembly language). The generation of
   *offsets.h* (by *gen_offset_header.py*) facilitates this.

System call boilerplate
   The *gen_syscall.py* and *parse_syscalls.py*  scripts work
   together to bind potential system call functions with their
   implementations.

.. figure:: ../../../../build/cmake/build-build-phase-1.svg
    :align: center
    :alt: Zephyr's build stage I
    :figclass: align-center
    :width: 80%

Intermediate binaries
+++++++++++++++++++++

Compilation proper begins with the first intermediate binary. Source files (C
and assembly) are collected from various subsystems (which ones is
decided during the configuration phase), and compiled into archives
(with reference to header files in the tree, as well as those
generated during the configuration phase and the pre-build stage(s)).

.. figure:: ../../../../build/cmake/build-build-phase-2.svg
    :align: center
    :alt: Zephyr's build stage II
    :figclass: align-center
    :width: 80%

The exact number of intermediate binaries is decided during the configuration
phase.

If memory protection is enabled, then:

Partition grouping
   The *gen_app_partitions.py* script scans all the
   generated archives and outputs linker scripts to ensure that
   application partitions are properly grouped and aligned for the
   target’s memory protection hardware.

Then *cpp* is used to combine linker script fragments from the target’s
architecture/SoC, the kernel tree, optionally the partition output if
memory protection is enabled, and any other fragments selected during
the configuration process, into a *linker.cmd* file. The compiled
archives are then linked with *ld* as specified in the
*linker.cmd*.

Unfixed size binary
   The unfixed size intermediate binary is produced when :ref:`usermode_api`
   is enabled or :ref:`devicetree` is in use.
   It produces a binary where sizes are not fixed and thus it may be used
   by post-process steps that will impact the size of the final binary.

.. figure:: ../../../../build/cmake/build-build-phase-3.svg
    :align: center
    :alt: Zephyr's build stage III
    :figclass: align-center
    :width: 80%

Fixed size binary
   The fixed size intermediate binary is produced when :ref:`usermode_api`
   is enabled or when generated IRQ tables are used,
   :kconfig:option:`CONFIG_GEN_ISR_TABLES`
   It produces a binary where sizes are fixed and thus the size must not change
   between the intermediate binary and the final binary.

.. figure:: ../../../../build/cmake/build-build-phase-4.svg
    :align: center
    :alt: Zephyr's build stage IV
    :figclass: align-center
    :width: 80%

Intermediate binaries post-processing
+++++++++++++++++++++++++++++++++++++

The binaries from the previous stage are incomplete, with empty and/or
placeholder sections that must be filled in by, essentially, reflection.

To complete the build procedure the following scripts are executed on the
intermediate binaries to produce the missing pieces needed for the final
binary.

When :ref:`usermode_api` is enabled:

Partition alignment
   The *gen_app_partitions.py* script scans the unfixed size binary and
   generates an app shared memory aligned linker script snippet where the
   partitions are sorted in descending order.

.. figure:: ../../../../build/cmake/build-postprocess-1.svg
    :align: center
    :alt: Zephyr's intermediate binary post-process I
    :figclass: align-center
    :width: 80%

When :ref:`devicetree` is used:

Device dependencies
   The *gen_device_deps.py* script scans the unfixed size binary to determine
   relationships between devices that were recorded from devicetree data,
   and replaces the encoded relationships with values that are optimized to
   locate the devices actually present in the application.

.. figure:: ../../../../build/cmake/build-postprocess-2.svg
    :align: center
    :alt: Zephyr's intermediate binary post-process II
    :figclass: align-center
    :width: 80%

When :kconfig:option:`CONFIG_GEN_ISR_TABLES` is enabled:
   The *gen_isr_tables.py* script scans the fixed size binary and creates
   an isr_tables.c source file with a hardware vector table and/or software
   IRQ table.

.. figure:: ../../../../build/cmake/build-postprocess-3.svg
    :align: center
    :alt: Zephyr's intermediate binary post-process III
    :figclass: align-center
    :width: 80%

When :ref:`usermode_api` is enabled:

Kernel object hashing
   The *gen_kobject_list.py* scans the *ELF DWARF*
   debug data to find the address of the all kernel objects. This
   list is passed to *gperf*, which generates a perfect hash function and
   table of those addresses, then that output is optimized by
   *process_gperf.py*, using known properties of our special case.

.. figure:: ../../../../build/cmake/build-postprocess-4.svg
    :align: center
    :alt: Zephyr's intermediate binary post-process IV
    :figclass: align-center
    :width: 80%

When no intermediate binary post-processing is required then the first
intermediate binary will be directly used as the final binary.

Final binary
++++++++++++

The binary from the previous stage is incomplete, with empty and/or
placeholder sections that must be filled in by, essentially, reflection.

The link from the previous stage is repeated, this time with the missing
pieces populated.

.. figure:: ../../../../build/cmake/build-build-phase-5.svg
    :align: center
    :alt: Zephyr's build final stage
    :figclass: align-center
    :width: 80%

Post processing
+++++++++++++++

Finally, if necessary, the completed kernel is converted from *ELF* to
the format expected by the loader and/or flash tool required by the
target. This is accomplished in a straightforward manner with *objdump*.

.. figure:: ../../../../build/cmake/build-build-phase-6.svg
    :align: center
    :alt: Zephyr's build final stage post-process
    :figclass: align-center
    :width: 80%


.. _build_system_scripts:

Supporting Scripts and Tools
============================

The following is a detailed description of the scripts used during the build process.

.. _gen_syscalls.py:

:zephyr_file:`scripts/build/gen_syscalls.py`
--------------------------------------------

.. include:: ../../../../../scripts/build/gen_syscalls.py
   :start-after: """
   :end-before: """

.. _gen_device_deps.py:

:zephyr_file:`scripts/build/gen_device_deps.py`
-----------------------------------------------

.. include:: ../../../../../scripts/build/gen_device_deps.py
   :start-after: """
   :end-before: """

.. _gen_kobject_list.py:

:zephyr_file:`scripts/build/gen_kobject_list.py`
------------------------------------------------

.. include:: ../../../../../scripts/build/gen_kobject_list.py
   :start-after: """
   :end-before: """

.. _gen_offset_header.py:

:zephyr_file:`scripts/build/gen_offset_header.py`
-------------------------------------------------

.. include:: ../../../../../scripts/build/gen_offset_header.py
   :start-after: """
   :end-before: """

.. _parse_syscalls.py:

:zephyr_file:`scripts/build/parse_syscalls.py`
----------------------------------------------


.. include:: ../../../../../scripts/build/parse_syscalls.py
   :start-after: """
   :end-before: """

.. _gen_idt.py:

:zephyr_file:`arch/x86/gen_idt.py`
----------------------------------

.. include:: ../../../../../arch/x86/gen_idt.py
   :start-after: """
   :end-before: """

.. _gen_gdt.py:

:zephyr_file:`arch/x86/gen_gdt.py`
----------------------------------

.. include:: ../../../../../arch/x86/gen_gdt.py
   :start-after: """
   :end-before: """

.. _gen_relocate_app.py:

:zephyr_file:`scripts/build/gen_relocate_app.py`
------------------------------------------------

.. include:: ../../../../../scripts/build/gen_relocate_app.py
   :start-after: """
   :end-before: """

.. _process_gperf.py:

:zephyr_file:`scripts/build/process_gperf.py`
---------------------------------------------

.. include:: ../../../../../scripts/build/process_gperf.py
   :start-after: """
   :end-before: """

:zephyr_file:`scripts/build/gen_app_partitions.py`
--------------------------------------------------

.. include:: ../../../../../scripts/build/gen_app_partitions.py
   :start-after: """
   :end-before: """

.. _check_init_priorities.py:

:zephyr_file:`scripts/build/check_init_priorities.py`
-----------------------------------------------------

.. include:: ../../../../../scripts/build/check_init_priorities.py
   :start-after: """
   :end-before: """

Part 3

한국어 전문 번역

Build system(CMake)

CMake는 application과 Zephyr kernel을 함께 빌드하는 데 사용됩니다. CMake build는 두 단계로 진행됩니다. 첫 단계인 configuration에서는 CMakeLists.txt build script를 실행합니다. Configuration이 끝나면 CMake는 Zephyr build의 internal model을 가지며 host platform에 맞는 build script를 생성합니다.

CMake는 여러 build system용 script를 만들 수 있지만 Zephyr에서 시험하고 지원하는 것은 Ninja와 Make뿐입니다. 두 번째 build 단계에서는 생성된 script를 실행합니다. 일반적인 source 변경 뒤에는 CMake를 다시 실행하지 않고 application만 재compile할 수 있습니다. 다만 특정 변경은 configuration을 다시 해야 하며, build script가 일부 상황을 감지해 자동 재구성하지만 수동 처리가 필요한 경우도 있습니다.

Zephyr는 CMake의 target 개념으로 build를 구성합니다. Target은 executable, library 또는 generated file일 수 있습니다. Application developer에게 가장 중요한 것은 library target입니다. Application code를 포함해 Zephyr build에 들어가는 모든 source code는 library target에 포함됩니다.

예를 들어 기존 app library target에 src/main.c를 추가합니다.

target_sources(app PRIVATE src/main.c)

PRIVATE는 library 자체의 build 내부만 변경한다는 뜻입니다. PUBLIC을 쓰면 app에 link하는 다른 library의 build 방식까지 바뀌므로 이 예에서는 그 library들도 src/main.c를 포함하는 원치 않는 결과가 생깁니다. 다만 target library의 include path를 전달할 때는 PUBLIC이 유용할 수 있습니다.

Build와 configuration 단계

Zephyr build는 CMake가 주도하는 configuration phase와 Make 또는 Ninja가 주도하는 build phase로 나눌 수 있습니다.

Configuration phase

사용자가 source application directory와 board target을 지정해 CMake로 build system을 생성하면 시작됩니다.

Zephyr build configuration phase
Zephyr build configuration phase

CMake는 application directory의 CMakeLists.txt부터 처리합니다. 이 file은 Zephyr top-level CMakeLists.txt를 참조하고, 다시 build tree 전역의 CMakeLists를 직·간접적으로 참조합니다. 주요 출력은 build를 구동할 Makefile 또는 Ninja file이지만 CMake script 자체도 다음 작업을 수행합니다. 아래 build/로 시작하는 path는 CMake 실행 시 만든 build directory를 뜻합니다.

Devicetree

  • Target architecture, SoC, board, application directory에서 *.dts와 *.dtsi를 수집합니다.
  • C preprocessor(cpp)가 DTSI include, overlay merge, DTS/DTSI/overlay macro 확장을 수행하고 결과를 build/zephyr/zephyr.dts.pre에 둡니다. 여기서 cpp는 C++가 아닙니다.
  • scripts/dts/gen_defines.py가 전처리 결과를 parsing해 build/zephyr/include/generated/zephyr/devicetree_generated.h macro header를 만듭니다.
  • Source code는 <zephyr/devicetree.h>를 include해 생성 macro에 접근합니다. 이 header가 devicetree_generated.h를 포함합니다.
  • gen_defines.py는 최종 tree를 build/zephyr/zephyr.dts에도 기록하므로 debugging에 활용할 수 있습니다.
  • dtc가 설치되어 있으면 최종 DTS에 대해 추가 warning/error를 검사합니다. DTC output 자체는 사용하지 않으며 dtc가 없으면 이 단계도 건너뜁니다.

Kconfig

  • Architecture, SoC, board, application의 Kconfig file이 option과 option 사이의 dependency를 정의합니다.
  • Board와 application의 prj.conf 같은 fragment를 merge해 initial configuration을 만듭니다.
  • 출력은 preprocessor assignment가 든 autoconf.h와 저장·CMake 입력을 겸하는 .config입니다.
  • autoconf.h definition은 compile 때 자동 노출되므로 직접 include할 필요가 없습니다.
  • scripts/kconfig/kconfigfunctions.py의 function을 통해 devicetree 정보도 Kconfig에서 사용할 수 있습니다.

Build phase

사용자가 make 또는 ninja를 실행하면 시작됩니다. 최종 출력은 target board에 load 또는 flash할 수 있는 zephyr.elf, zephyr.hex 등의 완성 application입니다. 개념적으로 pre-build, intermediate binary, final binary, post-processing 단계로 나뉩니다.

Pre-build

Source compile 전에 필요한 header를 생성합니다.

  • Offset generation: Assembly처럼 C structure definition에 직접 접근할 수 없는 코드에서 member offset이 필요합니다. gen_offset_header.py가 offsets.h를 생성합니다.
  • System call boilerplate: gen_syscall.py와 parse_syscalls.py가 system call 후보 function을 implementation에 연결합니다.
Zephyr build stage I
Build stage I: pre-build

Intermediate binary

첫 intermediate binary부터 실제 compile이 시작됩니다. Configuration에서 선택된 subsystem의 C·assembly source를 수집하고 tree 안의 header와 configuration/pre-build에서 생성된 header를 참조해 archive로 compile합니다.

Zephyr build stage II
Build stage II: source와 archive

Intermediate binary 수는 configuration phase에서 결정됩니다. Memory protection을 켜면 gen_app_partitions.py가 생성 archive를 검사해 application partition이 hardware 요구에 맞게 묶이고 정렬되도록 linker script를 출력합니다.

그 다음 cpp가 architecture/SoC, kernel tree, 선택된 fragment, 필요하면 memory partition 출력을 합쳐 linker.cmd를 만듭니다. Compile된 archive는 이 file의 지시에 따라 ld로 link됩니다.

Unfixed-size binary

User mode API가 활성화됐거나 devicetree를 사용할 때 생성됩니다. 크기가 아직 고정되지 않아 final binary 크기에 영향을 주는 post-process 단계가 사용할 수 있습니다.

Zephyr build stage III
Build stage III: unfixed-size intermediate binary
Fixed-size binary

User mode API 또는 generated IRQ table(CONFIG_GEN_ISR_TABLES)을 사용할 때 생성됩니다. 이 binary는 크기가 고정되어 intermediate와 final binary 사이에 크기가 달라지면 안 됩니다.

Zephyr build stage IV
Build stage IV: fixed-size intermediate binary

Intermediate binary post-processing

이 단계의 binary에는 reflection 성격의 처리로 채워야 할 빈 section 또는 placeholder가 있습니다. 다음 script가 누락 조각을 생성합니다.

Partition alignment

User mode API가 켜지면 gen_app_partitions.py가 unfixed-size binary를 검사해 partition을 내림차순으로 정렬한 app shared-memory aligned linker snippet을 만듭니다.

Intermediate binary post-process I
Post-process I: partition alignment
Device dependency

Devicetree를 쓰면 gen_device_deps.py가 unfixed-size binary에서 devicetree로 기록된 device 관계를 찾아, application에 실제 존재하는 device를 빠르게 찾도록 최적화된 값으로 바꿉니다.

Intermediate binary post-process II
Post-process II: device dependency
ISR table

CONFIG_GEN_ISR_TABLES가 켜지면 gen_isr_tables.py가 fixed-size binary를 검사해 hardware vector table 및/또는 software IRQ table이 든 isr_tables.c를 만듭니다.

Intermediate binary post-process III
Post-process III: ISR table
Kernel object hashing

User mode API가 켜지면 gen_kobject_list.py가 ELF DWARF debug data에서 모든 kernel object address를 찾습니다. 이 목록을 받은 gperf가 perfect hash function과 address table을 생성하고, process_gperf.py가 Zephyr의 특성을 이용해 결과를 최적화합니다.

Intermediate binary post-process IV
Post-process IV: kernel object hash

Intermediate binary post-processing이 필요하지 않으면 첫 intermediate binary를 final binary로 바로 사용합니다.

Final binary

앞 단계의 link를 누락 조각이 채워진 상태로 다시 수행해 final binary를 만듭니다.

Zephyr final build stage
Final link

Post-processing

필요하면 완성 kernel을 target loader 또는 flash tool이 요구하는 형식으로 변환합니다. 원문은 이 작업을 objdump로 수행한다고 설명합니다.

Zephyr final stage post-process
Final binary post-processing

지원 script와 tool

scripts/build/gen_syscalls.py

parse_syscalls.py가 만든 system call metadata JSON을 읽어 invocation macro를 생성합니다.

  • 구현되지 않았을 수 있는 system call의 weak alias와 type ID→handler dispatch table
  • System call type ID와 모든 handler prototype을 정의한 header
  • System call 선언이 있던 각 header에 대응하는 inline invocation header directory

scripts/build/gen_device_deps.py

First-pass binary의 generic devicetree ordinal handle을 application에 실제 포함된 device에 맞춘 runtime index로 바꿉니다. 예를 들어 sensor/I2C/GPIO ordinal 52/24/14가 static device array에서는 6/5/3일 수 있습니다. 결과 C source의 대체 array definition이 final link에서 driver object의 기존 definition을 덮습니다.

scripts/build/gen_kobject_list.py

User thread가 address로 전달한 kernel object가 실제 object인지, type과 initialization state가 맞는지, caller가 permission을 가졌는지 검증할 metadata를 생성합니다. zephyr_prebuilt.elf의 DWARF에서 kernel object와 driver API struct를 찾아 다음 다섯 출력을 만들 수 있습니다.

  • Object address→permission/type/state/data를 mapping하는 gperf script
  • System call handler에서 driver instance를 검증할 macro header
  • Kernel object type과 driver instance별 enum fragment
  • otype_to_str()용 switch case fragment
  • CONFIG_DYNAMIC_OBJECTS runtime allocation의 object size switch case fragment

scripts/build/gen_offset_header.py

Object file에서 특히 _OFFSET 또는 _SIZEOF로 끝나는 symbol을 찾아 structure member offset macro header를 만듭니다. 주 용도는 assembly code입니다.

scripts/build/parse_syscalls.py

C·header directory를 text scan해 system call과 function prototype database를 만들고 후속 처리를 위한 JSON을 출력합니다. __subsystem, __net_socket 같은 tagged struct도 찾아 tag→declaration dictionary를 만듭니다. 기존 JSON과 결과가 같으면 file을 건드리지 않아 불필요한 incremental build를 막습니다.

arch/x86/gen_idt.py

zephyr_prebuilt.elf의 intList section에서 IRQ_CONNECT()가 기록한 route를 읽어 x86 IDT, runtime dynamic interrupt용 free-vector bitfield, IRQ line→IDT vector mapping array를 생성합니다.

arch/x86/gen_gdt.py

zephyr_prebuilt.elf에서 Main/Double Fault TSS address, GDT address, userspace와 hardware stack protection 설정을 읽습니다. 기본 flat 32-bit code/data segment를 만들고, 보호 기능에 따라 task descriptor와 ring 3 segment를 추가합니다.

scripts/build/gen_relocate_app.py

지정 file의 .text, .rodata, .data, .bss를 요청한 memory region으로 옮깁니다. Region suffix로 section을 고르고 COPY/NOCOPY로 relocation code 생성 여부를, NOKEEP로 linker KEEP() 생성을 제어합니다. 여러 section은 SRAM2_DATA_BSS처럼 결합할 수 있습니다.

scripts/build/process_gperf.py

String으로 표현한 pointer와 memcmp()를 쓰는 gperf output을 4-byte pointer 직접 비교 방식으로 바꿔 perfect hash table 크기를 줄입니다.

scripts/build/gen_app_partitions.py

K_APPMEM_PARTITION_DEFINE partition과 K_APP_DMEM/K_APP_BMEM global을 memory protection hardware의 size·alignment 제약에 맞게 배치할 linker fragment를 만듭니다. Compile object directory와 static library→partition mapping을 입력받아 partition별 data/BSS를 포함하는 app shared-memory section을 출력합니다.

scripts/build/check_init_priorities.py

Zephyr executable에서 device와 effective initialization priority를 구하고 devicetree dependency와 비교합니다. Dependency보다 늦게 초기화돼야 할 device가 먼저 초기화되는 오류, 동일 priority이지만 서로 의존해 link order 변화에 취약한 경우를 찾고, 선택적으로 init level별 human-readable 호출 목록도 출력합니다.

Source

출처

영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.