Zephyr v3.7.0 · 커널과 서비스 소스 분석

Zephyr Sysbuild: 이미지가 둘일 때 빌드는 어디서 갈라지나

west 명령은 하나여도 상위 sysbuild 설정과 각 이미지의 Zephyr 설정은 따로 있습니다. 무엇이 MCUboot를 추가하고, 어떤 파일이 어느 이미지의 결과인지 따라갑니다.

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

이 글은 Zephyr v3.7.0, commit 36940db938a8f4a1e919496793ed439850a221c2의 Sysbuild 문서와 CMake·Kconfig·west 구현을 기준으로 새로 쓴 설명이다. MCUboot 예시는 모듈·보드가 이를 지원하는 경우다. 그림의 폴더와 화살표는 구조를 설명하며 실제 빌드 실행 결과의 캡처가 아니다.

1. Sysbuild는 “west build를 한 번 더 쓰는 법”이 아니다

기존 Build System / west 글은 한 애플리케이션의 보드 선택, Kconfig/devicetree 생성, 빌드 산출물을 따라간다. Sysbuild는 그 위에 있는 CMake/Kconfig 층이다. 기본 애플리케이션 한 개의 빌드도 관리할 수 있지만, 필요할 때 다른 Zephyr 이미지나 별도 빌드 프로젝트를 함께 편성한다. 따라서 --sysbuild만 붙였다고 이미지가 자동으로 두 개가 되는 것은 아니다.

Zephyr에서 sysbuild가 관리하는 각 Zephyr CMake 빌드는 domain이다. 여러 domain이면 multi-domain이고, non-Zephyr ExternalProject는 함께 빌드할 수 있어도 Zephyr domain처럼 자동 플래시·디버그 대상이 되지는 않는다. 이미지 수, domain 수, 물리 보드 수를 같은 숫자로 읽지 않는다.

표 1. 상위 빌드를 선택해도 보장되지 않는 것
상황상위 구성Sysbuild domain·west 선택 대상틀린 결론
일반 west build애플리케이션 CMake가 시작점Sysbuild domain 없음. domains.yaml이 없으면 west 내부의 app 한 개두 번째 이미지를 자동 통합한다는 말
--sysbuild만 사용Sysbuild CMake/Kconfig가 시작점주 이미지 하나일 수도 있음옵션 하나로 언제나 multi-image라는 말
Sysbuild + MCUboot 선택부트로더 이미지 포함 조건을 평가주 이미지와 mcuboot 등한 ELF 안에 두 이미지가 합쳐졌다는 말

근거: 3.7.0 Sysbuild 정의, west build.py 575–583행, west의 단일 app domain 합성, images/CMakeLists.txt 4–15행.

2. 상위 CMake가 이미지를 편성하고 각 이미지는 따로 구성한다

west build --sysbuild는 애플리케이션 폴더를 직접 CMake의 최상위 소스로 쓰지 않고 share/sysbuild를 최상위 소스로 지정하며 APP_DIR에 본래 애플리케이션 경로를 넘긴다. 상위 빌드는 sysbuild Kconfig를 계산하고 이미지들을 추가·구성한다. 각 Zephyr 이미지에는 자기 소스, CMake cache, Kconfig 결과, 실행 파일이 따로 있다. 상위 빌드가 이미지의 설정값 하나를 모두 공유하는 구조가 아니다.

그림 1. 한 명령에서 시작해 분리되는 두 Zephyr domain

↔ 좁은 화면에서 상위 빌드와 두 이미지, 결과 목록을 좌우로 이동해 읽으세요.

상위 Sysbuild · build/west build --sysbuild → share/sysbuild CMake + APP_DIR
SB_CONFIG를 읽고 이미지 목록·구성 순서·domains.yaml을 관리
주 애플리케이션 · build/<app>/자기 prj.conf·overlay·CMake
zephyr/.config → zephyr/zephyr.elf 등
선택된 MCUboot · build/mcuboot/별도 소스·설정·CMake
zephyr/.config → zephyr/zephyr.elf 등
상위의 목록 build/domains.yaml은 domain 이름·build_dir·default·flash_order를 기록한다. 파일 자체가 두 ELF를 합친 펌웨어는 아니다.

