[ BBB - yocto (2) ] yocto 빌드하고 배포하기

 1) yocto란 무엇인가?

yocto project는 형상관리, 빌드 툴로 설명 가능함. 커스텀 리눅스를 빌드하고 이를 쉽게 유지보수, 배포할 수 있도록 도와주는 툴이라고 생각하면 됨





2) yocto의 구성요소

yocto project는 meta와 recipe로 파일을 관리함


meta는 레이어 파일 이름이야. recipe 파일을 갖고 있고, 빌드 할 때 설정등이 담겨있는 파일이고


recipe는 파일들을 설치할 수 있도록 도와주는 역할을 하는 코드를 모아놓은 파일이야


우선 말로만 보면 어려우니 직접 다운 받아서 확인해보자. 회색 라인 칠해진 부분은 WSL이야


앞으로 wsl 환경을 주로 사용할 거고 버추얼 박스는 마운트 용으로만 쓸거야


$ sudo apt-get install git tree

$ mkdir yocto 

$ cd yocto

$ git clone git://git.yoctoproject.org/poky -b kirkstone 

$ cd ./poky/meta-poky

$ tree -L 1 


meta 파일은 다음과 같이 구성돼

- classes : 레시피 파일에서 공통적으로 사용되는 함수와 변수들을 정의해둠

- conf : Yocto 빌드 시스템의 전반적인 변수를 담고 있는 파일이며 마치 bash의 환경 변수처럼 동작

- recipes-core : 핵심 패키지들이 포함된 디렉터리


yocto 프로젝트는 이 파일들을 가지고 사용자가 설정한 hw에 맞는 이미지 파일을 배포(파일을 생성)함


아래 과정을 거쳐서 파일시스템에 패키지가 설치가 되게 됨.


즉 전체 흐름을 요약해서 보면 아래와 같음


1. 클래스(.bbclass)에서 공통 사용 함수와 변수를 파악.

2. 설정(conf/) 파일에서 설정된 전역 변수를 읽어옴[빌드 전반에 거쳐 사용됨].

3. 레시피(.bb, .bbappend)를 로드하여 패키지 빌드 정보를 가져옴.

4. 소스 코드 다운로드(do_fetch) 및 패치(do_patch) 적용.

5. 컴파일(do_compile) 및 설치(do_install) 수행.

6. 패키징(do_package)하여 .rpm, .ipk, .deb 등의 형식으로 변환.

7. 완성된 패키지를 이미지에 포함하여 최종 빌드 완료.


.bb파일이나, .bbappend 같은 분석은 안할게... 강좌에서도 앞으로 거의 안씀.






3) 배포

yocto 프로젝트로 bitbake라는 빌드 툴을 사용해서 비글본에 쓸 이미지를 빌드 할 거야...


배포 파일들에 관해 간단하게 설명하겠음


1. MLO : u-boot 이미지를 불러오는 부트로더

2. u-boot.img : 부트로더, 운영체제에서 배웠던 부트로더 맞음. 하드웨어를 초기화하고, 디바이스 트리, 오버레이, 커널 이미지를 로드.

3. 커널 : 리눅스 커널임, 운영체제에서 배웠던 커널임. 이 친구는 많은 역할을 수행함. 하드웨어 입출력 제어라던가 메모리 관리라던가 cpu관리라던가...

4. am335x-boneblack.dtb, 디바이스 트리 오버레이 : 커널이 초기화 과정을 거칠 때 하드웨어 정보들이 기술되어 있는 바이너리 파일임

5. 루트 파일 시스템 : 커널이 올바르게 로드되기 위해서 커널에 필요한 패키지들을 포함하고 있는 파일, 사용자 공간이기도 함



따라서 우리가 배포한(빌드한) 이미지들의 동작 과정은 아래와 같아


