IMAGE_INSTALL += " myhello "
와 같은 명령어로 따로 설치 할 수 있음packagegroup-
을 시작하는 패키지 이름을 가진다.layer-dir/recipes-*/packagegroups/
packagegroup-'name'.bb 아래와 같이 자주 사용되는 패키지 그룹들이 있음
poky/meta/recipes-core/packagegroups/packagegroup-core-boot.bb
packagegroup-dhyang.bb
로 해본다.RDEPENDS_${PN} = ""
lsblk
명령, lspci
명령, lsusb
명령을 사용하고자 한다.util-linux
, pciutils
, usbutils
컴포넌트를 런타임 디펜던시로 가지고 있다.# ====== poky/my-layer/packagegroups/packagegroup-dhyang.bb ===== #
SUMMARY = "my package group"
inherit packagegroup
RDEPENDS_${PN} = "\
util-linux \
pciutils \
usbutils \
"
$ bitbake packagegroup-dhyang
-g
로 확인가능하다.$ bitbake -g packagegroup-dhyang
pn-buildlist
아웃풋 출력poky/meta/recipe-core/images/core-image-minimal-tiny.bb
라는 자체 제작 이미지에IMAGE_INSTALL += "packagegroup-dhynag"
명시$ bitbake core-image-minimal-tiny
$ runqemu core-image-minimal-tiny
poky/meta/recipes-core/packagegroups/packagegroup-base.bb
가 있다.
inherit packagegroup
PACKAGES = "PG1 PG2 ..."
RDEPENDS_PG1 = "P1 P2 ... PN"
RRECOMMENDS_PG1 = "P1 P2 ... PN"
형식
IMAGE에 대한 bbappend파일을 만들 수도 있다.
meta-skeleton
layer에서 recipes-kernel/hello-mod
Component에서 external kernel module example recipe 가 있다.preinst
: 패키지가 압축 해제 되기 전에 실행된다. 서비스들은 설치나 업그레이드를 위해 preinst
가 실행되기 전에 멈춰야한다.postinst
: 이 스크립트는 패키지가 압축 해제된 후에 필요한 환경설정을 한다. postinst
스크립트의 상당수가 새 피키지가 설치되거나 업그레이드된 이후에 서비스를 재시작하는 명령어를 실행한다.prerm
: 보통 패키지와 관련된 daemon을 멈춘다. 패키지와 관련된 파일이 지워지기 전에 실행된다.postrm
: 주로 패키지에 의해 생성된 파일이나 링크를 수정한다.postinst
)는 rootfs 생성 시 실행된다. 스크립트가 성공적으로 진행되면 패키지는 설치됨(installed)로 표시된다.postinst
스크립트를 추가하려면 다음과 같은 코드를 작성한다.pkg_postinst_${PN} () {
#!/bin/sh -e
# Insert commands abobe
}
스크립트의 실행을 미뤄 타깃 디바이스에서 실행하도록 다음과 같은 구조의 스크립트를 사용한다.
pkg_postinst_${PN} () {
#!/bin/sh -e
if [ -n "$D" ]; then
# Insert commands here
else
exit 1
fi
}
앞 예제에서 어떻게 스크립트의 실행이 미뤄지는지 볼 수 있었다. 변수 $D가 값을 갖고 있다면 이 스크립트는 에러를 반환하고 패키지는 압축 해제됨 상태가 된다. 즉, if 구문에 작성된 문장은 변수 $D가 할당되지 않았을 때만 실행된다.
postscript
의 실행을 건너뛰어 rootfs
를 만드는 시점에 daemon이 실행되는 것을 막고 업그레이드가 완료된 이후에 실행하게 할 수도 있다. 다음 예제를 살펴보자.
pkg_postinst_${PN} () {
#!/bin/sh -e
if [ -n "$D" ]; then
exit 0
fi
# Insert commands here to restart
}
IMAGE_FEATURES
에서 이미지를 read-only-rootfs
로 만들 경우 모든 postinst
스크립트는 성공해야 한다. 어떤 스크립트가 실패하고 패키지를 압축 해제됨 상태로 표기해 rootfs 생성 이후에 돌아가게 된다면 do_rootfs
태스크는 실패한다. 실제 부팅 시점에 filesystem에 기록할 수 없어서 에러가 발생하기 전에 이 방법으로 빌드 시점에 문제를 확인한다.
pkg_postinst
스크립트가 do_rootfs
에서 실행 가능한지 확인하자. IMAGE_FEATURES
변수가 read-only-rootfs
의 경우 필요하다.postinst
스크립트를 작성하는 데 가장 많이 하는 실수는 절대 경로 앞에 변수 $D
를 생략하는 것이다. 이렇게 하면 경로가 호스트와 타깃 환경 모두 유효하게 된다. D
변수가 비어 있는지 확인하면 어떤 환경 변수가 사용됐는지 판별하고, rootfs이 생성되거나 타깃에서 실행되고 있으면 다른 코드를 사용할 수 있다.
많이 하는 실수는 타깃 아키텍처에 관련되거나 종속적인 프로세스를 실행하려 하는 것이다. 가장 간단한 해결책은 이 타깃 스크립트의 실행을 미루는 것이다. 그러나 앞에서 언급한 것 처럼 read-only
파일 시스템에서는 사용하기 어렵다.
레시피에서 다시 빌드할 것인가를 결정하는 전략은 복잡하다. 기본적으로 비트베이크는 빌드에 사용되는 모든 태스크, 변수, 코드에 대해 정보를 최대한 많이 추적한다. 그리고 비트베이크는 모든 태스크에 대해 관련된 모든 정보의 CHK을 생성한다.
포키는 비트베이크가 생성한 이 모든 정보를 이용해 태스크의 스냅샷을 저장하고, 이 패키지로 묶인 캐시 정보를 sstate-cache
라 한다. 이 캐시는 ${SSTATE_DIR}
디렉토리에 저장되고 패키지로 묶인 태스크의 결과를 포함한다. 비트베이크가 태스크를 실행하려 할 때 먼저 일치하는 sstate-cache
패키지가 있는지 확인한다. 패키지가 존재하면 빌드하지 않고 이미 빌드된 패키지를 이용한다. 이것은 shared state cache의 매커니즘에 대한 요약이고, 실제로 상당히 복잡한 코드로 이뤄져 있다. 자세한 내용은 Yocto 프로젝트 레퍼런스 매뉴얼 참고의 shared state cache 절을 살펴보면된다.
포키로 빌드를 한 번에 진행 중이라면 shared state가 빌드할 때마다 커지기 띠ㅐ문에 삭제를 하는 것이 좋다. 다음 명령을 사용하면 쉽게 삭제할 수 있다.
$ poky/scripts/sstate-cache-management.sh --remove-duplicated -d --cachedir=<path to sstate-cache>
이 명령어는 중복된 데이터나 오래된 데이터를 캐시에서 지운다.
${PV}라고 불리는 패키지 버전은 어떤 레시피로 빌드할지 경정할 때 주요한 역할을 한다. 포키의 기본 동작은 앞에서 알아본 preference를 이용해 명시적으로 선언하지 않는한 최신 버전을 이용하는 것이다.
예를들어 myrecipe_1.0.bb
와 myrecipe_1.1.bb
두개의 레시피가 있다면 비트베이크는 기본적으로 1.1.bb
레시피를 빌드한다.
PEPR
(Package Epoch, Package Revision) 변수가 있다. 이 변수는 기본 값으로 0을 사용하고 패키지 버전 정책이 바뀌어 일반적인 버전 순서를 깨뜨릴 수 있을 때 이용한다. PE는 PV앞에 추가되기 때문에 강제로 더 높은 버전을 설정할 필요가 있을 때 사용한다. 예를 들어 패키지가 PV 변수값에 20140101나 20140201과 같이 날짜를 이용한다고 하자. 이때 버전 전책이 바뀌어 새 버전을 1.0으로 릴리스하면 1.0과 20140201 중 어떤 것이 최신 버전인지 구분할 수 없다. 여기서 PE=1 을 사용하면 버전 1.0이 2014.0201보다 높다고 표시할 수 있는데, 이는 내부적으로 1:1.0과 0:201402011을 비교하기 때문이다.
PR
변수는 기본적으로 r0
를 사용하고 버전을 정하는 과정에서 사용된다. 이 변수가 업데이트되면 비트베이크에게 특정 레시피에 대해 모두 재빌드하라고 강제한다. 레시피 메타데이터에서 수동으로 값을 올려 강제로 재빌드하는 것이 필요할 때 사용한다. PR 변수의 값을 수동으로 올리는 것이 편해 보이지만, 이는 사람의 판단에 의존하는 불안정한 방법이다. Dora라 불리는 Yocto 1.5버전 부터 비트베이크는 어떤 모듈을 재빌드할지 결정하기 위해 태스크 체크섬을 이용하고, 태스크 체크섬이 변하지 않았는데 PR을 수동으로 증가시키는 것은 매우 드물다.
대부분 레시피의 최종 결과물은 패키지 관리자가 관리하는 패키지이다. 앞 절에서도 살펴봤듯이 모든 패키지와 패키들이 서로 어떻게 관련돼 있는지에 대한 정보가 필요하다. 예를 들어 어느 한 패키지가 다른 패키지에 의존성이 있거나 충돌이 있을 수 있다. 이런 것들을 표현할 여러 패키지 제약 조건이 있다. 그러나 이런 제약 조건은 패키지 형식에 따라 다르기 때문에 비트베이크는 패키지 제약 조건을 추상화하는데 사용하는 메타데이터 집합을 갖고 있다.
다음은 런타임 제약 조건에서 많이 사용하는 변수다.
RDEPENDS
: 하나의 패키지들 설치할 때, 함께 설치해야할 필요가 잇는 패키지들 목록을 정의한다.RPROVIDES
: 패키지 이름의 별칭을 정의한다. 기본적으로 패키지는 패키지 이름을 갖고 있다. 대안으로 패키지가 제공하는 다른 이름을 이 변수를 가지고 정의할 수도 있다.RCONFLICTS
: 하나의 패키지와 충돌하는 것으로 알려진 패키지를 정의한다. 이 패키지들 중 한 번에 하나만 설치할 수 있다.RREPLACES
: 하나의 패키지의 대안으로 사용할 수 있는 패키지 이름을 정의한다.do_rootfs()
는 루트 파일 시스템을 만들 때 로컬 패키지 저장소를 사용해서 바이너리 패키지를 다운로드한다. 이 저장소는 패키지 피드(package feed)라고 불린다.이 저장소가 이미지나 SDK를 빌드할 때에만 이용될 필요는 없다. 실제로 이 저장소를 프로젝트 내부에서 원격으로 접속할 수 있게 하거나, 외부에 공개할 이유도 충분하다. 다음과 같은 이유가 있을 것이다.
1. 개발 단계에서 업데이트된 애플리케이션에 대해 재설치 없이 쉽게 테스트할 수 있게한다.
2. 추가 패키지를 실행하는 이미지에 업데이트할 수 있게한다.
3. 현장에서 상품을 업데이트한다.
깨지지 않는 패키지 피드를 만들려면 패키지가 변경될 때마다 패키지 리비전(PR)이 증가하는 것을 확인해야 한다. 이를 수작업으로 하는 것은 거의 불가능해서 Yocto 프로젝트는 이를 도와주는 PR 서비스를 제공한다.
비트베이크의 일부인 PR 서비스는 수작업 없이 비트에이크가 레시피의 체크섬이 바뀔 때마다 PR을 자동으로 올려주기 위해 사용된다. 기본적으로 PR에 접미사를 ${PR}.X 형태로 붙인다. 예를 들어 PR = "r34" 일 때, PR 서비스를 사용하면 r34.1, r34.2, r34.3
순서로 증가한다.
이미지를 만들기 위해 포키를 사용하면서 원격 패키지 피드를 사용하지 않으면 PR 서비스는 필요없다. 비트베이크가 태스크의 체크섬이 바뀌면 스스로 재빌드하기 때문이다. PR 서비스는 깨지지 않는 버전이 선형적으로 올라가야하는 패키지 피드를 위해 필수적이다. 깨지지 않는 패키지 버전을 위해 PR 서비스를 사용해야 하지만, 여전히 PR을 수동으로 작업하는 것은 일부 예외 상황에서 필요하다.
기본적으로 PR 서비스는 활성화돼 있지 않다. 로컬에서 이를 활성화시키려면 PRSERV_HOST
변수를 비트베이크 환경설정 파일에 설정해야 한다. 예를 들어 build/conf/local.conf
에 다음과 같이 설정한다.
PRSERV_HOST = "localhost:0"
빌드가 하나의 컴퓨터에서 이뤄질 때에는 패키지 피드의 모든 패키지를 빌드하는데는 이 방법으로 충분하다. 비트베이크는 매 딜드마다 서버를 켰다 끄며 PR 값을 자동적으로 증가시킨다. 여러 컴퓨터가 공통 패키지 피드를 갖고 작업하는 더 복잡한 경우에는 패키지 피드에 관련된 하나의 PR 서비스를 모든 빌드 머신이 이용하게 설정해야 한다. 이 경우네는 다음과 같이 PR 서비스를 bitbake-prserv
명령어로 실행한다.
$ bitbake-prserv --host <ip> --port <port> --start
서버를 시작시키는 것 외에도 모든 빌드 서버의 비트베이크 환경설정 파일(e.g., build/conf/local.conf
)의 PRSERV_HOST
변수에 서버의 IP와 PORT를 적어 서버를 사용하게 해야 한다.
$ bitbake package-index
build/tmp/deploy/rpm
디렉토리 패키지를 사용한다.bitbake package-index
를 실행한다.$ cd build/tmp/deply/rpm
$ python3 -m http.server 5678
패키지 관리자를 이미지에 추가하려면 약간의 작업이 필요하다. EXTRA_IMAGE_FEATURE
변수에 package-management
를 추가하고 PACKAGE_FEED_URIS
변수에 패키지를 다운로드하게 URI를 설정한다. build/conf/local.conf
에 다음을 추가한다.
PACKAGE_FEED_URIS = "http://my-ip-address:5678"
EXTRA_IMAGE_FEATURES += " package-management "
패키지 관리자 지원 없이 작은 이미지를 빌드하려면 EXTRA_IMAGE_FEATURES
변수에 package-management
를 포함시키지 말아야 한다.
PACKAGE_FEED_URI
와 IMAGE_FEATURES
설정은 클라이언트에서 돌아가는 이미지가 서버에 접근해 패키지들을 설치, 제거, 업그레이드할 수 있게 해준다.
이 과정 후에 타깃 디바이스에서 런타임 패키지 관리자를 사용할 수 있다.
예를 들어 이미지를 위해 RPM 형식을 선택했다면 저장소의 정보를 다음명령으로 알 수 있다.
$ dnf check-update
패키지를 설치하기 위해서는 dnf search <package>
와 dnf install <package>
명령어를 사용한다.
선택한 패키지 형식에 따라 타깃에서 패키지 인덱스, 검색, 설치하는 명령어가 다르다. 다음 표에서 각 패키지 형식에 따른 사용 가능한 명령어를 볼 수 있다.
패키지 형식 | RPM | IPK | DEB |
---|---|---|---|
패키지 인덱스 업데이트 | dnf check-updates | opkg update | apt-get update |
패키지 검색 | dnf search <package> | opkg search <package> | apt-cache search <package> |
패키지 설치 | dnf install <package> | opkg install <package> | apt-get install <package> |
시스템 업그레이드 | dnf upgrade | opkg upgrade | apt-get dist-upgrade |
각 단계는 이미 배포한 이미지에서 패키지를 설치할 수 있기 때문에 로컬 개발 단계에서 사용하기에 적합하다.
패키지 피드 관리는 훨씬 더 복잡하며, 패키지 피드 의존성 체인, 다른 업그레이드 시나리오 등과 같은 여러 가지 측면과 관련이 있다. 복잡한 패키지 피드 외부 서버 생성은 Yocto 레퍼런스 문서를 참고하자.
PACKAGE VARIABLE
/poky/meta/conf/bitbake.conf
에 기본 값이 있다.DEPLOY_DIR_DEB
${TMPDIR} = poky/build/tmp
<virtual/kernel>
$ bitbake -c menuconfig <virtual/kernel>
virtual/<name>
형태로 되어 있음virtual/bootloader
: u-boot
,u-boot-ti-staging...
virtual/kernel
: linux-yocto
, linux-yocto-tiny
, linux-yocto-rt
, linux-ti-staging
...virtual/libc
: eglibc
, uclibc
virtual/xserver
: xserver-xorg
menuconfig
다음에 입력하면 된다.kernel code
만 재 build$ bitbake -C compile virtual/kernel
SDK
를 만들려면?$ bitbake -c populate_sdk core-image-minimal
Q4) 특정 패키지의 build directory가 어디인지 알고 싶다면 ?
A4) $ bitbake -e | grep ^WORKDIR=
예를 들어, kernel의 build directory를 찾고 싶다면, 아래와 같이 하면 됨.
$ bitbake -e virtual/kernel | grep ^WORKDIR=
WORKDIR="/home/chyi/IoT/BBB/yocto_fe/poky/build/tmp/work/beaglebone-poky-linux-gnueabi/linux-ti-staging/4.4.19+gitAUTOINC+e581bb1cac-r22a"
() 보충 설명 - kernel 디렉토리 내용 ()
$ cd /home/chyi/IoT/BBB/yocto_fe/poky/build/tmp/work/beaglebone-poky-linux-gnueabi/linux-ti-staging/4.4.19+gitAUTOINC+e581bb1cac-r22a
$ ls -l
Q5) rootfs file system의 위치를 알고 싶다면 ?
A5) $ bitbake -e core-image-minimal | grep ^IMAGE_ROOTFS=
예를 들자면, 아래와 같은 결과를 얻을 수 있겠음.
IMAGE_ROOTFS="/home/chyi/IoT/BBB/yocto_fe/poky/build/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs"
Q6) menuconfig로 수정한 kernel config 내용을 (clean build 이후에도 사용할 수 있도록)저장하려면 ?
A6) $ bitbake -c savedefconfig virtual/kernel
이 명령은 단순히 .config 파일로 부터 dependency 부분을 제거한 후, 같은 디렉토리(build)의 defconfig 파일로 저장하는 역할만 수행함. 따라서 이후 반드시 이 파일(defconfig)을 kernel recipe 디렉토리로 복사해 주어야 함. 예를 들어, (beaglebone black의 경우라면) defconfig 파일을 meta-ti/recipes-kernel/linux/linux-ti-staging-4.4/defconfig에 복사해 주어야만 함.
Q7) kernel, bootloader build 방법을 구체적으로 알고 싶다면 ?
A7) 아래 내용 참조
<BeagleBone Black에 Yocto project를 적용한 예 - 1절 참조>
=> kernel, bootloader를 build하는 방법도 소개되어 있음.
http://slowbootkernelhacks.blogspot.kr/2016/12/booting-beaglebone-black-with-yocto.html
<RIoT board에 Yocto project를 적용한 예 - 5절 참조>
http://slowbootkernelhacks.blogspot.kr/2017/01/riot-board-based-on-freescale-imx-6solo.html
Q8) kernel module build 방법을 구체적으로 알고 싶다면 ?
A8) 아래 내용 참조(2.3절)
http://slowbootkernelhacks.blogspot.kr/2017/05/yocto-project-linux-device-driver.html
내용 출처: https://slowbootkernelhacks.blogspot.com/2016/12/yocto-project.html