flatpak を使って python application をパッケージングしてみる試み、その2
前回 は httpie をパッケージングしてみたので、今度は自作のアプリケーションをパッケージングしてみようとしたわけだが。
コケる
このようなビルドスクリプトを用意して:
#!/bin/bash set -e REPOSITORY="${HOME}/repos/flatpak/u7fa9.org" PACKAGE="konnyaku" URL="git+https://github.com/nakamuray/konnyaku.git" VERSION="master" BUILD_FINISH_ARGS=( --share=network --command=konnyaku ) _APP="org.u7fa9.${PACKAGE}" _RUNTIME="org.freedesktop.BasePlatform" _SDK="org.freedesktop.BaseSdk" _RUNTIME_VERSION="1.4" build_location="$(mktemp -d "${_APP}".XXXXXXX)" flatpak build-init "${build_location}" "${_APP}" "${_SDK}" "${_RUNTIME}" "${_RUNTIME_VERSION}" flatpak build "${build_location}" python3 -m venv /app flatpak build --share=network "${build_location}" /app/bin/pip install -U pip flatpak build --share=network "${build_location}" /app/bin/pip install "${URL}" flatpak build-finish "${BUILD_FINISH_ARGS[@]}" "${build_location}" flatpak build-export "${REPOSITORY}" "${build_location}" "${VERSION}"
実行:
$ bash ./build-konnyaku.bash
Collecting pip
... snip ...
Collecting git+https://github.com/nakamuray/konnyaku.git
Cloning https://github.com/nakamuray/konnyaku.git to /tmp/pip-arprb4sp-build
/usr/lib/python3.4/distutils/dist.py:244: UserWarning: 'licence' distribution option is deprecated; use 'license'
warnings.warn(msg)
... snip ...
Collecting lxml (from konnyaku==0.0.1)
Using cached lxml-3.7.2.tar.gz
Building lxml version 3.7.2.
Building without Cython.
ERROR: b'ERROR: /usr/bin/xslt-config should not be used, use an alternative such as pkg-config\n'
** make sure the development packages of libxml2 and libxslt are installed **
Using build configuration of libxslt --should-not-have-used-/usr/bin/xslt-config
Traceback (most recent call last):
... snip ...
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-zzfiqm16/lxml
コケた。
どうも xslt-config
が意図した値を返してないっぽい。
対応方針
さて、 flatpak の流儀としては、こういう時の正しい対応は「 /app
以下に libxslt
をビルド・インストールする」となる (多分)。
が、自分で依存ライブラリを一つずつビルド・インストールしていくとか面倒くさいので、今回は「 alpine ベースでこのアプリケーション専用の runtime/sdk を作成し、使用する」という対応をしてみる。
runtime/sdk の作成
こんな感じのスクリプトを用意して:
#!/bin/bash set -e IMAGE_URL="https://nl.alpinelinux.org/alpine/v3.5/releases/x86_64/alpine-minirootfs-3.5.1-x86_64.tar.gz" REPOSITORY_PATH="${HOME}/repos/flatpak/u7fa9.org" APP_NAME="org.u7fa9.konnyaku" RUNTIME_VERSION="3.5-1" RUNTIME_NAME="${APP_NAME}.Runtime" SDK_NAME="${APP_NAME}.Sdk" RUNTIME_PACKAGES=( python3 libxml2 libxslt ca-certificate ) SDK_PACKAGES=( git gcc musl-dev linux-headers python3-dev libxml2-dev libxslt-dev ) image_filename="${IMAGE_URL##*/}" if [[ ! -e "${image_filename}" ]]; then wget "${IMAGE_URL}" fi runtime_dir=$(mktemp -d "${RUNTIME_NAME}-${RUNTIME_VERSION}".XXXXXXXXXX) sdk_dir=$(mktemp -d "${SDK_NAME}-${RUNTIME_VERSION}".XXXXXXXXXX) rootfs_dir="${runtime_dir}"/rootfs mkdir -p "${rootfs_dir}" tar xpf "${image_filename}" -C "${rootfs_dir}" --exclude="./dev/*" run_in_rootfs() { /usr/libexec/flatpak-bwrap \ --unshare-ipc \ --unshare-pid \ --unshare-uts \ --setenv PATH "/bin:/usr/bin:/sbin:/usr/sbin" \ --bind "${rootfs_dir}" / \ --bind /etc/resolv.conf /etc/resolv.conf \ --proc /proc --dev /dev --tmpfs /tmp \ "$@" } run_in_rootfs apk update run_in_rootfs apk add "${RUNTIME_PACKAGES[@]}" || true # create sdk based on runtime cp -a "${rootfs_dir}" "${sdk_dir}"/ # as flatpak link (mount) runtime's files as a "/usr", copy all important files to /usr and use it as a "files" pushd "${rootfs_dir}" cp -a ./etc ./usr/ cp -a ./bin/* ./usr/bin cp -a ./sbin/* ./usr/sbin # to overwrite symlinks which look back to /lib it self, remove it before yes | cp -a --remove-destination ./lib/* ./usr/lib popd cat > "${runtime_dir}"/metadata <<EOF [Runtime] name=${RUNTIME_NAME} runtime=${RUNTIME_NAME}/x86_64/${RUNTIME_VERSION} sdk=${SDK_NAME}/x86_64/${RUNTIME_VERSION} EOF flatpak build-export --runtime --files=rootfs/usr "${REPOSITORY_PATH}" "${runtime_dir}" "${RUNTIME_VERSION}" # setup sdk, same as runtime rootfs_dir="${sdk_dir}"/rootfs run_in_rootfs apk add "${SDK_PACKAGES[@]}" || true pushd "${rootfs_dir}" cp -a ./etc ./usr/ cp -a ./bin/* ./usr/bin cp -a ./sbin/* ./usr/sbin # to overwrite symlinks which look back to /lib it self, remove it before yes | cp -a --remove-destination ./lib/* ./usr/lib popd cat > "${sdk_dir}"/metadata <<EOF [Runtime] name=${SDK_NAME} runtime=${SDK_NAME}/x86_64/${RUNTIME_VERSION} EOF flatpak build-export --runtime --files=rootfs/usr "${REPOSITORY_PATH}" "${sdk_dir}" "${RUNTIME_VERSION}"
実行。(一般ユーザーで apk
を実行すると色々動かないので、 sudo
で。) (コンソール出力記録し忘れた。)
改めてアプリケーションのパッケージング
runtime/sdk を先程作成したものに切り替えて
diff -r d1d5803c4e99 flatpak/build-konnyaku.bash
--- a/flatpak/build-konnyaku.bash Thu Feb 09 21:22:13 2017 +0900
+++ b/flatpak/build-konnyaku.bash Thu Feb 09 21:22:20 2017 +0900
@@ -12,9 +12,9 @@
)
_APP="org.u7fa9.${PACKAGE}"
-_RUNTIME="org.freedesktop.BasePlatform"
-_SDK="org.freedesktop.BaseSdk"
-_RUNTIME_VERSION="1.4"
+_RUNTIME="${_APP}.Runtime"
+_SDK="${_APP}.Sdk"
+_RUNTIME_VERSION="3.5-1"
build_location="$(mktemp -d "${_APP}".XXXXXXX)"
再度パッケージング実行。
$ flatpak --user install u7fa9 org.u7fa9.konnyaku.Sdk
Installing: org.u7fa9.konnyaku.Sdk/x86_64/3.5-1 from u7fa9
Scanning metadata: 290
$ bash build-konnyaku.bash
Collecting pip
Using cached pip-9.0.1-py2.py3-none-any.whl
Installing collected packages: pip
Found existing installation: pip 8.1.1
Uninstalling pip-8.1.1:
Successfully uninstalled pip-8.1.1
Successfully installed pip-9.0.1
Collecting git+https://github.com/nakamuray/konnyaku.git
Cloning https://github.com/nakamuray/konnyaku.git to /tmp/pip-orfzyndp-build
Collecting aiohttp (from konnyaku==0.0.1)
Using cached aiohttp-1.3.0.tar.gz
Collecting click (from konnyaku==0.0.1)
Using cached click-6.7-py2.py3-none-any.whl
Collecting cssselect (from konnyaku==0.0.1)
Using cached cssselect-1.0.1-py2.py3-none-any.whl
Collecting lxml (from konnyaku==0.0.1)
Using cached lxml-3.7.2.tar.gz
Collecting pyxdg (from konnyaku==0.0.1)
Collecting sqlalchemy (from konnyaku==0.0.1)
Collecting chardet (from aiohttp->konnyaku==0.0.1)
Collecting multidict>=2.1.4 (from aiohttp->konnyaku==0.0.1)
Using cached multidict-2.1.4.tar.gz
Collecting async_timeout>=1.1.0 (from aiohttp->konnyaku==0.0.1)
Using cached async_timeout-1.1.0-py3-none-any.whl
Collecting yarl>=0.8.1 (from aiohttp->konnyaku==0.0.1)
Downloading yarl-0.9.2.tar.gz (125kB)
100% |████████████████████████████████| 133kB 1.0MB/s
Installing collected packages: chardet, multidict, async-timeout, yarl, aiohttp, click, cssselect, lxml, pyxdg, sqlalchemy, konnyaku
Running setup.py install for multidict ... done
Running setup.py install for yarl ... done
Running setup.py install for aiohttp ... done
Running setup.py install for lxml ... done
Running setup.py install for konnyaku ... done
Successfully installed aiohttp-1.3.0 async-timeout-1.1.0 chardet-2.3.0 click-6.7 cssselect-1.0.1 konnyaku-0.0.1 lxml-3.7.2 multidict-2.1.4 pyxdg-0.25 sqlalchemy-1.1.5 yarl-0.9.2
Please review the exported files and the metadata
Commit: 82aac3014529a0400b080f7092fff457fb7900c13bc57fa09d76b7ef72778eb7
Metadata Total: 349
Metadata Written: 173
Content Total: 1420
Content Written: 1156
Content Bytes Written: 27112616 (27.1 MB)
今度はうまくいった。
インストールして実行
$ flatpak --user install u7fa9 org.u7fa9.konnyaku
Required runtime for org.u7fa9.konnyaku/x86_64/master (org.u7fa9.konnyaku.Runtime/x86_64/3.5-1) is not installed, searching...
Found in remote u7fa9, do you want to install it? [y/n]: y
Installing: org.u7fa9.konnyaku.Runtime/x86_64/3.5-1 from u7fa9
252 metadata, 3929 content objects fetched; 18779 KiB transferred in 24 seconds
Installing: org.u7fa9.konnyaku/x86_64/master from u7fa9
175 metadata, 1145 content objects fetched; 8243 KiB transferred in 7 seconds
$ flatpak run org.u7fa9.konnyaku
Usage: konnyaku [OPTIONS] COMMAND [ARGS]...
Options:
--debug / --no-debug
--help Show this message and exit.
Commands:
add add site
check check site updates
links list links
list list sites
modify modify site
oneshot add & check but not save
remove remove site
show show site information
今後の方針について
今後の application/runtime/sdk を更新していく方針についても考える。
OS パッケージ側 (alpine 側) に更新があったら、 runtime/sdk のみを作成し直す
アプリケーション側を更新したら、 application 側のみを作成し直す
アプリケーション側を更新し、新たに OS 側に依存パッケージが増えたら、 runtime/sdk を作り直してバージョンを上げ、 application はその新しいバージョンを使用するように作り直す
という感じかなぁ。