오른쪽 MCUboot 칸은 SB_CONFIG_BOOTLOADER_MCUBOOT=y이고 필요한 모듈·보드 조건이 맞을 때만 존재한다. 실제 image별 BIN/HEX 생성 여부는 각 이미지 설정에 달려 있다.

근거: 상위 CMakeLists.txt 6–21행, sysbuild_images.cmake 7–27행, domains.cmake 5–19행.

3. 같은 CONFIG처럼 보여도 목적지가 다르다

상위 빌드의 옵션은 SB_CONFIG_* 이름공간으로 간다. 이미지의 Zephyr 옵션은 CONFIG_*이며, 명령행에서 이미지 이름을 앞에 붙이면 그 이미지의 설정으로 보낸다. 접두어 없는 -DCONFIG_*는 주 애플리케이션으로 전달된다. 상위의 sysbuild.conf, 주 이미지의 prj.conf, 보조 이미지 조각 sysbuild/<image>.conf를 한 파일처럼 합쳐 생각하면 설정이 예상과 다른 domain에 도착한다.

그림 2. 설정 이름 앞부분이 결정하는 목적지

↔ 좁은 화면에서 명령행 변수와 최종 설정 목적지를 한 행씩 읽으세요.

-DSB_CONFIG_BOOTLOADER_MCUBOOT=y
→
Sysbuild Kconfig추가할 MCUboot image 여부를 결정
-DCONFIG_DEBUG_OPTIMIZATIONS=y
→
주 애플리케이션 Kconfig접두어가 없으면 main domain으로 전달
-Dmcuboot_CONFIG_DEBUG_OPTIMIZATIONS=y
→
MCUboot Kconfigmcuboot_ 이름공간에 속함
sysbuild/mcuboot.conf
→
MCUboot 설정 조각보조 이미지의 기존 기본 설정에 추가하는 경로

첫 세 행은 3.7.0 공식 문서의 명령행 이름공간 예시를 바탕으로 새로 그렸다. 네 번째는 애플리케이션 아래의 이미지별 설정 조각이며, 명령행의 명시적 파일 지정 등은 우선순위에 영향을 준다.

표 2. 세 종류의 설정과 예외
입력소유자확인할 조건
sysbuild.conf / SB_CONF_FILE상위 Sysbuild기본 파일은 앱 최상위에서 찾고, 별도 파일을 지정할 수 있음
prj.conf / -DCONFIG_*주 Zephyr 이미지일반 단일 이미지와 동일한 Kconfig 변수 문법
sysbuild/<image>.conf이름 붙은 보조 이미지의 추가 조각명령행의 별도 설정 파일·조각 지정이 있으면 선택 경로를 다시 확인
sysbuild/<image>/그 이미지의 앱 설정 디렉터리디렉터리가 있고 명시적인 -D<image>_CONF_FILE이 없을 때 선택. 명시 파일이 우선
sysbuild/<image>.overlay그 이미지의 devicetree 추가 조각이미지별 명시 overlay가 있으면 실제 적용 값을 확인

근거: 3.7.0 Configuration namespacing, Zephyr application configuration, sysbuild_kconfig.cmake 27–105행, sysbuild_extensions.cmake 262–297행.

4. 이미지를 추가했다고 실행 순서까지 정해지지는 않는다

상위 이미지는 ExternalZephyrProject_Add(APPLICATION ... SOURCE_DIR ...)로 등록된다. v3.7.0의 기본 images CMake는 주 애플리케이션을 먼저 넣고, SB_CONFIG_BOOTLOADER_MCUBOOT가 켜진 경우 MCUboot를 추가한다. 추가 이미지마다 CMake 구성과 빌드 디렉터리가 분리된다. BUILD_ONLY TRUE는 이미지의 빌드는 유지하면서 기본 west flash 순서에서 뺀다.

