반응형

 

이전 글 바탕으로 예제를 작성했다.  이전 글을 읽는 것을 권장한다.

https://i5i5.tistory.com/1603

 

[Yocto] Ubuntu 환경에서 Yocto를 빌드 환경 구축 및 QEMU로 실행하는 방법

아래는 Ubuntu 환경에서 Yocto를 빌드하고 QEMU로 실행하는 전체 과정에 대한 내용이다.Ubuntu 22.04 LTS를 기준으로 설명하며, 가장 기본인 poky 배포판의 core-image-minimal을 빌드하였다. 1. 필수 패키지 설

i5i5.tistory.com

 

STEP 1.

cd ~/yocto-test/poky
source oe-init-build-env
# 레이어 생성
bitbake-layers create-layer ../meta-my-layer

# 레이어 활성화 등록
bitbake-layers add-layer ../meta-my-layer

# 레이어 등록된지 확인  (meta-my-layer가 항목에 있는지 확인)
bitbake-layers show-layers

 

 

STEP 2. 폴더구조

meta-my-layer/
├── conf/
│   └── layer.conf
├── recipes-example/           <-- (또는 recipes-hello 처럼 자유롭게 명명)
│   └── hello/                 <-- 패키지 이름 폴더
│       ├── hello_1.0.bb       <-- 레시피 파일
│       └── files/             <-- 소스 파일들이 들어갈 폴더
│           ├── hello.cpp
│           └── CMakeLists.txt
└── COPYING.MIT / README       <-- 레이어 생성 시 자동 생성된 파일들

 

 

mkdir -p meta-my-layer/recipes-example/hello

- hello_1.0.bb

SUMMARY = "Simple 5s Hello World App"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

# CMake 시스템을 사용함을 명시
inherit cmake

# 소스 파일 위치 (로컬 경로)
SRC_URI = "file://hello.cpp \
           file://CMakeLists.txt"

S = "${WORKDIR}"

# 빌드된 결과물을 /usr/bin 에 넣겠다는 설정
do_install() {
    install -d ${D}${bindir}
    install -m 0755 hello-yocto ${D}${bindir}
}

 

 

mkdir -p meta-my-layer/recipes-example/hello/files

- hello.cpp

#include <iostream>
#include <thread>
#include <chrono>

int main() {
    while (true) {
        std::cout << "Hello World from Yocto!" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(5));
    }
    return 0;
}

- CMakeLitst.txt

cmake_minimum_required(VERSION 3.10)
project(hello-yocto)
add_executable(hello-yocto hello.cpp)
install(TARGETS hello-yocto DESTINATION bin)

 

 

 

cd ~/yocto-test/poky

# 환경 초기화 (필요시)
source oe-init-build-env

# 레시피 파싱 확인
bitbake -s | grep hello

 

이후 "hello 1.0-r0"와 같은 내용이 뜬다면 제대로 설정된 것이다.

 

 

 

cd ~/yocto-test/poky

source oe-init-build-env

bitbake core-image-minimal

 

runqemu qemux86-64 nographic

which hello-yocto

hello-yocto

 

 

 

-------------

 

Service 파일로 변경하기

meta-my-layer/recipes-example/hello/files/hello.service

[Unit]
Description=5 Second Hello World Service
After=network.target

[Service]
ExecStart=/usr/bin/hello-yocto
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

 

 

hello_1.0.bb 레시피 수정

SUMMARY = "Simple 5s Hello World App with Systemd"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

# 1. systemd 클래스 상속
inherit cmake systemd

SRC_URI = "file://hello.cpp \
           file://CMakeLists.txt \
           file://hello.service"

S = "${WORKDIR}"

# 2. 서비스 이름 설정
SYSTEMD_SERVICE:${PN} = "hello.service"
SYSTEMD_AUTO_ENABLE:${PN} = "enable"

do_install() {
    # 바이너리 설치 (CMake가 처리하지만 수동으로 명시 가능)
    install -d ${D}${bindir}
    install -m 0755 hello-yocto ${D}${bindir}

    # 3. 서비스 파일을 systemd 시스템 폴더에 설치
    install -d ${D}${systemd_system_unitdir}
    install -m 0644 ${WORKDIR}/hello.service ${D}${systemd_system_unitdir}
}

# 4. 패키지에 서비스 파일 포함 명시
FILES:${PN} += "${systemd_system_unitdir}/hello.service"

 

 

~/yocto-test/poky/build/conf/local.conf

# Init 매니저를 systemd로 변경
DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED += "sysvinit"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"

 

 

systemctl status hello.service

journalctl -u hello.service -f

 

