BlinkGTK を使ったアプリのビルド

BlinkGTK を組み込んだアプリケーションをビルドするための最小限の手引きです。

前提: BlinkGTK 本体はソースからビルドしません

BlinkGTK は Chromium を組み込んでいるため、本体のビルドには Chromium の
ソースツリー (100 GB 超) と数時間から十数時間のビルド時間を要します。
利用者は配布されているパッケージを使ってください。 本ページは
「配布パッケージを使ってアプリをビルドする」手順を説明します。

配布形態は 3 つに分かれています。

パッケージ 用途
runtime 共有ライブラリと Chromium ランタイム。実行に必要
devel ヘッダと .pc。ビルドに必要
gir GObject Introspection typelib。Python / GJS から使う場合に必要

1. インストール

# Fedora
sudo dnf install ./blinkgtk-release-*.noarch.rpm ./blinkgtk-bin-1.2.5-build5.fc45.x86_64.rpm \
                 ./blinkgtk-bin-devel-1.2.5-build5.fc45.x86_64.rpm

# Debian / Ubuntu
sudo dpkg -i ./libblinkgtk-0.1-0_1.2.5-build5-1_amd64.deb \
             ./libblinkgtk-0.1-dev_1.2.5-build5-1_amd64.deb

tarball を使う場合は任意の場所に展開し、pkg-config に場所を教えます。

tar xzf blinkgtk-1.2.5-build5-linux-x86_64.tar.gz -C /opt/blinkgtk
export PKG_CONFIG_PATH=/opt/blinkgtk/usr/lib64/pkgconfig:$PKG_CONFIG_PATH

2. 必ず pkg-config 経由でリンクする

これが最も間違えやすく、最も分かりにくい失敗を招く点です。

cc -o myapp myapp.c $(pkg-config --cflags --libs blinkgtk-0.1)

-lblinkgtk だけを手で書いてリンクしないでください。BlinkGTK は Chromium の
PartitionAlloc allocator shim を必要とし、これは実行ファイルの直接依存
(DT_NEEDED) として早期にロードされなければなりません。blinkgtk-0.1.pc の
Libs にはこの shim が含まれています。

shim を落とすと、ビルドもリンクも通り、起動もするのに ページの読み込みが
完了しない
(ナビゲーションが commit しない = 白いまま) という、原因の分かり
にくい症状になります。

確認方法:

readelf -d ./myapp | grep allocator_shim
# 1 行以上出れば OK。何も出なければ pkg-config を経由していない
#include <blink_gtk/blink_gtk.h>
#include <gtk/gtk.h>

公開 API はこのヘッダに集約されています。内部ヘッダを直接インクルードしないで
ください (バージョン間で変わります)。

4. 最小構成のアプリ

BlinkGTK アプリケーションのライフサイクル。リソースの場所指定、blink_gtk_init、ウィンドウと WebView の作成、読み込みとメインループ、終了処理の 5 段。

呼び出しの順序が重要です。特に blink_gtk_init() は GTK より先に呼びます。

次のコードを myapp.c という名前で保存します。

#include <blink_gtk/blink_gtk.h>
#include <gtk/gtk.h>

static void on_activate(GtkApplication *app, gpointer user_data) {
    GtkWidget *win = gtk_application_window_new(app);
    gtk_window_set_default_size(GTK_WINDOW(win), 1024, 768);

    GtkWidget *view = blink_web_view_new();
    gtk_window_set_child(GTK_WINDOW(win), view);
    gtk_widget_set_visible(win, TRUE);

    blink_web_view_load_uri(BLINK_WEB_VIEW(view), "https://example.com/");
}

int main(int argc, char **argv) {
    blink_gtk_init(&argc, &argv);
    GtkApplication *app = gtk_application_new("com.example.MyApp",
                                              G_APPLICATION_DEFAULT_FLAGS);
    g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL);
    /* BlinkGTK は Chromium のブラウザメインループを回す必要がある。
     * g_application_run() ではそれが回らず、ページが読み込まれない
     * (navigation が commit しない)。blink_gtk_application_run() が
     * 正しい順序 (register → activate → BlinkGTK のループ) を代行し、
     * 最後のウィンドウが閉じると、この関数から戻る。
     */
    int status = blink_gtk_application_run(app);   /* 1.2.0-build9 以降 */
    g_object_unref(app);

    blink_gtk_shutdown();
    return status;
}