두 종류의 의존성도 분리해야 한다. CONFIGURE는 한 이미지의 CMake 구성이 다른 이미지 구성을 기다리게 한다. FLASH는 domains.yaml의 기본 플래시 순서를 바꾼다. 다만 BUILD_ONLY TRUE 이미지가 sysbuild_add_dependencies(FLASH <image> ...)의 대상 <image>이면 CMake가 구성 중 오류를 낸다. 둘 다 실제 장치의 부팅 순서나 메모리 주소 배치를 저절로 검증하지 않는다.

그림 3. 같은 두 이미지에 적용된 두 개의 독립 순서

↔ 좁은 화면에서 구성 순서와 기본 flash 순서가 별도 목록임을 비교하세요.

CONFIGURE 의존성① MCUboot CMake 구성↓② 주 이미지 CMake 구성

뒤 이미지의 설정이 앞 이미지의 구성 결과에 의존할 때 쓰는 순서

FLASH 의존성① MCUboot 기본 플래시↓② 주 이미지 기본 플래시

domains.yaml의 flash_order로 넘기는 순서

두 순서는 독립적으로 설정할 수 있다. 그림에서 FLASH 의존성의 대상인 주 이미지는 BUILD_ONLY가 아니다. MCUboot 포함 분기는 이 고정 소스에서 CONFIGURE와 FLASH 의존성을 각각 명시한다.

3.7.0 예시 문법 주의: 공식 Sysbuild 페이지의 의존성 예시는 sysbuild_add_dependencies(IMAGE CONFIGURE ...) 형태지만, 이 글에서 고정한 v3.7.0 CMake 함수와 MCUboot 실제 호출은 sysbuild_add_dependencies(CONFIGURE <image> <선행 image>) 및 FLASH 형태다. 의존성 코드를 직접 작성할 때는 사용 중인 소스의 함수 시그니처를 확인한다.
표 3. 이미지 편성과 순서 API가 바꾸는 것
조작영향하지 않는 일
ExternalZephyrProject_Add()별도 Zephyr 이미지/domain 등록플래시 가능 여부나 주소 충돌의 자동 증명
sysbuild_add_dependencies(CONFIGURE ...)이미지 CMake 구성 순서기본 플래시 순서 설정
sysbuild_add_dependencies(FLASH ...)기본 west flash 순서. 대상 <image>가 BUILD_ONLY면 CMake 오류CMake 구성 순서 설정
BUILD_ONLY TRUE기본 flash 목록에서 제외; FLASH 의존성의 대상 이미지로 지정 불가빌드 제외나 개별 west flash --domain 금지

근거: 3.7.0 Adding Zephyr applications 및 Adding dependencies Note, MCUboot CMakeLists.txt 6–19행, sysbuild_extensions.cmake 674–722행.

5. 한 빌드 폴더에 여러 결과가 있어도 최종 설정은 이미지별이다

상위 build/domains.yaml은 default domain, 상위 build_dir, domain별 경로, 기본 flash_order를 묶는다. 각 Zephyr domain의 zephyr/.config와 zephyr/zephyr.elf는 그 이미지에 속한다. BIN·HEX·S19·UF2 등의 산출물 속성은 각 이미지가 실제 그 형식을 만들 때만 설정된다. 따라서 주 이미지의 .config 하나만 보고 MCUboot가 어떤 키·최적화·보드로 구성됐는지 단정하면 안 된다.