(영구적으로 systemd 수정하는 방법)

영구적으로 systemd 활성화 하는 방법은 없습니까?
 
 
 
local.conf를 수정하는 방식은 현재의 '빌드 폴더'에만 국한되기 때문에, 빌드 폴더를 새로 만들 때마다 설정을 다시 적어야 하는 번거로움이 있습니다.
이를 영구적으로, 그리고 프로젝트 전체에 적용하는 정석적인 방법은 커스텀 배포판(Distro) 설정 파일을 만드는 것입니다.

1. 커스텀 배포판 설정 파일 생성

Yocto의 poky 배포판 설정을 그대로 가져오되, systemd 설정만 우리가 원하는 대로 영구 고정시킨 새로운 배포판을 정의합니다.
  • 위치: meta-my-layer/conf/distro/my-distro.conf (폴더가 없으면 생성)
  • 내용:
    코드 스니펫
     

2. 프로젝트에서 이 배포판을 기본값으로 지정

이제 어떤 빌드 폴더를 만들더라도 자동으로 my-distro가 선택되게 하려면, 레이어 설정에서 배포판을 선언해야 합니다.
  • 위치: meta-my-layer/conf/layer.conf
  • 추가 내용: (파일 맨 아래에 추가)
    코드 스니펫
     

3. 영구 적용 확인법

이제 새로운 빌드 폴더를 만들어서 테스트해 보면 효과를 알 수 있습니다.
  1. 새 빌드 폴더 생성:
    Bash
     
  2. 설정 확인: build-new/conf/local.conf 파일을 열어보면 아무것도 수정하지 않았음에도 불구하고, 이미 배포판 설정에 의해 systemd가 활성화된 상태로 빌드 준비가 끝납니다.

💡 왜 이 방법이 "영구적"인가요?

  1. Git 관리 가능: meta-my-layer 안에 설정이 들어있으므로, 이 레이어만 Git으로 관리하면 다른 컴퓨터나 다른 개발자도 똑같이 systemd 환경을 즉시 가질 수 있습니다.
  2. 자동화: local.conf를 매번 메모장에서 복사-붙여넣기 할 필요가 없습니다.
  3. 일관성: core-image-minimal 뿐만 아니라 어떤 이미지를 빌드하더라도 이 배포판(Distro) 규칙이 적용됩니다.
이제 질문자님만의 전용 OS 배포판이 하나 생긴 셈입니다. 앞으로 모든 시스템 레벨의 변경 사항(네트워크 기본값, 타임존 등)은 이 my-distro.conf 파일에서 영구적으로 관리하시면 됩니다!

 

 

 

 

------------------------

외부 라이브러리

 

1. 외부 라이브러리 레시피 확보하기

Yocto 환경에 이미 sdbus-c++ 레시피가 있는지 먼저 확인해야 합니다. 보통 meta-oe 레이어에 포함되어 있습니다.

 

# build 폴더에서 검색
bitbake-layers show-recipes "sdbus-c++"

 

만약 검색 결과가 나온다면, 해당 라이브러리를 바로 사용할 수 있습니다. 결과가 없다면 meta-openembedded 레이어를 추가하거나, 직접 레시피를 만들어야 합니다.

 

2. 내 프로그램 레시피 수정 (hello_1.0.bb)

내 프로그램이 sdbus-c++에 의존하고 있다는 사실을 Yocto에게 알려줘야 빌드 시점에 해당 라이브러리를 먼저 빌드하고 링크해 줍니다.

# ... 기존 내용 중략 ...

# sdbus-c++ 라이브러리에 대한 의존성 추가
DEPENDS += "sdbus-c++"

# 런타임 시에도 라이브러리가 필요함을 명시
RDEPENDS:${PN} += "sdbus-c++"

inherit cmake systemd
# ... 이하 동일 ...

 

 

3. CMakeLists.txt 수정

Yocto가 라이브러리를 빌드해주면, 실제 컴파일 시점에 소스코드에서 이를 찾을 수 있어야 합니다.

cmake_minimum_required(VERSION 3.10)
project(hello-yocto)

# 1. 외부 패키지 찾기
find_package(sdbus-c++ REQUIRED)

add_executable(hello-yocto hello.cpp)

# 2. 라이브러리 링크
target_link_libraries(hello-yocto PRIVATE sdbus-c++::sdbus-c++)

install(TARGETS hello-yocto DESTINATION bin)

 

 

4. 소스코드에서 사용 (hello.cpp)

이제 코드에서 해당 라이브러리의 헤더를 호출할 수 있습니다.

#include <sdbus-c++/sdbus-c++.h>
// ... sdbus 관련 코드 작성 ...

 

 

 

