Yocto の meta-qt6 の SDK を作成して Qt Creator に設定をする

# はじめに

この記事は [Qt Advent Calendar 2024](https://qiita.com/advent-calendar/2024/qt) ６日目の記事です。

昨日は @CharNoe さんによる [Qtで作ったPC向けアプリケーションをAndroidで動かす話
](https://qiita.com/CharNoe/items/ba6cd0f5bfa05f6be5ce) という記事でした。

元々 Windows 向けに開発していた Qt アプリを Android へ移植したとのことで、「**想像以上に低コストで対応できました**」というのがすごいですね。

---

今回は３日目に書いた [Toradex Verdin AM62 Solo で meta-qt6 を動かしてみた](https://qiita.com/task_jp/items/bfc8594bf6eb022f05d8) の続きで、前回作成して動かした Yocto + meta-qt6 向けに開発環境を整え、アプリケーションを動かしてみます。

# SDK の作成

## docker 内で SDK を作成する

※ 結局 meta-python が必要だったのでここで追加しました。

```console
ubuntu@5f2e1485b731:~/am62$ bitbake-layers add-layer ../layers/meta-openembedded/meta-python/
NOTE: Starting bitbake server...
```

```console
ubuntu@5f2e1485b731:~/am62$ bitbake meta-toolchain-qt6 -k
Loading cache: 100% |                                                                                         | ETA:  --:--:--
Loaded 0 entries from dependency cache.
Parsing recipes: 100% |########################################################################################| Time: 0:00:09
Parsing of 4762 .bb files complete (0 cached, 4762 parsed). 7642 targets, 939 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
NOTE: Resolving any missing task queue dependencies
NOTE: Resolving any missing task queue dependencies
NOTE: Resolving any missing task queue dependencies
NOTE: Resolving any missing task queue dependencies
NOTE: Resolving any missing task queue dependencies

Build Configuration (mc:default):
BB_VERSION           = "2.0.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "ubuntu-24.04"
TARGET_SYS           = "aarch64-oe-linux"
MACHINE              = "verdin-am62"
DISTRO               = "nodistro"
DISTRO_VERSION       = "nodistro.0"
TUNE_FEATURES        = "aarch64"
TARGET_FPU           = ""
meta                 = "HEAD:fb45c5cf8c2b663af293acb069d446610f77ff1a"
meta-arm-toolchain
meta-arm             = "HEAD:936c02ec13661bd86a05f7f90e1b920d5092d670"
meta-ti-bsp          = "HEAD:16e09294cbfc3961af6f041b5b2d785d9ee75853"
meta-toradex-bsp-common = "HEAD:e6a8677f4a5bcf56f4338f4441e64eb2538f52d4"
meta-toradex-ti      = "HEAD:140d7c15af7147dc39bee8727acbf99a3eb34877"
meta-oe              = "HEAD:4ad41baed6236d499804cbfc4f174042d84fce97"
meta-qt6             = "HEAD:d6e576a7d75d0371602e93124c4e2f1c539be8f3"
meta-python          = "HEAD:4ad41baed6236d499804cbfc4f174042d84fce97"


Build Configuration:
BB_VERSION           = "2.0.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "ubuntu-24.04"
TARGET_SYS           = "arm-oe-eabi"
MACHINE              = "verdin-am62-k3r5"
DISTRO               = "nodistro"
DISTRO_VERSION       = "nodistro.0"
TUNE_FEATURES        = "arm armv7a vfp thumb callconvention-hard"
TARGET_FPU           = "hard"
meta                 = "HEAD:fb45c5cf8c2b663af293acb069d446610f77ff1a"
meta-arm-toolchain
meta-arm             = "HEAD:936c02ec13661bd86a05f7f90e1b920d5092d670"
meta-ti-bsp          = "HEAD:16e09294cbfc3961af6f041b5b2d785d9ee75853"
meta-toradex-bsp-common = "HEAD:e6a8677f4a5bcf56f4338f4441e64eb2538f52d4"
meta-toradex-ti      = "HEAD:140d7c15af7147dc39bee8727acbf99a3eb34877"
meta-oe              = "HEAD:4ad41baed6236d499804cbfc4f174042d84fce97"
meta-qt6             = "HEAD:d6e576a7d75d0371602e93124c4e2f1c539be8f3"
meta-python          = "HEAD:4ad41baed6236d499804cbfc4f174042d84fce97"

Initialising tasks: 100% |#####################################################################################| Time: 0:00:02
Sstate summary: Wanted 2424 Local 2422 Mirrors 0 Missed 2 Current 0 (99% match, 0% complete)
NOTE: Executing Tasks
NOTE: Tasks Summary: Attempted 7350 tasks of which 7341 didn't need to be rerun and all succeeded.
```

## ホスト PC へコピーをする

```console
ubuntu@fee456f40266:~/am62$ ls deploy-ti/sdk/
oecore-x86_64-aarch64-toolchain-nodistro.0.host.manifest  oecore-x86_64-aarch64-toolchain-nodistro.0.target.manifest
oecore-x86_64-aarch64-toolchain-nodistro.0.sh             oecore-x86_64-aarch64-toolchain-nodistro.0.testdata.json
buntu@fee456f40266:~/am62$ scp deploy-ti/sdk/oecore-x86_64-aarch64-toolchain-nodistro.0.sh tasuku@172.17.0.1:/home/tasuku/Downloads
(tasuku@172.17.0.1) Password:
oecore-x86_64-aarch64-toolchain-nodistro.0.sh                                                                                             100% 1174MB 665.4MB/s   00:01
```

# SDK のインストール

```console
 $ ~/Downloads/oecore-x86_64-aarch64-toolchain-nodistro.0.sh
OpenEmbedded SDK installer version nodistro.0
=============================================
Enter target directory for SDK (default: /usr/local/oecore-x86_64):
You are about to install the SDK to "/usr/local/oecore-x86_64". Proceed [Y/n]? Y
Extracting SDK..........................................................................................................................................................................................................................................................done
Setting it up...done
SDK has been successfully set up and is ready to be used.
Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g.
 $ . /usr/local/oecore-x86_64/environment-setup-aarch64-oe-linux
```

## SDK の内容を確認する

```console
$ . /usr/local/oecore-x86_64/environment-setup-aarch64-oe-linux
$ type -p $CC
/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/aarch64-oe-linux/aarch64-oe-linux-gcc
$ type -p $CXX
/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/aarch64-oe-linux/aarch64-oe-linux-g++
$ type -p $GDB
/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/aarch64-oe-linux/aarch64-oe-linux-gdb
$ type -p qmake
/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/qmake
$ type -p cmake
/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/bin/cmake
$ echo $SDKTARGETSYSROOT
/usr/local/oecore-x86_64/sysroots/aarch64-oe-linux
```

# Qt Creator の設定をする

Qt Creator 15 を利用しています。バージョンによっては多少異なることがあります。

## コンパイラーの登録

左側の「Kits」からまずはコンパイラーの登録をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/490bb688-3eac-a3f3-b30a-f11bc4bb68b8.png)

`type -p $CC` の値を設定します。

## デバッガーの登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/173cb8bb-2b7a-4e81-3dd8-f15970cf9ba3.png)

`type -p $GDB` の値を設定します。

## qmake の登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/2f9e1f4c-d404-e8d9-bd5c-c7b3880bfc49.png)

`type -p qmake` の値を登録します。

## CMake の登録

左側の「CMake」から登録をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/096848f7-9dc1-a0fd-83a9-8f4783eb49dd.png)


## デバイスの登録

左側の「Devices」から登録をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/905be587-f8c7-440a-2fe1-1c2252396757.png)

