Fedora 24: Flatpakのインストール方法とビルド方法

Flatpakのインストール方法と作成方法について記載します。

xdg-appsからFlatpakに名前が変更されました。

 

1 Flatpak

Flatpakはアプリケーションが必要とするコマンドやライブラリをSandBox(専用のルートファイルシステム)に含めて提供するフレームワークです。

Flatpakを利用することで、ライブラリのバージョンや互換性の問題が解消されます。同じCPUアーキテクチャ向けのものならば、複数のLinuxディストリビューションで同じバイナリが動作します。

Flatpakはアプリケーションとランタイムの2種類があります。ランタイムはアプリケーションから読み込み専用で利用されるコマンドとライブラリです。

複数のアプリケーションでランタイムを共有できるので、SandBoxを提供するマシンの容量を無駄にしません。これは今までのLinux/Unixの共有ライブラリの概念に則っています。

2 flatpakパッケージのインストール

Flatpakのインストールとビルドを実行するツールです。flatpakとflatpak-libsをインストールします。

$ sudo dnf install -y flatpak flatpak-libs

3 アプリケーションとランタイムのインストール

ユーザ毎にアプリケーションとランタイムをインストールする手順について記載します。

GNOMEリポジトリのGPGキーをインポートします。

$ wget https://sdk.gnome.org/keys/gnome-sdk.gpg
$ flatpak --user remote-add --gpg-import=gnome-sdk.gpg gnome \
https://sdk.gnome.org/repo/

リモートのリポジトリをインポートします。

$ flatpak --user remote-add --gpg-import=gnome-sdk.gpg gnome-apps \
https://sdk.gnome.org/repo-apps/

ランタイムのorg.gnome.Platformをインストールします。2016年7月3日現在、org.gnome.Platformとorg.gnome.Sdkのインストールは不安定で、セグメンテーションフォルトが発生する場合があります。

Segmentation fault      (core dumped) flatpak --user install
gnome org.gnome.Platform 3.20

本問題はインストールを再実行することで回避できます。${HOME}/.local/share/flatpak/runtimeにインストールされます。

$ while : ; do
  flatpak --user install gnome org.gnome.Platform 3.20 &
  pid=$!
  sleep 300
  ps -p ${pid} | awk '{ print $1 }' | grep ${pid} > /dev/null || break
  sudo kill -KILL ${pid}
done

アプリケーションのorg.gnome.geditををインストールします。${HOME}/.local/share/flatpak/appにインストールされます。

$ flatpak --user install gnome-apps org.gnome.gedit stable

org.gnome.geditを起動します。

$ flatpak --user run org.gnome.gedit

geditが起動しました。

0001_gedit.png

3.1 アプリケーションとランタイムを全ユーザで共有する

flatpakを–userオプションなし、かつroot権限で実行することで、アプリケーションが/var/lib/flatpak/appに、ランタイムが/var/lib/flatpak/runtimeにインストールされます。これによりアプリケーションを複数ユーザで共有できます。

ランタイムのorg.gnome.Platformがセグメンテーションフォルトする問題を回避するために子プロセスをkillしてインストールを再実行させています。

$ sudo flatpak remote-add --gpg-import=gnome-sdk.gpg gnome \
     https://sdk.gnome.org/repo/
$ sudo flatpak remote-add --gpg-import=gnome-sdk.gpg gnome-apps \
     https://sdk.gnome.org/repo-apps/
$ while : ; do
  sudo flatpak install gnome org.gnome.Platform 3.20 &
  pid=$!
  sleep 300
  ps -p ${pid} | awk '{ print $1 }' | grep ${pid} > /dev/null || break
  sudo kill -KILL ${pid}
done
$ sudo flatpak install gnome-apps org.gnome.gedit stable
$ flatpak run org.gnome.gedit

3.2 リポジトリにあるFlatpakの一覧

remote-lsサブコマンドに登録したリポジトリ名を指定します。