5. 이미지에 라이브러리 영구 포함 (local.conf 등)

만약 내 프로그램뿐만 아니라 시스템 전체에서 이 라이브러리를 자유롭게 쓰고 싶다면, 앞서 배운 방식대로 이미지 설정에 추가합니다.

IMAGE_INSTALL:append = " sdbus-c++"

 

주의사항: 버전 이슈 (2.0.0)

만약 Yocto 레이어(meta-oe)가 제공하는 버전이 질문하신 2.0.0보다 낮다면, 다음과 같이 처리해야 합니다.

  1. Recipe Upgrading: 기존 .bb 파일을 복사하여 sdbus-c++_2.0.0.bb로 이름을 바꾸고 내부의 SRCREV(커밋 해시)나 SRC_URI를 2.0.0 버전 주소로 수정합니다.
  2. 레이어 확인: 최신 버전의 라이브러리는 최신 Yocto 브랜치(예: Scarthgap, Kirkstone 등)용 레이어에 있을 확률이 높습니다.

결론

네, 외부 라이브러리 추가는 1) 레시피 존재 확인, 2) DEPENDS 추가, 3) CMake 링크 세 단계로 요약됩니다. sdbus-c++처럼 시스템 버스(D-Bus)를 다루는 라이브러리는 임베디드 리눅스 개발에서 매우 자주 쓰이는 패턴이므로, 이 방식으로 익혀두시면 아주 유용합니다!

혹시 bitbake-layers show-recipes 명령어로 검색했을 때 라이브러리가 나오나요? 안 나온다면 레이어 추가 방법부터 다시 가이드해 드릴 수 있습니다.

 

 

 

다시 sdbus로 돌아와서, yocto에 sdbus를 추가하고, 빌드 시 CMakeLists.txt 파일을 읽어 수행하게 될텐데, 그 때 yocto에 포함되어있는 sdbus-c++-xml2cpp 명령어로 codegen을 실행하게 하고 싶습니다. 가능합니까? 가능하다면, 간단한 예제 알려줄 수 있나요
 
 
 
네, 충분히 가능합니다! Yocto 빌드 과정에서 D-Bus 인터페이스 파일(.xml)을 기반으로 sdbus-c++-xml2cpp 도구를 실행하여 C++ 프록시나 스텁 코드를 자동 생성(Codegen)하는 것은 매우 정석적인 방식입니다.
이 작업을 수행하려면 네이티브(Native) 도구에 대한 의존성 설정과 CMake의 커스텀 커맨드 설정이 핵심입니다.

1. 레시피 수정 (hello_1.0.bb)

빌드를 수행하는 호스트(PC) 환경에서 sdbus-c++-xml2cpp 도구가 실행되어야 하므로, DEPENDS에 -native 패키지를 추가해야 합니다.
코드 스니펫
 

2. CMakeLists.txt 설정

CMake에서 XML 파일을 읽어 소스코드를 생성하도록 add_custom_command를 작성합니다.
CMake
 

3. 소스코드 배치

meta-my-layer 내의 파일 구조는 다음과 같아야 합니다.
Plaintext
 

4. 작동 원리 (Yocto 빌드 메커니즘)

  1. 의존성 해결: Yocto가 sdbus-c++-native를 먼저 빌드하여 빌드 호스트의 recipe-sysroot-native 경로에 도구들을 설치합니다.
  2. 환경 변수: Yocto 내에서 CMake가 실행될 때, PATH 환경 변수에 위 도구가 들어있는 경로가 자동으로 포함됩니다.
  3. 빌드 타임 실행: bitbake를 실행하면 CMake가 빌드 과정 중에 sdbus-c++-xml2cpp를 호출하여 헤더 파일을 생성하고, 이를 참조하여 C++ 코드를 컴파일합니다.

💡 주의할 점

  • 도구 이름: 최신 sdbus-c++ 버전에서는 도구 이름이 sdbus-c++-xml2cpp입니다. 사용하는 레이어 버전에 따라 이름이 조금 다를 수 있으니, 만약 "command not found"가 뜬다면 bitbake -c devshell hello로 들어가서 정확한 명령 이름을 확인해 보는 것이 좋습니다.
  • 파일 경로: add_custom_command에서 파일 경로는 절대 경로(${CMAKE_CURRENT_SOURCE_DIR})를 사용하는 것이 가장 안전합니다.
이제 XML 파일만 수정하면 C++ 코드가 자동으로 생성되는 진정한 임베디드 통신 환경을 구축하실 수 있습니다! 혹시 D-Bus XML 파일 샘플이 필요하신가요?

 

반응형