はじめに
meta-tegraがjetson nano
に対応したので、yoctoで動かしてみる。
いくつか注意点
readmeに重要な注意点がいくつか書いてある。
Jetson-TX1についても書いてあるけど関係ないので無視。
そして最後に重要なやつ。
Toolchain version selection is usually a distro configuration setting, but you can also set this in your build/conf/local.conf file. To use gcc 7 instead of gcc 8, set: GCCVERSION = "7.%" but you will also need the gcc 7 toolchain recipes in one of your layers, since it was retired from OE-Core in favor of gcc 8.
local.confでGCCVERSION = "7.%"
と設定すればgcc7系を選択しようとするけど、
warrior
ブランチではgcc7系のレシピは削除されているので、自分でレイヤ作ってgcc7系のレシピを用意してね!
とのこと。
JetPackのインストール
CUDAを使用するためにはNVIDIAのプロプライエタリな成果物を必要とするため yocto環境だけでは完結しない。
予めNVIDIA Developer Network(Devnet)
にログインしJetPackのパッケージをインストールしておく必要がある。
このためにはDevnetのアカウントを作成する必要がある。
NVIDIAのサイトでJOIN
をクリックし、指示に従ってアカウントを作成する。
アカウントの作成ができたら、ここからNVIDIA SDK Manager
をダウンロードする。
debパッケージなのでgdebiコマンドでインストールと便利。
$ sudo gdebi sdkmanager_0.9.11-3405_amd64.deb
SDK Managerを起動する。
$ sdkmanager
ログイン画面が表示されるのでDevnetのアカウントでログインする。
Target HardwareをJetson Nano
に変更する。
I accept the terms and conditions of the license agreements
にチェックを入れる。
Linuxの管理者権限のパスワード(sudo)を入力する。 ログインパスワードではないので注意。
セットアップの項目が出てくるので、全部スキップする。
本当にスキップするか確認されるのでYesをクリック
完了。
環境構築
ソース取得
Jetson Nanoはmeta-tegraのmasterかwarriorブランチでのみ対応している。
masterブランチのLAYERSERIES_COMPAT
がwarrior
に設定されているので、
thud
以前のバージョンでは使用できない。
warrior
は開発中のステータスだが、今回はこれを使う。
$ mkdir -p jetson-warrior/layers $ cd jetson-warrior/layers $ git clone git://git.yoctoproject.org/poky.git -b warrior $ git clone git://git.openembedded.org/meta-openembedded $ git clone https://github.com/madisongh/meta-tegra.git -b warrior $ cd ../
meta-openembedded
はwarrior
ブランチがまだ無いので、master
ブランチを使用する。
環境変数設定
$ source layers/poky/oe-init-build-env build
自動的にビルドディレクトリに移動される。 これで、bitbake関連のツールが使用可能になる。
レイヤ追加
$ bitbake-layers add-layer ../layers/meta-openembedded/meta-oe $ bitbake-layers add-layer ../layers/meta-tegra/
meta-localの作成
先述の通りgcc7系のレシピを用意する必要があるので、そのためのレイヤを作成する。
$ bitbake-layers create-layer meta-local $ rm -rf ./meta-local/recipes-example $ mkdir -p ./meta-local/recipes-devtools/gcc $ mv meta-local ../layers $ bitbake-layers add-layer ../layers/meta-local
pokyリポジトリから古いレシピを取り出す。
$ pushd . $ cd ../layers/poky/meta/recipes-devtools/gcc $ git checkout -b thud origin/thud $ cp -ra *7.3* ../../../../meta-local/recipes-devtools/gcc/ $ cp *.inc ../../../../meta-local/recipes-devtools/gcc/ $ rm -f ../../../../meta-local/recipes-devtools/gcc/*8.* $ git checkout warrior $ git branch -D thud $ popd
gccレシピの修正
warriorではgcc-initialが廃止されるなど、glibcとの依存関係が変更されているためレシピを修正する必要がある。
diff --git a/recipes-devtools/gcc/gcc-cross-canadian.inc b/recipes-devtools/gcc/gcc-cross-canadian.inc index 2f32d34..e7c08d3 100644 --- a/recipes-devtools/gcc/gcc-cross-canadian.inc +++ b/recipes-devtools/gcc/gcc-cross-canadian.inc @@ -3,7 +3,7 @@ inherit cross-canadian SUMMARY = "GNU cc and gcc C compilers (cross-canadian for ${TARGET_ARCH} target)" PN = "gcc-cross-canadian-${TRANSLATED_TARGET_ARCH}" -DEPENDS = "virtual/${TARGET_PREFIX}gcc virtual/${HOST_PREFIX}gcc-crosssdk virtual/${HOST_PREFIX}binutils-crosssdk virtual/nativesdk-${HOST_PREFIX}libc-for-gcc nativesdk-gettext flex-native" +DEPENDS = "virtual/${TARGET_PREFIX}gcc virtual/${HOST_PREFIX}gcc-crosssdk virtual/${HOST_PREFIX}binutils-crosssdk virtual/nativesdk-libc nativesdk-gettext flex-native virtual/libc" GCCMULTILIB = "--enable-multilib" diff --git a/recipes-devtools/gcc/gcc-cross.inc b/recipes-devtools/gcc/gcc-cross.inc index 89b1968..3274d08 100644 --- a/recipes-devtools/gcc/gcc-cross.inc +++ b/recipes-devtools/gcc/gcc-cross.inc @@ -2,7 +2,7 @@ inherit cross INHIBIT_DEFAULT_DEPS = "1" EXTRADEPENDS = "" -DEPENDS = "virtual/${TARGET_PREFIX}binutils virtual/${TARGET_PREFIX}libc-for-gcc ${EXTRADEPENDS} ${NATIVEDEPS}" +DEPENDS = "virtual/${TARGET_PREFIX}binutils ${EXTRADEPENDS} ${NATIVEDEPS}" PROVIDES = "virtual/${TARGET_PREFIX}gcc virtual/${TARGET_PREFIX}g++" python () { if d.getVar("TARGET_OS").startswith("linux"): @@ -31,7 +31,6 @@ EXTRA_OECONF += "\ --with-system-zlib \ " -DEPENDS_remove_libc-baremetal := "virtual/${TARGET_PREFIX}libc-for-gcc" EXTRA_OECONF_append_libc-baremetal = " --without-headers" EXTRA_OECONF_remove_libc-baremetal = "--enable-threads=posix" EXTRA_OECONF_remove_libc-newlib = "--enable-threads=posix" @@ -44,6 +43,11 @@ EXTRA_OECONF_PATHS = "\ ARCH_FLAGS_FOR_TARGET += "-isystem${STAGING_DIR_TARGET}${target_includedir}" +do_configure_prepend () { + install -d ${RECIPE_SYSROOT}${target_includedir} + touch ${RECIPE_SYSROOT}${target_includedir}/limits.h +} + do_compile () { export CC="${BUILD_CC}" export AR_FOR_TARGET="${TARGET_SYS}-ar" diff --git a/recipes-devtools/gcc/gcc-crosssdk.inc b/recipes-devtools/gcc/gcc-crosssdk.inc index cda2927..bd2e71d 100644 --- a/recipes-devtools/gcc/gcc-crosssdk.inc +++ b/recipes-devtools/gcc/gcc-crosssdk.inc @@ -8,5 +8,5 @@ SYSTEMLIBS1 = "${SDKPATHNATIVE}${libdir_nativesdk}/" GCCMULTILIB = "--disable-multilib" -DEPENDS = "virtual/${TARGET_PREFIX}binutils-crosssdk virtual/nativesdk-${TARGET_PREFIX}libc-for-gcc gettext-native ${NATIVEDEPS}" +DEPENDS = "virtual/${TARGET_PREFIX}binutils-crosssdk gettext-native ${NATIVEDEPS}" PROVIDES = "virtual/${TARGET_PREFIX}gcc-crosssdk virtual/${TARGET_PREFIX}g++-crosssdk" diff --git a/recipes-devtools/gcc/libgcc-initial.inc b/recipes-devtools/gcc/libgcc-initial.inc index 950ad86..6edbd30 100644 --- a/recipes-devtools/gcc/libgcc-initial.inc +++ b/recipes-devtools/gcc/libgcc-initial.inc @@ -1,20 +1,58 @@ +# +# Notes on the way the OE cross toolchain now works +# +# We need a libgcc to build glibc. Tranditionally we therefore built +# a non-threaded and non-shared compiler (gcc-cross-initial), then use +# that to build libgcc-initial which is used to build glibc which we can +# then build gcc-cross and libgcc against. +# +# We were able to drop the glibc dependency from gcc-cross, with two tweaks: + +# a) specify the minimum glibc version to support in a configure option +# b) create a dummy limits.h file so that later when glibc creates one, +# the headers structure has support for it. We can do this with a simple +# empty file +# +# Once gcc-cross is libc independent, we can use it to build both +# libgcc-initial and then later libgcc. +# +# libgcc-initial is tricky as we need to imitate the non-threaded and +# non-shared case. We can do that by hacking the threading mode back to +# "single" even if gcc reports "posix" and disable libc presence for the +# libgcc-intial build. We have to create the dummy limits.h to avoid +# compiler errors from a missing header. +# +# glibc will fail to link with libgcc-initial due to a missing "exception +# handler" capable libgcc (libgcc_eh.a). Since we know glibc doesn't need +# any exception handler, we can safely symlink to libgcc.a. +# + require libgcc-common.inc -DEPENDS = "virtual/${TARGET_PREFIX}gcc-initial" +DEPENDS = "virtual/${TARGET_PREFIX}gcc" LICENSE = "GPL-3.0-with-GCC-exception" -STAGINGCC = "gcc-cross-initial-${TARGET_ARCH}" -STAGINGCC_class-nativesdk = "gcc-crosssdk-initial-${SDK_SYS}" -PATH_prepend = "${STAGING_BINDIR_TOOLCHAIN}.${STAGINGCC}:" - PACKAGES = "" EXTRA_OECONF += "--disable-shared" -COMPILERINITIAL = "-initial" - inherit nopackages # We really only want this built by things that need it, not any recrdeptask deltask do_build + +do_configure_prepend () { + install -d ${STAGING_INCDIR} + touch ${STAGING_INCDIR}/limits.h + sed -i -e 's#INHIBIT_LIBC_CFLAGS =.*#INHIBIT_LIBC_CFLAGS = -Dinhibit_libc#' ${B}/gcc/libgcc.mvars + sed -i -e 's#inhibit_libc = false#inhibit_libc = true#' ${B}/gcc/Makefile +} + +do_configure_append () { + sed -i -e 's#thread_header = .*#thread_header = gthr-single.h#' ${B}/${BPN}/Makefile +} + +do_install_append () { + ln -s libgcc.a ${D}${libdir}/${TARGET_SYS}/${BINV}/libgcc_eh.a +} \ No newline at end of file diff --git a/recipes-devtools/gcc/libgcc.inc b/recipes-devtools/gcc/libgcc.inc index 5f1dff6..e4e0c48 100644 --- a/recipes-devtools/gcc/libgcc.inc +++ b/recipes-devtools/gcc/libgcc.inc @@ -1,6 +1,6 @@ require libgcc-common.inc -DEPENDS = "virtual/${TARGET_PREFIX}gcc virtual/${TARGET_PREFIX}g++" +DEPENDS = "virtual/${TARGET_PREFIX}gcc virtual/${TARGET_PREFIX}g++ virtual/${MLPREFIX}libc" do_install_append_class-target () { if [ "${TCLIBC}" != "glibc" ]; then
次の2つの修正を参考にした。
https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/meta/recipes-devtools/gcc?id=0afd3ac3ada35dd986aaf3be41d7177dc6b71ade https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/meta/recipes-devtools/gcc?id=1867965acd5291725069346eda9b239e60af2694
libxcryptのエラー回避
missing-attributes
のオプションが原因でエラーになるのでbbappend
を追加して回避する。
$ recipetool newappend -e ../layers/meta-local libxcrypt
このコマンドでエディタが起動するので次の内容を記述する。
TARGET_CPPFLAGS_remove = "-Wno-error=missing-attributes" CPPFLAGS_remove_class-nativesdk = " -Wno-error=missing-attributes"
local.confの修正
色々と注意する点がある。
MACHINEの設定
MACHINE = "jetson-nano"
NVIDIA_DEVNET_MIRRORの設定
sdkmanagerがダウンロードしたファイルを格納しているディレクトリをNVIDIA_DEVNET_MIRROR
で指定する必要がある。
筆者の環境では~/Downloads/nvidia/sdkm_downloads
になっていた。
NVIDIA_DEVNET_MIRROR = "file://${HOME}/Downloads/nvidia/sdkm_downloads"
gcc7を選択
CUDA10ではgccのバージョンが7で固定されているらしいのでGCCVERSION = '7.%'
が必要。
GCCVERSION = "7.%"
DEBUG_PREFIX_MAPの変更
gcc7を使用する場合EXTRA_OECONF変数の中にmacro-prefix-map
があると、libgccのdo_configureでエラーがになるため回避。
DEBUG_PREFIX_MAP = " -fdebug-prefix-map=${WORKDIR}=/usr/src/debug/${PN}/${EXTENDPE}${PV}-${PR} \ -fdebug-prefix-map=${STAGING_DIR_HOST}= \ -fdebug-prefix-map=${STAGING_DIR_NATIVE}= \ "
パッケージシステムの変更
デフォルトではrpmを使用するようになっているが、NVIDIAが提供するプロプライエタリなパッケージがdeb形式なので、 PACKAGE_CLASSESを変更する。
PACKAGE_CLASSES = "package_deb"
SDカードイメージ出力の設定
SDカードに直接ddで書き込めるイメージを生成するために次の内容を追加する。
IMAGE_CLASSES += "image_types_tegra" IMAGE_FSTYPES = "tegraflash"
SDカードイメージのサイズ変更(オプション)
これはやらなくてもいいが、デフォルトでは16Gのイメージが生成される。
容量が大きめのSDカードを用意する必要があること、書き込みに時間がかかることから、 OSを頻繁に作り直す場合は不便となる。
TEGRAFLASH_SDCARD_SIZE
で変更できる。
TEGRAFLASH_SDCARD_SIZE = "3G"
数字の部分は整数のみ。3.5G
などの表記はできないのでそのようなサイズを指定したい場合は3500M
などとする。
cuda関連パッケージ
cuda関連のパッケージを追加する。
# cuda IMAGE_INSTALL_append = " \ cuda-toolkit \ cudnn \ tegra-tools \ opencv \ "
サンプルパッケージ
サンプルプログラムを収録したパッケージを追加する。
# samples IMAGE_INSTALL_append = " \ opencv-samples \ cudnn-samples \ cuda-samples \ libvisionworks-sfm-samples \ libvisionworks-tracking \ tensorrt-samples \ "
イメージのビルド
最小構成のビルド。
$ bitbake core-image-minimal
この他にcore-image-sato
、core-image-weston
がビルドできることを確認した。
SDカードの作成
ddコマンドでsdcardイメージを書き込む。
$ sudo dd if=./tmp/deploy/core-image-weston-jetson-nano.sdcard of=/dev/sdX bs=100M
/dev/sdX
は環境に応じてsdbやsdcなどに適宜変更する。
SDKの作成
次のコマンドでSDKを作成する。今回はcore-image-weston
をベースにSDKを作成した。
$ bitbake core-image-weston -c populate_sdk
下記のようなWARNINGが出るが、SDK自体は作成された。
The following packages have unmet dependencies: apt-dev : Depends: apt (= 1.2.24-r0) but it is not going to be installed Recommends: bash-dev Recommends: libcurl-dev but it is not installable Recommends: liblzma-dev but it is not installable Recommends: shadow-sysroot-dev but it is not installable cogl-1.0-dev : Depends: cogl-1.0 (= 1.22.2-r0) Recommends: libcogl-dev but it is not installable Recommends: libcogl-gles2-dev but it is not installable Recommends: libcogl-pango-dev but it is not installable Recommends: libcogl-path-dev but it is not installable dpkg-dev : Depends: dpkg (= 1.19.4-r0) but it is not going to be installed Recommends: dpkg-start-stop-dev but it is not installable Recommends: libbz2-dev but it is not installable Recommends: liblzma-dev but it is not installable Recommends: perl-dev Recommends: perl-module-carp-dev but it is not installable Recommends: perl-module-constant-dev but it is not installable Recommends: perl-module-cwd-dev but it is not installable Recommends: perl-module-digest-dev but it is not installable Recommends: perl-module-digest-md5-dev but it is not installable Recommends: perl-module-errno-dev but it is not installable Recommends: perl-module-exporter-dev but it is not installable Recommends: perl-module-fcntl-dev but it is not installable Recommends: perl-module-feature-dev but it is not installable Recommends: perl-module-file-basename-dev but it is not installable Recommends: perl-module-file-compare-dev but it is not installable Recommends: perl-module-file-copy-dev but it is not installable Recommends: perl-module-file-find-dev but it is not installable Recommends: perl-module-file-path-dev but it is not installable Recommends: perl-module-file-spec-dev but it is not installable Recommends: perl-module-file-temp-dev but it is not installable Recommends: perl-module-filehandle-dev but it is not installable Recommends: perl-module-io-dev but it is not installable Recommends: perl-module-io-handle-dev but it is not installable Recommends: perl-module-io-seekable-dev but it is not installable Recommends: perl-module-list-util-dev but it is not installable Recommends: perl-module-overload-dev but it is not installable Recommends: perl-module-parent-dev but it is not installable Recommends: perl-module-posix-dev but it is not installable Recommends: perl-module-scalar-util-dev but it is not installable Recommends: perl-module-selectsaver-dev but it is not installable Recommends: perl-module-storable-dev but it is not installable Recommends: perl-module-symbol-dev but it is not installable Recommends: perl-module-term-ansicolor-dev but it is not installable Recommends: perl-module-tie-handle-dev but it is not installable Recommends: perl-module-tie-hash-dev but it is not installable Recommends: perl-module-time-hires-dev but it is not installable Recommends: perl-module-time-piece-dev but it is not installable Recommends: perl-module-xsloader-dev but it is not installable Recommends: update-alternatives-opkg-dev but it is not installable target-sdk-provides-dummy-dev : Depends: target-sdk-provides-dummy (= 1.0-r0) but it is not going to be installed E: Unable to correct problems, you have held broken packages.
まとめ
gccバージョンやコンパイルオプションなど意外と罠が多かった。 結局、jetbackのインストールなどが必要となるので、わざわざyoctoでやる必要は薄い気がした。
ツールチェインを含め、より自由度の高いOSを作成できるのはやはり利点か。