はじめに
NVIDIA Jetsonで、JetPack SDKを利用するDockerイメージをクロスコンパイルする方法を紹介する。
動作確認環境
- コンパイル環境
- Ubuntu 22.04 x86_64
- Docker 27.3.1
- buildx: v0.17.1
- Buildxによるクロスコンパイル環境導入済み
- buildx: v0.17.1
- ターゲット環境
- NVIDIA JetPack
- 5.0.2
- 5.1.1
- 5.1.2
- NVIDIA JetPack
方法
事前準備:QEMUの導入
コンパイル環境に、Dockerを用いたQEMU環境を構築する。
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
QEMUが有効になったか確認する。
cat /proc/sys/fs/binfmt_misc/qemu-aarch64
flagsにFが入っていれば成功。
enabled
interpreter /usr/bin/qemu-aarch64
flags: OCF
offset 0
magic 7f454c460201010000000000000000000200b7
Dockerイメージの作成
ポイント
- ベースとするDockerイメージは、NVIDIA社から提供されているJetson用のDockerイメージを使う
- 上記イメージには、JetPack SDKのライブラリファイルが含まれないので、Dockerfile内でJetPack SDKのライブラリを参照する必要がある場合は、Dockerfile内でダウンロードする
ベースとするJetsonのDockerイメージは、NGCで公開されている。
Dockerイメージ名 | 概要 |
---|---|
nvcr.io/nvidia/l4t-base | Linux for Tegraの一番シンプルなコアとなるイメージ |
nvcr.io/nvidia/l4t-jetpack | 上記にJetPack SDKが付属したイメージ |
今回は、JetPack SDKを利用するので、nvcr.io/nvidia/l4t-jetpack
をベースのDockerイメージとする。
JetPack SDKライブラリファイルを配置する
JetPack SDKのライブラリを使ってクロスコンパイルするには、ライブラリファイルをDockerfile内で配置する必要がある。
JetPack SDKは、nvcr.io/nvidia/l4t-jetpack
に導入されるが、これらのSDKに依存したソースのコンパイルを行うには、ライブラリファイル(.so)が必要となる。ライブラリファイルは、Dockerの起動時のruntimeで指定されるので、Dockerイメージ作成時のクロスコンパイル環境では利用できない制約がある。(また、Jetson上でのDocker buildにおいても、runtimeを指定する必要がある。)
そこで、Dockerfile内で、NVIDIAから提供されているDriver Package(BSP)をダウンロードして展開することで、ライブラリファイルを参照できるようにする。BSPは、JetPackごとに公式サイトから提供されている。
ここでは、JetPack 5.1.2の場合の例を示す。JetPack 5.1.2は、Jetson Linux 35.4.1に相当するので、こちらの以下のDRIVERS -> Driver Package (BSP) からダウンロードする。また、ベースとなるDockerイメージは、こちらからnvcr.io/nvidia/l4t-jetpack:r35.4.1
とする。
以下にDockerfileの例を示す。JetPack SDKのライブラリは、/usr/lib/aarch64-linux-gnu/tegra
に配置する必要があるので、BSPからダウンロードしたライブラリのシンボリックリンクusr/lib/aarch64-linux-gnu/tegra
に作成する。
Dockerfile内でのクロスコンパイルの例として、JetsonのMultimedia APIサンプルをビルドする。
cd <your_workspace>
vi Dockerfile
FROM nvcr.io/nvidia/l4t-jetpack:r35.4.1
# tegraライブラリのシンボリックリンクを作成
# JetPack BSP
# 5.0.2(r35.1.0): https://developer.nvidia.com/embedded/l4t/r35_release_v1.0/release/jetson_linux_r35.1.0_aarch64.tbz2
# 5.1.1(r35.3.1): https://developer.nvidia.com/downloads/embedded/l4t/r35_release_v3.1/release/jetson_linux_r35.3.1_aarch64.tbz2
# 5.1.2(r35.4.1): https://developer.nvidia.com/downloads/embedded/l4t/r35_release_v4.1/release/jetson_linux_r35.4.1_aarch64.tbz2
ARG JETSON_BSP_FILE=https://developer.nvidia.com/downloads/embedded/l4t/r35_release_v4.1/release/jetson_linux_r35.4.1_aarch64.tbz2
RUN echo "Jetson BSP drivers wget URL : " ${JETSON_BSP_FILE} && \
cd /tmp && \
wget ${JETSON_BSP_FILE} && \
tar -jxpf jetson_linux_r35*aarch64.tbz2 && \
cd Linux_for_Tegra/nv_tegra && \
tar -jxpf nvidia_drivers.tbz2 && \
cd /usr/lib/aarch64-linux-gnu && \
echo "Create jetson lib symbolic links" && \
ln -s /tmp/Linux_for_Tegra/nv_tegra/usr/lib/aarch64-linux-gnu/tegra tegra
# 以下にJetson SDKを使ったライブラリのビルドなどを記載
# 例として、Multimedia APIサンプルをビルド
# サンプルのビルドに必要な依存をインストール
RUN apt update && apt install -y libdrm-dev libvulkan-dev
RUN cd /usr/src/jetson_multimedia_api/samples/00_video_decode && \
make
# ライブラリのビルドが完了後、tegraライブラリのシンボリックリンクを削除
RUN echo "Delete jetson dependencies: " "${ARCH}" && \
unlink /usr/lib/aarch64-linux-gnu/tegra && \
rm -rf /tmp/Linux_for_Tegra && \
rm -rf /tmp/jetson_linux_r35*aarch64.tbz2
DockerfileからArm64環境のDockerイメージを作成する。Buildxの環境構築などはこちらの記事を参照。
docker buildx build --platform linux/arm64 -t <image_name>:latest .
Multimedia APIサンプルのビルドが成功すると、Dockerイメージ内にvideo_decode
の実行ファイルが生成される。
make[1]: Entering directory '/usr/src/jetson_multimedia_api/samples/common/classes'
Compiling: NvDrmRenderer.cpp
Compiling: NvLogging.cpp
Compiling: NvEglRenderer.cpp
Compiling: NvBufSurface.cpp
Compiling: NvJpegDecoder.cpp
Compiling: NvVideoEncoder.cpp
Compiling: NvV4l2ElementPlane.cpp
Compiling: NvVulkanRenderer.cpp
Compiling: NvV4l2Element.cpp
make[1]: Leaving directory '/usr/src/jetson_multimedia_api/samples/common/classes'
Linking: video_decode
Multimedia APIサンプルのビルドに失敗すると、以下のようにJetPack SDKライブラリが見つからずのリンカエラーとなる。
make[1]: Entering directory '/usr/src/jetson_multimedia_api/samples/common/classes'
Compiling: NvDrmRenderer.cpp
Compiling: NvLogging.cpp
Compiling: NvEglRenderer.cpp
Compiling: NvBufSurface.cpp
Compiling: NvJpegDecoder.cpp
Compiling: NvVideoEncoder.cpp
Compiling: NvV4l2ElementPlane.cpp
Compiling: NvVulkanRenderer.cpp
Compiling: NvV4l2Element.cpp
make[1]: Leaving directory '/usr/src/jetson_multimedia_api/samples/common/classes'
Linking: video_decode
/usr/bin/ld: cannot find -lnvv4l2
/usr/bin/ld: cannot find -lnvbufsurface
/usr/bin/ld: cannot find -lnvbufsurftransform
/usr/bin/ld: cannot find -lnvjpeg
/usr/bin/ld: cannot find -lnvosd
/usr/bin/ld: cannot find -lcuda
collect2: error: ld returned 1 exit status
make: *** [Makefile:53: video_decode] Error 1
上記のエラーとなる場合は、JetPack SDKのライブラリが参照できていないので、BSPパッケージのダウンロードやシンボリックリンクの記述を見直してDockerfileを修正する。
動作確認
作成したDockerイメージを起動して動作確認を行う。
docker run -it --rm <image_name>:latest /bin/bash
Dockerコンテナ内のターミナルには入れれば成功。
cd /usr/src/jetson_multimedia_api/samples/00_video_decode
ls | grep video_decode
video_decode
video_decode
が存在しない場合は、Dockerイメージが上手く作成できていないので再度作成する。
まとめ
NVIDIA Jetsonで、JetPack SDKを利用するDockerイメージをクロスコンパイルする方法を紹介した。JetPack SDKを使った自作のライブラリなどをクロスコンパイルする際に有用。
参考