`Remote Linux Device` として登録をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/b5275935-656a-9032-0d62-20c1b13e2180.png)

ホスト名は `verdin-am62.local` でアクセスができます。

事前に `ssh root@verdin-am62.local` が成功することを確認しておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/76cd8fbb-4024-d1ae-629e-b33bb082e01f.png)

`verdin-am62.local` は `root` ユーザーで（空の）パスワードで入るため、キーのデプロイは不要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/5459d9e7-9e58-55a9-e9f4-4814ff7ea23a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/5d05fc74-703f-e2c0-6b59-ad0b66e40a99.png)

`Access via` が `Local PC` になっていない場合は設定し、右側の `Test` を試します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/acab07cb-fc86-37a8-1ff0-8e543165dba1.png)

大体成功しますが、以下のとおり `rsync` 等いくつかは失敗しました。

```console
Connecting to device...
Connected. Now doing extended checks.

Sending echo to device...
Device replied to echo with expected contents.

Sending echo to device...
Device replied to echo with expected contents.

Checking kernel version...
Linux 6.1.83-0+git.dd30c7ec04b8 aarch64

Checking if specified ports are available...
All specified ports are available.

Checking whether "generic file copy" works...
"generic file copy" is functional.

Checking whether "sftp" works...
"sftp" is functional.

Checking whether "rsync" works...
"rsync" failed with exit code 12: sh: rsync: not found
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(231) [Receiver=3.3.0]


Checking if required commands are available...
base64...
base64 not found.
cat...
cat found.
chmod...
chmod found.
cp...
cp found.
cut...
cut found.
dd...
dd found.
df...
df found.
echo...
echo found.
eval...
eval found.
exit...
exit found.
kill...
kill found.
ls...
ls found.
mkdir...
mkdir found.
mkfifo...
mkfifo found.
mktemp...
mktemp found.
mv...
mv found.
printf...
printf found.
read...
read found.
readlink...
readlink found.
rm...
rm found.
sed...
sed found.
sh...
sh found.
shift...
shift found.
stat...
stat found.
tail...
tail found.
test...
test found.
touch...
touch found.
trap...
trap found.
which...
which found.
Device test failed.
```

