커스텀 레이어 및 레시피 생성¶
새 레이어 생성¶
커스텀 애플리케이션을 위한 새 레이어를 생성해보겠습니다:
레이어 생성 명령¶
# 새 레이어 생성
bitbake-layers create-layer ../meta-myapp
# 생성된 레이어 구조 확인
tree ../meta-myapp
# 레이어를 빌드에 추가
bitbake-layers add-layer ../meta-myapp
# 레이어 목록 확인
bitbake-layers show-layers
표준 레이어 구조¶
meta-myapp/
├── conf/
│ └── layer.conf # 레이어 기본 설정
├── recipes-example/ # 예제 레시피들
├── recipes-myapp/ # 커스텀 애플리케이션 레시피
│ └── hello-world/
│ ├── files/ # 소스 파일들
│ └── hello-world_1.0.bb # 레시피 파일
├── classes/ # 공통 클래스 파일들
├── files/ # 공통 파일들
└── README # 레이어 설명서
layer.conf 설정¶
# meta-myapp/conf/layer.conf
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "myapp"
BBFILE_PATTERN_myapp = "^${LAYERDIR}/"
BBFILE_PRIORITY_myapp = "6"
# 의존성 레이어 정의
LAYERDEPENDS_myapp = "core openembedded-layer"
# Yocto 버전 호환성
LAYERSERIES_COMPAT_myapp = "scarthgap"
Hello World 애플리케이션 만들기¶
소스 코드 작성¶
# 소스 코드 디렉토리 생성
mkdir -p ../meta-myapp/recipes-myapp/hello-world/files
# C 소스 코드 작성
cat > ../meta-myapp/recipes-myapp/hello-world/files/hello.c << 'EOF'
#include <stdio.h>
#include <time.h>
int main() {
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("Hello from Yocto Custom Layer!\n");
printf("This is my first custom application.\n");
printf("Built at: %s", __DATE__ " " __TIME__ "\n");
printf("Current time: %s", asctime(timeinfo));
return 0;
}
EOF
Makefile 작성¶
# Makefile 생성
cat > ../meta-myapp/recipes-myapp/hello-world/files/Makefile << 'EOF'
CC ?= gcc
CFLAGS ?= -Wall -O2
TARGET = hello
SOURCE = hello.c
$(TARGET): $(SOURCE)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCE)
install:
install -d $(DESTDIR)/usr/bin
install -m 755 $(TARGET) $(DESTDIR)/usr/bin/
clean:
rm -f $(TARGET)
.PHONY: install clean
EOF
레시피 파일 작성¶
# 레시피 파일 생성
cat > ../meta-myapp/recipes-myapp/hello-world/hello-world_1.0.bb << 'EOF'
SUMMARY = "Hello World application for Yocto"
DESCRIPTION = "A simple Hello World C application demonstrating custom layer creation"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
# 소스 파일들 정의
SRC_URI = "file://hello.c \
file://Makefile"
# 작업 디렉토리 설정
S = "${WORKDIR}"
# 컴파일 태스크
do_compile() {
oe_runmake
}
# 설치 태스크
do_install() {
oe_runmake install DESTDIR=${D}
}
# 패키지 정보
FILES:${PN} = "/usr/bin/hello"
EOF
레시피 빌드 및 테스트¶
개별 레시피 빌드¶
# 레시피만 빌드
bitbake hello-world
# 빌드 과정 상세 확인
bitbake hello-world -v
# 생성된 패키지 확인
find tmp/deploy -name "*hello-world*"
이미지에 포함시키기¶
# local.conf에 추가
echo 'IMAGE_INSTALL:append = " hello-world"' >> conf/local.conf
# 전체 이미지 재빌드
bitbake core-image-minimal
# QEMU에서 테스트
runqemu qemux86-64 core-image-minimal nographic
# 애플리케이션 실행 (QEMU 내부에서)
hello
고급 레시피 기능¶
패치 적용¶
# 패치 파일 추가
mkdir -p ../meta-myapp/recipes-myapp/hello-world/files
cat > ../meta-myapp/recipes-myapp/hello-world/files/add-version.patch << 'EOF'
--- a/hello.c
+++ b/hello.c
@@ -1,4 +1,6 @@
#include <stdio.h>
+#include <time.h>
+
+#define VERSION "1.0"
int main() {
time_t rawtime;
@@ -8,6 +10,7 @@
timeinfo = localtime(&rawtime);
printf("Hello from Yocto Custom Layer!\n");
+ printf("Version: %s\n", VERSION);
printf("This is my first custom application.\n");
printf("Built at: %s", __DATE__ " " __TIME__ "\n");
printf("Current time: %s", asctime(timeinfo));
EOF
# 레시피에 패치 추가
echo 'SRC_URI += "file://add-version.patch"' >> ../meta-myapp/recipes-myapp/hello-world/hello-world_1.0.bb
설정 파일 포함¶
# 설정 파일 생성
cat > ../meta-myapp/recipes-myapp/hello-world/files/hello.conf << 'EOF'
# Hello World Application Configuration
greeting=Hello from Yocto
show_time=true
debug_mode=false
EOF
# 레시피에 설정 파일 추가
cat >> ../meta-myapp/recipes-myapp/hello-world/hello-world_1.0.bb << 'EOF'
SRC_URI += "file://hello.conf"
do_install:append() {
install -d ${D}${sysconfdir}
install -m 644 ${WORKDIR}/hello.conf ${D}${sysconfdir}/
}
FILES:${PN} += "${sysconfdir}/hello.conf"
EOF
의존성 추가¶
# 런타임 의존성 추가
cat >> ../meta-myapp/recipes-myapp/hello-world/hello-world_1.0.bb << 'EOF'
# 빌드 시간 의존성
DEPENDS = "zlib openssl"
# 런타임 의존성
RDEPENDS:${PN} = "bash python3"
# 권장 패키지
RRECOMMENDS:${PN} = "nano vim"
EOF
커스텀 이미지 레시피 생성¶
전용 이미지 레시피¶
# 커스텀 이미지 레시피 생성
mkdir -p ../meta-myapp/recipes-core/images
cat > ../meta-myapp/recipes-core/images/my-custom-image.bb << 'EOF'
SUMMARY = "My custom image with additional tools"
DESCRIPTION = "Custom image including hello-world app and development tools"
LICENSE = "MIT"
# core-image 클래스 상속
inherit core-image
# 이미지 기능 설정
IMAGE_FEATURES += "ssh-server-openssh package-management"
IMAGE_FEATURES += "debug-tweaks tools-debug"
# 포함할 패키지들
IMAGE_INSTALL = "packagegroup-core-boot \
packagegroup-base-extended \
hello-world \
nano \
vim \
htop \
git \
python3 \
python3-pip \
curl \
wget \
${CORE_IMAGE_EXTRA_INSTALL}"
# 이미지 이름 설정
export IMAGE_BASENAME = "my-custom-image"
# 추가 설정
IMAGE_ROOTFS_EXTRA_SPACE = "1024"
IMAGE_OVERHEAD_FACTOR = "1.3"
EOF
커스텀 이미지 빌드¶
Python 애플리케이션 레시피¶
Python 스크립트 생성¶
# Python 애플리케이션 디렉토리 생성
mkdir -p ../meta-myapp/recipes-myapp/python-hello/files
# Python 스크립트 작성
cat > ../meta-myapp/recipes-myapp/python-hello/files/hello.py << 'EOF'
#!/usr/bin/env python3
"""
Simple Hello World Python application for Yocto
"""
import sys
import datetime
import platform
def main():
print("="*50)
print("Hello from Python on Yocto!")
print("="*50)
print(f"Python version: {sys.version}")
print(f"Platform: {platform.platform()}")
print(f"Current time: {datetime.datetime.now()}")
print(f"Arguments: {sys.argv[1:] if len(sys.argv) > 1 else 'None'}")
print("="*50)
if __name__ == "__main__":
main()
EOF
# 실행 권한 부여
chmod +x ../meta-myapp/recipes-myapp/python-hello/files/hello.py
Python 레시피 작성¶
cat > ../meta-myapp/recipes-myapp/python-hello/python-hello_1.0.bb << 'EOF'
SUMMARY = "Python Hello World application"
DESCRIPTION = "A simple Python application for Yocto demonstration"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
# Python 관련 설정
inherit python3native
SRC_URI = "file://hello.py"
S = "${WORKDIR}"
# Python3 런타임 의존성
RDEPENDS:${PN} = "python3"
do_install() {
install -d ${D}${bindir}
install -m 755 ${WORKDIR}/hello.py ${D}${bindir}/python-hello
}
FILES:${PN} = "${bindir}/python-hello"
EOF
고급 레이어 관리¶
레이어 버전 관리¶
# 레이어에 버전 정보 추가
cat >> ../meta-myapp/conf/layer.conf << 'EOF'
# 레이어 버전
LAYERVERSION_myapp = "1"
# 레이어 시리즈 호환성
LAYERSERIES_COMPAT_myapp = "scarthgap nanbield"
EOF
다중 레시피 버전¶
# 다른 버전의 레시피 생성
cp ../meta-myapp/recipes-myapp/hello-world/hello-world_1.0.bb \
../meta-myapp/recipes-myapp/hello-world/hello-world_2.0.bb
# 버전별 기본 설정
echo 'PREFERRED_VERSION_hello-world = "2.0"' >> conf/local.conf
devtool을 활용한 개발¶
devtool 워크스페이스 생성¶
# 개발용 워크스페이스 생성
devtool create-workspace ../workspace
# 기존 레시피 수정
devtool modify hello-world
# 소스 코드 위치 확인
echo "소스 코드가 ../workspace/sources/hello-world 에 있습니다"
# 변경사항 빌드
devtool build hello-world
# 변경사항 적용
devtool finish hello-world ../meta-myapp
문제 해결¶
일반적인 레시피 오류¶
# 레시피 구문 확인
bitbake-layers show-recipes hello-world
# 레시피 파싱 오류 확인
bitbake -e hello-world | grep ERROR
# 의존성 문제 해결
bitbake -g hello-world
cat pn-depends.dot | grep hello-world
빌드 디버깅¶
# 상세 빌드 로그
bitbake hello-world -v -D
# 개발 쉘 진입
bitbake -c devshell hello-world
# 특정 태스크 재실행
bitbake -c compile hello-world -f
← 이미지 커스터마이징 | 고급 주제 →