みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

YoctoProject devtool addでローカルのソースをレシピ化することを考える

はじめに

devtool addはレシピ作成の大半の処理をrecipetool createで行っているが、 どちらのツールもネットワーク越しに公開されているソースコードからレシピを作成することを前提としている。

つまり、ローカルストレージ上にあってネットワーク上で公開されていないソースファイルをこれらのツールで レシピ化するにはハードルがあるということになる。

このようなソースコードからdevtool addを使用してレシピを作成するにはどうすればよいのか考えてみる。

ソースコードの準備

前回使用したサンプルとは別のものを使用する。

$ cd 
$ git clone https://github.com/mickey-happygolucky/helloworld.git
$ cd helloworld
$ rm -rf .git

.gitを削除することでgitリポジトリではなくしている。

devtool

ワークスペースへの追加

$ devtool add ~/helloworld

ワークスペースの内容を確認してみる。

./workspace/
├── README
├── appends
│   └── helloworld.bbappend
├── conf
│   └── layer.conf
├── recipes
│   └── helloworld
│       └── helloworld.bb
└── sources

リモートのプロジェクトを指定したときと異なり、ソースがワークスペース内のsourcesディレクトリに配置されていない。

これはrecipetool createにローカルのソースツリーを指定した場合ダウンロード処理が行われず、かつ、--extract-toオプションを指定できないため、ワークスペースのへのソースツリーのダウンロードが行われないためこのような動作になっている。

helloworld.bbappendを確認するとEXTERNAL_SRCにソースツリーのパスが直接指定されるようになっている。

inherit externalsrc
EXTERNALSRC = "/home/mickey/helloworld"

このため、devtool buildなどを行っても見かけ上はワークスペース内のsourcesディレクトリにあるときと同じような動作になる。

helloworld.bbを確認するとSRC_URIが空になっていることがわかる。

# Recipe created by recipetool
# This is the basis of a recipe and may need further editing in order to be fully functional.
# (Feel free to remove these comments when editing.)

# WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is
# your responsibility to verify that the values are complete and correct.
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=134b970c55f7388271efa7b17c06d072"

# No information for SRC_URI yet (only an external source tree was specified)
SRC_URI = ""

inherit cmake

# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
EXTRA_OECMAKE = ""

レシピのレイヤへの登録

devtool finishを実行してみる。

$ devtool finish helloworld ../poky/meta-work

下記のようなエラーになる。

NOTE: Starting bitbake server...
Traceback (most recent call last):
  File "/home/mickey/yocto/rpi-kirkstone/sources/poky/scripts/devtool", line 338, in <module>
    ret = main()
  File "/home/mickey/yocto/rpi-kirkstone/sources/poky/scripts/devtool", line 325, in main
    ret = args.func(args, config, basepath, workspace)
  File "/home/mickey/yocto/rpi-kirkstone/sources/poky/scripts/lib/devtool/standard.py", line 2060, in finish
    check_git_repo_op(srctree, [corebasedir])
  File "/home/mickey/yocto/rpi-kirkstone/sources/poky/scripts/lib/devtool/__init__.py", line 371, in check_git_repo_op
    stdout, _ = bb.process.run('git rev-parse --show-toplevel', cwd=srctree)
  File "/home/mickey/yocto/rpi-kirkstone/sources/poky/bitbake/lib/bb/process.py", line 189, in run
    raise ExecutionError(cmd, pipe.returncode, stdout, stderr)
bb.process.ExecutionError: Execution of 'git rev-parse --show-toplevel' failed with exit code 128:
fatal: not a git repository (or any of the parent directories): .git

devtool finishでは、レイヤにレシピを登録する際にワークスペース内で行った修正の差分からパッチを作成し、レシピに登録するという処理を行うため、ワークスペース登録中のレシピのソースツリーはgitリポジトリである必要がある。

前回説明した通り、devtool addでネットワーク越しのソースを指定した場合は対象がgitリポジトリじゃない場合は自動的にgitリポジトリに変換される。

ソースツリーをgitリポジトリにしてみる。

$ cd ~/helloworld
$ git init
$ git add .
$ git commit -m "Initial commit"

この状態で再度devtool finishを実行する。

