はじめに
recipetoolでバイナリパッケージを作ってみる。
ちなみに今回は作ることが目的のため、作ったものの動作確認はしていない。
reciptool
オプションの確認
$ recipetool create --help NOTE: Starting bitbake server... usage: recipetool create [-h] [-o OUTFILE] [-p PROVIDES] [-m] [-x EXTRACTPATH] [-N NAME] [-V VERSION] [-b] [--also-native] [--src-subdir SUBDIR] [-a | -S SRCREV] [-B SRCBRANCH] [--keep-temp] [--npm-dev] [--mirrors] source Creates a new recipe from a source tree arguments: source Path or URL to source options: -h, --help show this help message and exit -o OUTFILE, --outfile OUTFILE Specify filename for recipe to create -p PROVIDES, --provides PROVIDES Specify an alias for the item provided by the recipe -m, --machine Make recipe machine-specific as opposed to architecture-specific -x EXTRACTPATH, --extract-to EXTRACTPATH Assuming source is a URL, fetch it and extract it to the directory specified as EXTRACTPATH -N NAME, --name NAME Name to use within recipe (PN) -V VERSION, --version VERSION Version to use within recipe (PV) -b, --binary Treat the source tree as something that should be installed verbatim (no compilation, same directory structure) --also-native Also add native variant (i.e. support building recipe for the build host as well as the target machine) --src-subdir SUBDIR Specify subdirectory within source tree to use -a, --autorev When fetching from a git repository, set SRCREV in the recipe to a floating revision instead of fixed -S SRCREV, --srcrev SRCREV Source revision to fetch if fetching from an SCM such as git (default latest) -B SRCBRANCH, --srcbranch SRCBRANCH Branch in source repository if fetching from an SCM such as git (default master) --keep-temp Keep temporary directory (for debugging) --npm-dev For npm, also fetch devDependencies --mirrors Enable PREMIRRORS and MIRRORS for source tree fetching (disabled by default).
バイナリオプション-b
がある。
これを指定してレシピを作成すると、自動的にbin_package
クラスを継承してくれる。
レシピの作成
今回は例としてラズベリーパイ4向けのtensorflowを作成する。
$ recipetool create -b https://github.com/Qengineering/Tensorflow-Raspberry-Pi/raw/master/libtensorflow_2_1_0.tar.gz
レイヤの作成
ビルドするために適当なレイヤを作成し、レシピを移動する。
$ bitbake-layers create-layer meta-local $ bitbake-layers add-layer meta-local $ mkdir ./meta-local/recipes-example/libtensorflow $ mv ./libtensorflow-2-1_0.bb ./meta-local/recipes-example/libtensorflow
ビルド
とりあえずビルドしてみる。
$ bitbake libtensorflow-2-1 NOTE: Tasks Summary: Attempted 551 tasks of which 158 didn't need to be rerun and all succeeded.
問題なくビルドできた。
tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/libtensorflow-2-1/0-r0/packages-split/libtensorflow-2-1
でパッケージ内のツリー構成がどうなっているか確認する。
. ├── LICENSE ├── THIRD_PARTY_TF_C_LICENSES ├── include │ └── tensorflow │ └── c │ ├── c_api.h │ ├── c_api_experimental.h │ ├── eager │ │ └── c_api.h │ ├── tf_attrtype.h │ ├── tf_datatype.h │ ├── tf_file_statistics.h │ ├── tf_status.h │ └── tf_tensor.h └── lib ├── libtensorflow.so.2 -> libtensorflow.so.2.1.0 ├── libtensorflow.so.2.1.0 ├── libtensorflow_framework.so.2 -> libtensorflow_framework.so.2.1.0 └── libtensorflow_framework.so.2.1.0
tarの内容を/
に展開しているようだ。
bin_package.bbclass
bin_package.bbclass
の実装を確認してみると下記のようになっている。
do_configure[noexec] = "1" do_compile[noexec] = "1" # Install the files to ${D} bin_package_do_install () { # Do it carefully [ -d "${S}" ] || exit 1 if [ -z "$(ls -A ${S})" ]; then bbfatal bin_package has nothing to install. Be sure the SRC_URI unpacks into S. fi cd ${S} tar --no-same-owner --exclude='./patches' --exclude='./.pc' -cpf - . \ | tar --no-same-owner -xpf - -C ${D} } FILES_${PN} = "/" EXPORT_FUNCTIONS do_install
FILES_${PN} = "/"
となっている。?=
などではなく=
で設定されているため、レシピやlocal.conf
では設定を上書きできない。
bin_package.bbclassを継承しているの場合、どこにインストールされるかは元のtar
の構成に依存するということになりそうだ。
インストールディレクトリを変更したい
先述の通り、bin_package
クラスを継承する場合は、パッケージのディレクトリツリーを単純には変更できない。
今回のように。/include
や/lib
のように、本来は使用するべきではないディレクトリにインストールされてしまうのは避けたい。
そのような場合は次のようにする。
do_install() { install -d ${D}/opt cp -ra "${S}/" "${D}/opt/" chown -R root:root "${D}/opt/" } FILES_${PN}_remove = "/" FILES_${PN}-dev = "/opt/libtensorflow-2-1-0/lib/*.so \ /opt/libtensorflow-2-1-0/lib/*.so.2 \ " FILES_${PN} = "/opt/libtensorflow-2-1-0/"
do_install
を上書きして、インストール先を変更する。この時ファイルの所有権をroot:root
に変更することを忘れると下記のエラーに苦しむ。
ERROR: libtensorflow-2-1-0-r0 do_package: Error executing a python function in exec_python_func() autogenerated: The stack trace of python calls that resulted in this exception/failure was: File: 'exec_python_func() autogenerated', lineno: 2, function: <module> 0001: *** 0002:sstate_report_unihash(d) 0003: File: '/home/mickey/work/yocto/rpi-dunfell/layers/poky/meta/classes/sstate.bbclass', lineno: 840, function: sstate_report_unihash 0836: report_unihash = getattr(bb.parse.siggen, 'report_unihash', None) 0837: 0838: if report_unihash: 0839: ss = sstate_state_fromvars(d) *** 0840: report_unihash(os.getcwd(), ss['task'], d) 0841:} 0842: 0843:# 0844:# Shell function to decompress and prepare a package for installation File: '/home/mickey/work/yocto/rpi-dunfell/layers/poky/bitbake/lib/bb/siggen.py', lineno: 555, function: report_unihash 0551: 0552: if "." in self.method: 0553: (module, method) = self.method.rsplit('.', 1) 0554: locs['method'] = getattr(importlib.import_module(module), method) *** 0555: outhash = bb.utils.better_eval('method(path, sigfile, task, d)', locs) 0556: else: 0557: outhash = bb.utils.better_eval(self.method + '(path, sigfile, task, d)', locs) 0558: 0559: try: File: '/home/mickey/work/yocto/rpi-dunfell/layers/poky/bitbake/lib/bb/utils.py', lineno: 420, function: better_eval 0416: if extraglobals: 0417: ctx = copy.copy(ctx) 0418: for g in extraglobals: 0419: ctx[g] = extraglobals[g] *** 0420: return eval(source, ctx, locals) 0421: 0422:@contextmanager 0423:def fileslocked(files): 0424: """Context manager for locking and unlocking file locks.""" File: '<string>', lineno: 1, function: <module> File "<string>", line 1, in <module> File: '/home/mickey/work/yocto/rpi-dunfell/layers/poky/meta/lib/oe/sstatesig.py', lineno: 585, function: OEOuthashBasic 0581: 0582: update_hash("\n") 0583: 0584: # Process this directory and all its child files *** 0585: process(root) 0586: for f in files: 0587: if f == 'fixmepath': 0588: continue 0589: process(os.path.join(root, f)) File: '/home/mickey/work/yocto/rpi-dunfell/layers/poky/meta/lib/oe/sstatesig.py', lineno: 548, function: process 0544: add_perm(stat.S_IXOTH, 'x') 0545: 0546: if include_owners: 0547: try: *** 0548: update_hash(" %10s" % pwd.getpwuid(s.st_uid).pw_name) 0549: update_hash(" %10s" % grp.getgrgid(s.st_gid).gr_name) 0550: except KeyError: 0551: bb.warn("KeyError in %s" % path) 0552: raise Exception: KeyError: 'getpwuid(): uid not found: 1000' ERROR: Logfile of failure stored in: /home/mickey/work/yocto/rpi-dunfell/build/tmp/work/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi/libtensorflow-2-1/0-r0/temp/log.do_package.8254 ERROR: Task (/home/mickey/work/yocto/rpi-dunfell/build/meta-local/recipes-example/libtensorflow/libtensorflow-2-1_0.bb:do_package) failed with exit code '1'
これはhashを生成する際にファイルの所有権をキーにするらしいのだが、この時bitbakeはfakerootで動いており、この動作環境内に一般ユーザーが存在しないためException: KeyError: 'getpwuid(): uid not found: 1000'
が発生するということらしい。
まとめ
- バイナリパッケージを作成するには
bin_package
クラスを継承する。 - 作成されるパッケージのツリー構成は
/
からに固定されている。 - 自分の好きなようにファイルを配置するには少し手間がかかるが不可能ではない。
- do_install時に所有権の変更を忘れずに。