終わり方: メインループ (blink_gtk_application_run() や blink_gtk_run_main_loop()) が戻ったら、
必ず blink_gtk_shutdown() を呼んでから main() を終えてください。呼ばずに終えると、片づけは
プロセスの終了の間際 (atexit) に回ります。Windows ではその時点では正しく片づけられず、
終わるまでに時間がかかったうえ、異常終了することがあります。Linux でも同じ書き方にしてください。

注意: blink_web_view_new() は GtkWidget * を返しますが、BlinkGTK の
API は BlinkWebView * を取ります。BLINK_WEB_VIEW() でキャストしてください。

5. Makefile の例

myapp.c と同じ場所に Makefile という名前で保存します。最後の行の先頭は空白ではなくタブです。

CC      ?= cc
PKGS     = blinkgtk-0.1
CFLAGS  += -O2 -Wall $(shell pkg-config --cflags $(PKGS))
LDLIBS  += $(shell pkg-config --libs $(PKGS))

myapp: myapp.c
	$(CC) $(CFLAGS) -o $@ $< $(LDLIBS)

ビルドして起動します。

make
./myapp

6. 実行時に必要なもの

Wayland が必要です

BlinkGTK は Wayland 専用です。X11 では動作しません。Wayland セッションで
実行するか、ヘッドレス検証には Weston の headless バックエンドを使ってください。

weston --backend=headless-backend.so --width=1024 --height=768 &
export WAYLAND_DISPLAY=wayland-1

Chromium のリソースファイルの位置

Chromium は ICU データ (icudtl.dat)、V8 スナップショット
(snapshot_blob.bin / v8_context_snapshot.bin)、リソースパック
(content_shell.pak) を必要とします。カレントディレクトリは見ず、次の順に探します。

  1. blink_gtk_set_resources_path() で指定した場所 (指定した場合はここだけを見ます)
  2. 実行ファイルのあるディレクトリ
  3. そこに icudtl.dat が無ければ、libblinkgtk が置かれた場所 (<libdir>) を基準に
    <libdir>/blinkgtk-0.1/chromium/、<libdir>/chromium/、<libdir>/ の順 (1.2.3 以降)

RPM / DEB でインストールした場合や、tarball を / に展開した場合は 3 で見つかるため、
通常は何もする必要はありません。リソースをこれらと違う場所に置くと、起動時に
次のエラーになります。

ERROR:base/i18n/icu_util.cc: Invalid file descriptor to ICU data received.
FATAL:base/i18n/icu_util.cc: Check failed: result.

このときは、blink_gtk_init() より前に blink_gtk_set_resources_path() で
リソースのディレクトリを指定してください。

blink_gtk_set_resources_path("/opt/myapp/lib/chromium/");  /* blink_gtk_init() より前 */

ライブラリも別の場所 (例 /opt/blinkgtk) に展開した場合は、実行時のライブラリの
探索パスも合わせます。

export LD_LIBRARY_PATH=/opt/blinkgtk/usr/lib64/blinkgtk-0.1:\
/opt/blinkgtk/usr/lib64/blinkgtk-0.1/chromium

7. うまくいかないときの確認順序

症状 最初に確認すること
リンクエラー (undefined reference) pkg-config --libs blinkgtk-0.1 が値を返すか。devel パッケージが入っているか
起動するがページが白いまま readelf -d ./myapp | grep allocator_shim — shim が直接依存にあるか (第 2 節)
Invalid file descriptor to ICU data 実行ファイルとリソースの位置関係 (第 6 節)
ウィンドウが出ない Wayland セッションか。echo $WAYLAND_DISPLAY
Python から import できない gir パッケージが入っているか

8. GTK4 の使い方について

BlinkGTK は GTK4 のウィジェットを 1 つ提供するライブラリです。ウィンドウ、
レイアウト、ボタン、メニュー、イベント処理といった GTK4 そのものの使い方は、
GTK4 の公式ドキュメントを参照してください。本ドキュメントでは扱いません。

BlinkWebView は GtkWidget を継承しているため、他の GTK4 ウィジェットと
同じように扱えます (コンテナに入れる、サイズ要求を設定する、シグナルを繋ぐ等)。

ただしメインループだけは例外です。 GTK の g_application_run() や
g_main_loop_run() ではなく、blink_gtk_run_main_loop() を使ってください
(第 4 節)。

Python / Rust など他言語から使う場合

BlinkGTK は GObject Introspection に対応しているため、PyGObject や gtk-rs
から利用できます。各言語バインディングの使い方はそれぞれのドキュメントを
参照してください。

関連