$ devtool finish helloworld ../poky/meta-work

エラーの内容は変化するがfinishは失敗する。

NOTE: Starting bitbake server...
NOTE: Reconnecting to bitbake server...
NOTE: Retrying server connection (#1)...
Loading cache: 100% |##################################################################| Time: 0:00:00
Loaded 1679 entries from dependency cache.
Parsing recipes: 100% |################################################################| Time: 0:00:00
Parsing of 919 .bb files complete (917 cached, 2 parsed). 1680 targets, 67 skipped, 0 masked, 0 errors.
ERROR: Unable to find initial revision - please specify it with --initial-rev

devtoolは通常ワークスペースに登録された時点のコミットIDをinitial-revとして覚えておき、finishする際に差分を取るための基点としている。

devtool finishにはオプションでinitial-revが指定できるようになっているため実行時に指定する。

initiale-revに指定するためのコミットIDは下記のように取得する。

$ git rev-parse HEAD
1af1253de73276bc60689af176d69c99df26064a

initial-revを指定してdevtool finishを実行する。

$ devtool finish --initial-rev 1af1253de73276bc60689af176d69c99df26064a helloworld ../poky/meta-work

コマンドは成功する。

レイヤに登録されたレシピ

meta-workを確認する。

../poky/meta-work/
├── COPYING.MIT
├── README
├── conf
│   └── layer.conf
(... snip ...)
└── recipes-helloworld
    └── helloworld
        └── helloworld.bb

レイヤにはレシピは存在するが、ソースコードは存在していない。

helloworld.bbは下記のようにSRC_URIが設定されていない不完全な状態となっている。

# Recipe created by recipetool
# This is the basis of a recipe and may need further editing in order to be fully functional.
# (Feel free to remove these comments when editing.)

# WARNING: the following LICENSE and LIC_FILES_CHKSUM values are best guesses - it is
# your responsibility to verify that the values are complete and correct.
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=134b970c55f7388271efa7b17c06d072"

# No information for SRC_URI yet (only an external source tree was specified)
SRC_URI = ""

inherit cmake

# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
EXTRA_OECMAKE = ""

完全な状態にする

ソースツリーをmeta-workに配置し、SRC_URIを設定する。

$ mkdir ../poky/meta-work/recipes-helloworld/helloworld/files
$ cp -ra ~/helloworld ../poky/meta-work/recipes-helloworld/helloworld/files
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=134b970c55f7388271efa7b17c06d072"

# No information for SRC_URI yet (only an external source tree was specified)
SRC_URI = "file://helloworld"

S = "${WORKDIR}/${BPN}"

inherit cmake

# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
EXTRA_OECMAKE = ""

結局の所、肝心な部分は自動化できていない。

recipetoolでレシピを作成する

一旦devtoolで作成したレシピを削除する。

$ rm -rf ../poky/meta-work/recipes-helloworld

筆者がよくやる手順は下記のような感じになる。

  1. レイヤに格納先ディレクトリを作成する
  2. レイヤにソースコードを配置する
  3. recipetool createでレシピを作成する
  4. レシピの修正

具体的には下記のようになる。

$ mkdir -p ../poky/meta-work/recipes-app/helloworld/files
$ cp -ra ~/helloworld ../poky/meta-work/recipes-app/helloworld/files
$ recipetool create ../poky/meta-work/recipes-app/helloworld/files/helloworld -o ../poky/meta-work/recipes-app/helloworld/helloworld_0.1.bbt
$ recipetool edit helloworld

先ほどとレシピの内容は変わらず。

LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=134b970c55f7388271efa7b17c06d072"

# No information for SRC_URI yet (only an external source tree was specified)
SRC_URI = "file://helloworld"

S = "${WORKDIR}/${BPN}"

inherit cmake

# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
EXTRA_OECMAKE = ""

まとめ

ローカルストレージ上のソースからレシピを作成するためにdevtool addを使用してもあまり便利ではない。 recipetool createのほうがgitリポジトリ化の必要がない分結果的に手順が少なくなる。

ローカルにしろネットワーク越しにしろ、レシピの新規作成にはdevtool addを使用するメリットはあまり感じられなかった。