표 4. 예시 build 트리에서 무엇을 확인할까
위치·파일소유자읽을 정보
build/domains.yamlSysbuilddefault, domain 목록·경로, 기본 flash_order
build/<app>/zephyr/.config주 Zephyr 이미지주 앱의 최종 Kconfig
build/mcuboot/zephyr/.configMCUboot Zephyr 이미지부트로더의 별도 최종 Kconfig
build/<image>/zephyr/zephyr.elf각 Zephyr 이미지그 이미지의 ELF; 형식별 출력은 구성에 따라 다름
build/<image>/zephyr/runners.yaml각 Zephyr 이미지west flash/debug runner 설정의 입력

근거: 3.7.0 Architectural Overview, domains.cmake 5–19행, 이미지별 binary dir 및 형식별 출력 속성.

6. west build·flash·debug도 고르는 단위가 다르다

예를 들어 보드와 MCUboot 모듈이 지원된다면 west build -b <board> --sysbuild <app> -- -DSB_CONFIG_BOOTLOADER_MCUBOOT=y로 상위 빌드를 만든다. 이 명령은 주 이미지와 부트로더를 별도로 구성한다. 이후 west build -d build --domain mcuboot는 특정 domain 빌드이고, domain을 지정하지 않은 top-level 빌드는 전체를 대상으로 한다.

west flash는 sysbuild의 기본 flash_order에 있는 domain을 순서대로 플래시한다. west flash --domain mcuboot처럼 한 domain만 선택할 수 있다. west debug는 기본 domain 하나를 대상으로 하고, MCUboot를 디버깅하려면 --domain mcuboot를 명시한다. 일반적인 menuconfig는 주 이미지, sysbuild_menuconfig는 상위 설정, mcuboot_menuconfig는 부트로더 설정을 연다. 단, 각 target 사용 가능 여부는 생성된 빌드 도구·이미지 설정을 확인한다.

표 5. 같은 build 폴더, 다른 선택 단위
명령·target선택 대상확인할 결과
west build --sysbuild상위 빌드와 포함된 전체 이미지domains.yaml과 각 image build_dir
west build --domain <name>지정한 이미지의 빌드그 domain의 ELF·설정
west flash / --domain기본 flash_order 전체 / 선택 domainrunner·플래시 순서; BUILD_ONLY 예외
west debug / --domain기본 domain / 선택 domain 하나선택 이미지의 디버그 대상
sysbuild_menuconfig / mcuboot_menuconfig상위 Kconfig / MCUboot Kconfig어느 설정 층을 편집하는지

근거: 3.7.0 flash·debug·targets, 3.7.0 west multi-domain, build.py 상위 소스 선택 및 domain별 빌드.

7. 다시 빌드하기 전에 확인할 네 가지

  1. Zephyr commit, MCUboot 등 모듈 버전, 보드와 --sysbuild 선택 여부를 기록한다. 이미지 수가 예상과 다르면 상위 SB_CONFIG_*부터 본다.
  2. 상위 sysbuild 설정과 각 이미지의 최종 zephyr/.config를 각각 확인한다. 접두어 없는 CONFIG_*를 MCUboot 설정으로 오인하지 않는다.
  3. domains.yaml의 domain 목록·경로·default·flash_order와 각 Zephyr 이미지의 runners.yaml을 함께 본다. BUILD_ONLY 이미지가 기본 플래시에서 빠졌는지 구분한다.
  4. CONFIGURE 의존성과 FLASH 의존성을 따로 검사한다. 두 순서가 맞더라도 실제 보드의 파티션·부팅·서명 조건은 별도 검증한다.

8. 고정 버전 근거와 설명의 한계

이 글은 Zephyr v3.7.0의 Zephyr domain과 MCUboot 선택 경로를 설명한다. 특정 보드에 대한 실빌드·플래시·디버그 결과는 제시하지 않는다. ExternalProject로 묶은 non-Zephyr 앱은 같은 상위 빌드에 들어가도 자동 west domain으로 취급하지 않는다. 문서의 의존성 예시와 고정 CMake 함수 시그니처 차이는 위에 별도로 표시했다.

연결해서 읽기