1. MLO가 u-boot 이미지를 로드
2. u-boot가 커널이미지 디바이스트리, 오버레이 등을 로드하여 부팅 시작
3. 커널 이미지가 디바이스 트리, 오버레이의 내용대로 하드웨어를 초기화 시키고,  핀 먹스를 설정하며 루트 파일 시스템을 불러오고 마침내 user space에서 동작하기 시작함


이 배포 파일들을 바탕으로 리눅스 시스템이 동작하게 되는것임






4) 빌드하기

yocto 폴더로 돌아가자


$ cd ~/yocto

$ sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential\

 chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils\

 iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint xterm\

 python3-subunit mesa-common-dev zstd liblz4-tool

$ git clone git://git.yoctoproject.org/meta-arm -b kirkstone

$ git clone git://git.openembedded.org/meta-openembedded -b kirkstone

$ git clone git://git.yoctoproject.org/meta-ti -b kirkstone


다운로드 완료 후

cd ./poky
$ source oe-<tab키 입력>

이러면 build 디렉토리가 poky 디렉토리 밑에 만들어짐

$ code ./conf
치고 좀 기다리면 vscode가 자동으로 실행됨


ctrl + p 누르고 ">settings"
그러면 기본 사용자 설정 json 들어가서 yocto extension이 사용하는 파일들 루트를 지정하고 vscode가 사용하는 c, cpp 표준을 gnu23으로 지정하면됨

위 글대로 했으면

    "bitbake.pathToBuildFolder": "/home/[사용자 이름]/workplace/poky/build",
    "bitbake.pathToEnvScript": "/home/[사용자 이름]/yocto/poky/oe-init-build-env",
    "bitbake.pathToBitbakeFolder": "/home/[사용자 이름]/yocto/poky/bitbake",
    "C_Cpp.default.cStandard": "gnu23",
    "C_Cpp.default.cppStandard": "gnu++23",

 이렇게 복사해주시길 바람.


자 이렇게 3개의 파일이 보이지? .vscode는 무시하고




1. bblayers.conf 
위에서 다운로드 받은 meta-<레이어이름> 파일을 경로를 추가해주는 것임. 여기에 추가해 주면, bitbake를 할 때 meta 하위에 있는 레시피를 사용할 수 있음

meta 파일 종류와 레시피는

https://layers.openembedded.org/layerindex/branch/master/layers/

이 사이트에서 찾아 볼 수 있음

meta-ti, meta-openembedded, meta-arm 파일을 추가한 이유는 우리가 비글본 블랙을 마음대로 커스터 마이징 하려면 필요한 레이어를 담고있는 파일들이기 때문임

bblayers.conf 파일을 수정해서 쓸건데,  bitbake 명령어로 추가해줘도 됨

설치한 meta 파일들을 bitbake-layers add-layer [레시피 경로] 명령어로 레이어를 추가해 주시면 되겠음!

bblayer 변수만 수정해주면 됨

BBLAYERS ?= " \
  /home/[사용자 이름]/yocto/poky/meta \
  /home/[사용자 이름]/yocto/poky/meta-poky \
  /home/[사용자 이름]/yocto/poky/meta-yocto-bsp \
  /home/[사용자 이름]/yocto/meta-arm/meta-arm-toolchain \
  /home/[사용자 이름]/yocto/meta-arm/meta-arm \
  /home/[사용자 이름]/yocto/meta-arm/meta-arm-bsp \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-filesystems \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-gnome \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-initramfs \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-multimedia \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-networking \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-oe \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-perl \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-python \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-webserver \
  /home/[사용자 이름]/yocto/meta-openembedded/meta-xfce \
  /home/[사용자 이름]/yocto/meta-arm/meta-atp \
  /home/[사용자 이름]/yocto/meta-arm/meta-gem5 \
  /home/[사용자 이름]/yocto/meta-ti/meta-ti-bsp \
  /home/[사용자 이름]/yocto/meta-ti/meta-ti-extras \
  /home/[사용자 이름]/yocto/poky/build/workspace \
  "