$ flatpak remote-ls gnome-apps
org.gnome.Builder
org.gnome.Builder.Debug
org.gnome.Builder.Locale
org.gnome.Calculator
org.gnome.Calculator.Debug
org.gnome.Calculator.Locale
org.gnome.Calendar
org.gnome.Calendar.Debug
org.gnome.Calendar.Locale
org.gnome.Characters
org.gnome.Characters.Debug
org.gnome.Characters.Locale
org.gnome.Dictionary
org.gnome.Dictionary.Debug
org.gnome.Dictionary.Locale
org.gnome.Epiphany
org.gnome.Epiphany.Debug
org.gnome.Epiphany.Locale
org.gnome.Evince
org.gnome.Evince.Debug
org.gnome.Evince.Locale
org.gnome.Maps
org.gnome.Maps.Debug
org.gnome.Maps.Locale
org.gnome.Polari
org.gnome.Polari.Debug
org.gnome.Polari.Locale
org.gnome.Rhythmbox3
org.gnome.Rhythmbox3.Debug
org.gnome.Rhythmbox3.Locale
org.gnome.Todo
org.gnome.Todo.Debug
org.gnome.Todo.Locale
org.gnome.Weather
org.gnome.Weather.Debug
org.gnome.Weather.Locale
org.gnome.bijiben
org.gnome.bijiben.Debug
org.gnome.bijiben.Locale
org.gnome.clocks
org.gnome.clocks.Debug
org.gnome.clocks.Locale
org.gnome.eog
org.gnome.eog.Debug
org.gnome.eog.Locale
org.gnome.gedit
org.gnome.gedit.Debug
org.gnome.gedit.Locale
org.gnome.iagno
org.gnome.iagno.Debug
org.gnome.iagno.Locale

3.3 インストールされたFlatpakの一覧

listコマンドで表示されます。

$ flatpak list
org.gnome.gedit

4 アプリケーションを作成する

Flatpakの説明をする上でflatpak buildなしで作成する方法も紹介していますが、基本的にはflatpak buildの手順をお使い下さい。flatpak buildを使う手順は既存のビルド方法との親和性が高いです(単純にコマンドをflatpack buildでラップすれば良い)。

4.1 flatpak buildなしで作成する(非推奨)

SandBox上で/bin/shを実行するアプリケーションを作成します。ディレクトリを作成します。

$ mkdir shell
$ mkdir shell/files
$ mkdir shell/files/bin
$ mkdir shell/export

アプリケーションが提供するshell.shというファイルを作成します。

  • 与えられた引数を/bin/sh(bash)で実行します
  • 引数なしの場合は/bin/shへ処理を移します
$ cat <<EOF > shell/files/bin/shell.sh
#!/bin/sh