## Kit の登録

左側の「Kits」に戻って登録をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/7a53fe4c-17ab-2f8c-fb4d-410b97b4f88c.png)

|設定項目|設定|
|------:|---|
|Run device type|Remote Linux Device|
|Run device|上記で作成したデバイスの名前|
|Compiler|上記で追加したコンパイラー|
|Debugger|上記で追加したデバッガー|
|Sysroot|`$SDKTARGETSYSROOT` の値|
|Qt version|上記で追加した Qt|
|Qt mkspec|空欄（デフォルト）で問題ないと思います|
|CMake Tool|上記で追加した CMake|
|CMake Configuration|`-DCMAKE_TOOLCHAIN_FILE:FILEPATH=/usr/local/oecore-x86_64/sysroots/x86_64-oesdk-linux/usr/lib/cmake/Qt6/qt.toolchain.cmake` を追加します|

# Qt アプリの作成と実行

では、アプリを作成して実機で動かしてみましょう。

## アプリの作成

Qt Quick のテンプレートを使いましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/0e96ec2c-859b-9351-915e-049d58c3324c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/e825649a-4f16-5973-c7bf-2b1f06493b1b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/ef6bd270-ddfe-0b99-be35-6fed74264978.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/9c5526dc-5c5e-c684-b57d-a964776b3b41.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/c048a4ee-4175-3f9d-9331-cae8e6213f23.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/95ac763b-6747-3a04-aff2-d1feb4d62778.png)

上記で作成した Kit を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/d6d54c6c-0f36-2df9-0953-29dea501c166.png)

## ビルドと実行

デフォルトで実機で動く設定がすべて完了しているため、`Ctrl+R` で実行すると実機でアプリが立ち上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/b1a536de-b181-e5fe-ea32-1f7ff53ee18f.png)

![6237848980331544826.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/f7851be4-4990-b5e5-cdbb-c3fc3f2550d4.jpeg)

あまりにもあっさり動いてしまって、不思議ですね。

以下のように少し QML を変更して、再度実行してみます。

```qml
import QtQuick

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Rectangle {
        width: 100
        height: 100
        color: 'red'
        anchors.centerIn: parent

        RotationAnimation on rotation {
            from: 0
            to: 360
            duration: 5000
            running: true
            loops: Animation.Infinite
        }
    }
}
```

![qtquick.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/389bdfb6-0759-af29-3bc9-937c02d9e8cd.gif)

## デバッグ

現時点ではそのままは動かないので、別途記事を書こうと思います。


# 終わりに

[Toradex Japan 株式会社](https://www.toradex.com/ja-jp) からお借りした Verdin AM62 で、Qt アプリを開発するための環境を整備し、実際にアプリを実行してみました。

実機でのアプリの実行がシームレスに行えてとても効率的ですね！

明日は @hermit4 さんがなにか書いてくれるそうなので、楽しみに待ちましょう。