최종 추가 결과임




2. local.conf
이 파일에서는 우라가 설치할 패키지나 이미지를 지정하거나, 커널 디바이스 트리를 추가해준다던가...여러가지 작업을 해줄 수 있음

local.conf 파일 맨 밑에 붙여주셈
#머신은 비글본 사용
MACHINE = "beaglebone"
#참고로 사용 가능한 ti bsp의 머신 이름이 보고 싶으면 아래 루트에서 .conf앞의 머신 이름을 적어주면 됨
#[meta-ti 디렉터리]/meta-ti-bsp/conf/machine/.

#추가 이미지
EXTRA_IMAGE_FEATURES ?= "debug-tweaks"
EXTRA_IMAGE_FEATURES += "dev-pkgs tools-sdk"

CONF_VERSION = "2"

#재 빌드시 오래된 이미지 제거
RM_OLD_IMAGE = "1"
INHERIT += "rm_work"

#추가로 설치할 이미지들
IMAGE_INSTALL:append = " lrzsz"     #터미널 파일 전송을 위해 사용
IMAGE_INSTALL:append = " gcc g++"   #컴파일러
IMAGE_INSTALL:append = " git"       #git
IMAGE_INSTALL:append = " apt dpkg"  #패키지 설치 툴
IMAGE_INSTALL:append = " i2c-tools" #i2c쓸 때 유용한 툴

#systemd의 dbus 메세지 실패 오류를 없애기 위해 설치
IMAGE_INSTALL:append = " dbus"

#USB 관련 유틸, usbutils는 lsusb 명령어 사용 위함.
#udev-extraconf는 udev(usb 관리해주는 데몬 프로세스)가 추가적으로 자동 USB 마운트 할 수 있게 해주
#기 위해 설정함
IMAGE_INSTALL:append = " usbutils"
IMAGE_INSTALL:append = " udev-extraconf"


#libgpiod 설치, gpioinfo 보기 위함
IMAGE_INSTALL:append = " libgpiod libgpiod-tools libgpiod-dev"

#모든 커널 모듈을 설치
IMAGE_INSTALL:append = " kernel-modules"

#시작 매니저 systemd 설정 (시작 매니저 종류 busybox, sysvinit, systemd)
INIT_MANAGER = "systemd"

#빌드시 기본 설정으로 되어 있는 특정 설정을 지움
#루트 파일시스템 빌드할 때 타임스템프가 달라져서 메타 데이터의 해시 값이 지워지는 오류가 있었는데
#타임스템프 무시하려고 추가
#없애도 되지만 만약 rootfs bitbake에 실패하는 경우 설정...(basehash reparsing 오류)
BUILD_REPRODUCIBLE_BINARIES = "1"



아 참고로 주석을 달긴 했지만 변수들이 뭐하는 앤지 궁금하면

yocto 익스텐션 덕분에 갖다 대면 영어 설명이 보임

머신은 어디서 찾느냐면

~/yocto/meta-ti/meta-ti-bsp/conf/machine 이 쪽 루트에 있음
여기서 .conf 때주고 MACHINE 변수에 beaglebone 입력해주면됨

사용 가능 이미지 보고 싶으면 위의 오픈임베디드 layer 사이트를 참조해도 좋고

poky 디렉토리에서 에서 

$ source oe<tab키>

쳐서 실행한 상태에서 bitbake-layers show-recipes 쳐주면 됨

이렇게 하면 빌드 준비가 완료됨


$ cd ~/yocto/
$ source oe-<tab 키>
$ bitbake core-image-full-cmdline

이러면 빌드가 실행됨. 매우 무거운 프로그램이니 빌드중에는 아무것도 하지 말기를 바람...

그리고 ctrl+c를 여러번 눌러서 중지했거나 컴퓨터가 도중에 다운됐다면, 이미지 깨져서 처음부터 다시 빌드해야함