if [ \$# -eq 0 ]; then
  PS1="shell> " /bin/sh
else
  echo "shell> \$@"
  eval "\$@"
fi

EOF
$ chmod a+x shell/files/bin/shell.sh

アプリケーションの情報を記載したmetadataというファイルを作成します。

  • アプリケーション名をcom.example.shellとします。これは以降の説明で記載する${name}の値です。
  • org.gnome.Platformをランタイムとして利用します。
  • com.example.shellを実行した場合に実行されるコマンドをshell.shとします。
  • アプリケーションで利用できるファイルシステムをhostとします。
$ cat <<EOF > shell/metadata
[Application]
name=com.example.shell
runtime=org.gnome.Platform/x86_64/3.20
command=shell.sh

[Context]
filesystems=host;

EOF

shellディレクトリをrepoディレクトリへエクスポートします。

$ flatpak build-export repo shell
$ ls repo/
config  objects  refs  state  summary  tmp  uncompressed-objects-cache

repoディレクトリをexample-repoというリポジトリ名で登録します。example-repoからcom.example.shellをインストールします。

$ flatpak --user remote-add --no-gpg-verify example-repo repo
$ flatpak --user install example-repo com.example.shell

4.2 flatpak buildでビルドする(推奨)

flatpak buildを利用することで、SandBox上でアプリケーションをコンパイルすることができます。

アプリケーションをビルドする為にorg.gnome.Sdkをインストールします。

$ while : ; do
  flatpak --user install gnome org.gnome.Sdk 3.20 &
  pid=$!
  sleep 300
  ps -p ${pid} | awk '{ print $1 }' | grep ${pid} > /dev/null || break
  sudo kill -KILL ${pid}
done

今回はmakeのみで済む簡単なコードを使いますが、flatpak buildはconfigure、cmake等もサポートしています(ランタイムが提供)。

以下の手順でFlatpakでない通常のバイナリをビルドできます。

$ sudo dnf install -y ncurses-devel SDL2-devel SDL2_image-devel
$ git clone https://github.com/hiroom2/tetris-sdl-and-ncurses
$ cd tetris-sdl-and-ncurses
$ make
$ ./jni/src/ncurses # or ./jni/src/sdl

以下の手順でFlatpakを作成します。

  • flatpak build-initでflatpak buildを開始
  • flatpak build経由で実行したコマンドはSandBox上で実行
  • flatpak build-finishでflatpak buildを停止します。
$ flatpak build-init tetris com.hiroom2.tetris org.gnome.Sdk \
org.gnome.Platform 3.20
$ git clone https://github.com/hiroom2/tetris-sdl-and-ncurses
$ cd tetris-sdl-and-ncurses/
$ flatpak build ../tetris make all install DESTDIR=/app
$ cd ..
$ flatpak build-finish tetris --command=ncurses

なお、flatpak build実行中はorg.gnome.Sdkのコマンドとライブラリを利用し、flatpak run実行中はorg.gnome.Platformのコマンドとライブラリを利用します。

metadataは以下のとおりです。さらに手作業で内容を変更しても良いでしょう。

$ cat tetris/metadata
[Application]
name=com.hiroom2.tetris
runtime=org.gnome.Platform/x86_64/3.20
sdk=org.gnome.Sdk/x86_64/3.20
command=ncurses

先と同様にリポジトリを登録してアプリケーションをインストールします。

$ flatpak build-export repo tetris
$ flatpak --user remote-add --no-gpg-verify tetris-repo repo
$ flatpak --user install tetris-repo com.hiroom2.tetris

アプリケーションを実行します。

$ flatpak run com.hiroom2.tetris

ncursesコマンドが提供するテトリスが起動しました。

0002_tetris.png

4.3 作成したアプリケーションの更新

ソースツリーの中身を更新してからrepoディレクトリへエクスポートします。

$ # update shell or tetris-sdl-and-ncurses directory
$ flatpak build-export repo shell # or tetris-sdl-and-ncurses

クライアント側でアップデートを受け取ります。com.example.shellを省略した場合はインストールされている全てのパッケージをアップデートします。

$ flatpak --user update com.example.shell # or com.hiroom2.tetris

4.4 ランタイム

ランタイムはアプリケーションが利用するライブラリとコマンドを提供します。現状、アプリケーションはひとつのランタイムしか利用できません。 Gnomeとfreedesktop向けのランタイムKDE向けのランタイムも開発されています。

これはFlatpakの大きな特徴です。サーバ向けのデーモン用ランタイムや、組込み機器向けの小サイズなランタイム等が出てくると相当発展しそうです。

現在のランタイムのサイズは以下のとおりです。複数のアプリケーションで共有できるのでデスクトップ環境では問題にはなりません。

$ du -sh .local/share/flatpak/runtime/org.gnome.Platform
613M    .local/share/flatpak/runtime/org.gnome.Platform
$ du -sh .local/share/flatpak/runtime/org.freedesktop.Platform/
391M    .local/share/flatpak/runtime/org.freedesktop.Platform/

5 Flatpakの構成

こちらのSandBoxの説明に照らし合わせます。

5.1 /app

アプリケーションをインストールすると${HOME}/.local/share/flatpak/app/${name}/にファイルがインストールされます。システムにインストールした場合は/var/lib/flatpak/app/${name}です。

アプリケーション起動時に上記のディレクトリ内にあるfilesディレクトリが/appにmountされます。/appがPATHとLD_LIBRARY_PATHに追加されます。

shell> echo $PATH
/app/bin:/usr/bin
shell> echo $LD_LIBRARY_PATH
/app/lib:/usr/lib/GL

5.2 /usr

ランタイムをインストールすると${HOME}/.local/share/flatpak/runtim/${name}/にファイルがインストールされます。アプリケーション起動時に上記のディレクトリ内にあるfilesディレクトリが/usrにmountされます。

/usrはruntimeのディレクトリがmountされます。

$ ls .local/share/flatpak/runtime/org.gnome.Platform/x86_64/3.20/active/files/
bin    etc    include  lib64    local          sbin   src
cache  games  lib      libexec  manifest.json  share  var
$ flatpak run com.example.shell ls /usr
shell> ls /usr
bin    etc    include  lib64    local          sbin   src
cache  games  lib      libexec  manifest.json  share  var

/binは/usr/binへ、/libは/usr/libへ、/lib64は/usr/lib64へのシンボリックリンクです。

$ flatpak run com.example.shell ls -l /
shell> ls -l /
total 44
drwxrwxr-x   3 hiroom2   hiroom2    4096 Jul  2 06:22 app
lrwxrwxrwx   1 hiroom2   hiroom2       7 Jul  2 06:27 bin -> usr/bin
drwxr-xr-x   4 hiroom2   hiroom2     300 Jul  2 06:27 dev
drwxr-xr-x  20 hiroom2   hiroom2    1000 Jul  2 06:27 etc
drwxr-xr-x   3 nfsnobody nfsnobody  4096 Jun 22 04:59 home
lrwxrwxrwx   1 hiroom2   hiroom2       7 Jul  2 06:27 lib -> usr/lib
lrwxrwxrwx   1 hiroom2   hiroom2       9 Jul  2 06:27 lib64 -> usr/lib64
drwx------   2 nfsnobody nfsnobody 16384 Jun 15 01:25 lost+found
drwxr-xr-x   2 nfsnobody nfsnobody  4096 Feb  4 07:10 media
drwxr-xr-x   2 nfsnobody nfsnobody  4096 Feb  4 07:10 mnt
drwxr-xr-x   2 nfsnobody nfsnobody  4096 Feb  4 07:10 opt
dr-xr-xr-x 147 nfsnobody nfsnobody     0 Jul  2 06:27 proc
drwxr-xr-x   4 hiroom2   hiroom2     120 Jul  2 06:27 run
lrwxrwxrwx   1 hiroom2   hiroom2       8 Jul  2 06:27 sbin -> usr/sbin
drwxr-xr-x   2 nfsnobody nfsnobody  4096 Feb  4 07:10 srv
drwxr-xr-x   7 hiroom2   hiroom2     140 Jul  2 06:27 sys
drwxr-xr-x   3 hiroom2   hiroom2      60 Jul  2 06:27 tmp
drwxrwxr-x  13 hiroom2   hiroom2    4096 Jul  2 06:11 usr
drwxr-xr-x   5 hiroom2   hiroom2     140 Jul  2 06:27 var

5.3 /etc

/etcはホストマシンのファイルがmountされています。

shell> cat /proc/mounts | grep /etc/
 /etc/passwd tmpfs rw,seclabel,nosuid,nodev,relatime,uid=1000,gid=1000 0 0
 /etc/group tmpfs rw,seclabel,nosuid,nodev,relatime,uid=1000,gid=1000 0 0
/dev/mapper/fedora-root /etc/machine-id ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/mapper/fedora-root /etc/shells ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/mapper/fedora-root /etc/default ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/mapper/fedora-root /etc/issue ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/mapper/fedora-root /etc/timezone ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/mapper/fedora-root /etc/host.conf ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/mapper/fedora-root /etc/filesystems ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/mapper/fedora-root /etc/xdg ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
<snip>

ただし/etc/passwdと/etc/groupはアプリケーションを起動したユーザとnfsnobodyのみが記載されたものとなります。

shell> cat /etc/passwd
hiroom2:x:1000:1000:Unknown:/home/hiroom2:/bin/sh
nfsnobody:x:65534:65534:Unmapped user:/:/sbin/nologin
shell> cat /etc/group
hiroom2:x:1000:hiroom2
nfsnobody:x:65534:

5.4 /dev

デバイスファイルも必要最低限のものがmountされます。

shell> ls /dev
console  full  null  ptmx  pts  random  shm  stderr  stdin  stdout  tty  urandom  zero

5.5 /proc

ps aの実行結果は以下のとおりです。

shell> ps a
  PID TTY      STAT   TIME COMMAND
    1 ?        S+     0:00 /usr/libexec/flatpak-bwrap --args 13 shell.sh ps a
    2 ?        S+     0:00 /bin/sh /app/bin/shell.sh ps a
    3 ?        R+     0:00 ps a

flatpak-bwrapからコマンドが起動しています。

flatpak-bwrap -> /bin/sh -> shell.sh

以上を踏まえて、/procの内容は以下のとおりです。自分自身に関連するプロセスのみ見ることが出来ます。PID 70はlsのプロセスです。

shell> ls /proc/
1          cpuinfo      iomem        latency_stats  partitions     sysvipc
2          crypto       ioports      loadavg        sched_debug    thread-self
3          devices      irq          locks          schedstat      timer_list
70         diskstats    kallsyms     mdstat         scsi           timer_stats
acpi       dma          kcore        meminfo        self           tty
asound     driver       key-users    misc           slabinfo       uptime
buddyinfo  execdomains  keys         modules        softirqs       version
bus        fb           kmsg         mounts         stat           vmallocinfo
cgroups    filesystems  kpagecgroup  mtrr           swaps          vmstat
cmdline    fs           kpagecount   net            sys            zoneinfo
consoles   interrupts   kpageflags   pagetypeinfo   sysrq-trigger

5.6 /sys

ホストマシンの/sysを読み込みオンリーでmountされています。若干内容が異なるようです。

$ ls /sys/
block  bus  class  dev  devices  firmware  fs  hypervisor  kernel  module  power
$ flatpak run com.example.shell ls /sys
shell> ls /sys/
block  bus  class  dev  devices

5.7 /var

以下の書き込み領域が用意されています。

 

Host machine Shell
${HOME}/.var/app/${name}/cache /var/cache
${HOME}/.var/app/${name}/config /var/config
${HOME}/.var/app/${name}/data /var/data

 

5.8 Contextのfilesystems

/var/cache、/car/config、/var/data以外にもmetadataのfilesystemsでホストマシンの領域をSandBoxに見せることができます。ホームディレクトリ配下は書き込むことも可能です。

filesystemsで指定することができる領域は以下のとおりです。

 

host Host Mahine filesystem except dev, proc, /sys and /var
home User homedirectory
xdg-xxx XDG_XXX variable directory
Absolute path opt/path/to or ~.local/path/to

 

xdg変数とXDG変数のマッピングは以下のとおりです。

 

xdg variable XDG variable Fedora 24
xdg-desktop XDG_DESKTOP_DIR ${HOME}/Desktop
xdg-documents XDG_DOCUMENTS_DIR ${HOME}/Documents
xdg-download XDG_DOWNLOAD_DIR ${HOME}/Downloads
xdg-music XDG_MUSIC_DIR ${HOME}/Music
xdg-pictures XDG_PICTURES_DIR ${HOME}/Pictures
xdg-public-share XDG_PUBLICSHARE_DIR ${HOME}/Public
xdg-templates XDG_TEMPLATES_DIR ${HOME}/Templates
xdg-videos XDG_VIDEOS_DIR ${HOME}/Videos
xdg-run XDG_RUNTIME_DIR /var/user/<pid>

 

複数のfilesystemsを指定する場合は;で区切ります。以下はorg.gnome.geditが持つmetadataの例です。

filesystems=xdg-run/dconf;host;~/.config/dconf:ro;