#전체 빌드 과정 초기화
$ bitbake -c cleanall -f core-image-full-cmdline
$ rm -rf tmp download deploy-ti

5700x + 32gb램 + 100mbps 환경으로는 2시간 좀 더 걸림









5) sd카드 파티션 분할

SD카드를 컴퓨터에 연결한다. 가상머신을 사용하는 경우에는 usb를 가져올 수 있음.

호스트키 + home 또는 메뉴 탭에서 선택




usb 저장 공간을 선택해서 버추얼 머신에 내 sd카드를 마운트 시킴.

그러면 특별히 연결된 디바이스가 없다면, sd카드 공간이 sdb로 잡힐탠데

$ sudo fdisk -l
이걸로 디스크 목록을 검색해서 알아내도 좋다.

$ sudo fdisk /dev/sdb
실행한 뒤 나오는 화면에서

오류가 발생했는데 마운트가 자동으로 되서 그렇다.

q를 입력해 나가고

$ sudo umount /dev/sdb

를 입력한 뒤 다시 명령어를 실행하자


사용할 커맨드 리스트다.

d : 파티션을 지운다.

n : 파티션을 만든다.

a : 부트 가능 섹터로 지정한다.

t : 폴더의 타입을 지정한다.

p: 파티션 리스트 출력

w: 저장

q: 나가기



우선 d를 누르고 엔터를 계속 입력해 처음창(Command)이 뜨면 멈춰주자.

모든 파티션을 지워준다.

d -> 엔터 반복

p를 쳐서 파티션을 조회해 보면



이렇게 모든 파티션이 지워져 있을 때까지 반복해주삼.

n을 입력해 새로운 파티션을 만들자



n -> p -> 1 -> 2048 -> +256M 순으로 입력.

부가적으로 설명하자면, 


n을 입력하고 입력할 수 있는 명령은 2개임.

p: primary(기본 파티션)이다. 4개 밖에 만들지 못함.

e: extended (확장 파티션)이다. 4개 밖에 만들지 못하는 기존의 파티션 대신 논리적으로 파티션을 생성하여 추가로 파티션을 만들 수 있음.


어짜피 2개만 만들꺼니까 p만 쓰자.

partition number는 현재 만들 파티션 번호. 엔터를 치면 기본값인 1이 입력된다.


처음 섹터도 2048로 설정한다. 엔터 눌러도 된다.


마지막 섹터는 용량을 입력해도 됨. (+64M 이나, +256M, +1G 등)

여기서는 256M 정도가 적당함.


이러면 파티션이 만들어짐.



2번째 파티션은 SD카드의 모든 용량을 사용하게 함.

n -> p -> 엔터 -> 엔터 -> 엔터


와! 이렇게 파티션을 2개로 쪼갬!

p를 입력해 파티션을 조회하자


이제 파일 타입, 부트 가능 영역을 설정해 주어야 함.


1번 파티션 파일 타입을 설정해보자



t -> 1 -> L을 입력한다. 사용 가능한 파티션 리스트가 나오는데

1번 파티션은 fat32를 사용할 것이므로 0b를 입력한다.

t-> 2 -> 83을 입력해 2번 파티션은 LINUX 파일 시스템으로 설정하자.


a -> 1

a -> 2

를 입력해 둘다 부팅 플래그를 켜주자.


최종 설정 완료된 모습



w 저장하고 나가자.


나가서 fdisk -l로 리스트를 찍어보면




mkfs 명령어를 이용해 다시 파일 시스템의 타입을 지정해 포맷해주자.

$ sudo umount /dev/sdb*
$ mkfs.fat -F 32 /dev/sdb1
$ mkfs.ext4 /dev/sdb2








6) 파일 배포하기

1. sd카드에 파일 넣기

아직은 디바이스트리 오버레이는 사용을 안할거임.

BBB의 MLO와 u-boot.img 파일을 /dev/sdb1에 넣어주자. 이때 주의할 점은 MLO u-boot.img 순서를 꼭 지켜야 한다. 마운트를 하던, dd명령어로 넣던 상관없음.


우선 빌드 산출물이 있는 deploy 폴더로 이동하자

$ /home/[님 이름]/yocto/poky/build/deploy-ti/images/beaglebone​
$ cp zImage u-boot.img core-image-full-cmdline-beaglebone-20250208111559.rootfs.tar.xz  am335x-boneblack.dtb ~/share


sd카드가 윈도우에 마운트 되어서 이상한 파일이 생겼을 수도 있음, system volume information이라고 생성되어 있을탠데 이거 꼭 지워줘야함.


여기서 부터는 버추얼 박스로 할거야. 이미지 파일이 있는 share 폴더로 이동해서

$ cd ~/share
sudo mount /dev/sdb1 /mnt
$ sudo rm -rf /mnt/*
$ sudo cp MLO u-boot.img /mnt

/dev/sdb1에 또한 am335x-boneblack.dtb, zImage를 넣어주자

sudo cp am335x-boneblack.dtb zImage /mnt
$ sync
$ sudo umount /mnt
그리고 /dev/sdb2에는 루트 파일 시스템을 넣는다.

$ sudo mount /dev/sdb2 /mnt
$ sudo rm -rf /mnt/*
$ tar -xvf core-image-full-cmdline-beaglebone-20250208111559.rootfs.tar.xz -C /mnt
$ sync
$ cd ~
$ sudo umount /mnt

파일시스템은 core~로시작해서 rootfs.tar.xz로 끝나는 파일인데 이거 tar로 압축풀어주면 됨




이제 term을 키고, 부트로더 설정만 해주면 됨.



2. BBB 부트로더 설정

테라텀 키자

alt -> f -> n을 눌러서 cp210x를 선택하자

cp210x를 선택하면 됨...

BBB 회로도를 보면 uart0가 디버그 핀으로 할당되어 있음.  3.3v cp210x와 연결해주자.

cp210xbbb
gnd1
-2
-3
tx4
rx5
-6

참고로 bbb와 cp210x tx, rx는 서로 크로스해야한다. 


SD 카드와 가까이 있는 스위치를 누르고 전원을 연결한 뒤 부팅하면,



빠르게 엔터를 쳐서 부트로더로 진입하자



ls mmc 0:1, ls mmc 0:2를 쳐서 파티션에 저장되어 있는 파일을 볼 수 있다!



부팅 인자를 설정하자

=> setenv bootargs console=ttyS0,115200n8 rootwait rw root=/dev/mmcblk0p2
=> saveenv
rootwait 빼먹으면 루트 파일시스템이 불러오기 전에 부팅되서 멈출 수 있다. 조심하자.


이제 부트로더에서는 커널 이미지와 디바이스 트리 파일을 불러와주어야 한다.

sd카드이기 때문에 fatload mmc 0:1 [주소] [파일명] 해서 1번 파티션에 불러와주면 된다!

=> fatload mmc 0:1 0x80000000 zImage
=> fatload mmc 0:1 0x8f000000 am335x-boneblack.dtb
=> bootz 0x80000000 - 0x8f000000 
이렇게 부트로더에서 직접 설정해 부팅해 줄 수 있지만, 이 작업이매우 귀찮다.

bootcmd를 설정해주면 된다.

=> setenv bootcmd 'fatload mmc 0:1 0x80000000 zImage; fatload mmc 0:1 0x8f000000 am335x-boneblack.dtb; bootz 0x80000000 - 0x8f000000'
=> saveenv
=> boot

로그인은 root를 치면 된다.



댓글

이 블로그의 인기 게시물

[ BBB - yocto (9) ] 장치트리(DEVICE TREE)

[ BBB - yocto (11) ] uart

[ BBB - yocto (5) ] makefile 작성법과 컴파일 자동화