BlinkGTK 組み込みガイド (リンクと実行時の要件)

対象: BlinkGTK を使って自分のアプリを作る方 (C / Python / Rust など)
最終更新: 2026-07-29

まずこれだけ

リンクは pkg-config を通してください。これだけで、以降の落とし穴はほぼ避けられます。

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

Makefile なら次のとおりです。

CFLAGS  += $(shell pkg-config --cflags blinkgtk-0.1)
LDLIBS  += $(shell pkg-config --libs blinkgtk-0.1)

うまく動かないときは、まずこの 3 つを確認してください。

症状 確認すること
ビルドできない pkg-config --cflags --libs blinkgtk-0.1 が値を返すか。devel パッケージは入っているか
起動するが画面が白い readelf -d ./myapp | grep allocator_shim が 1 行以上出るか (第 2 章)
Invalid file descriptor to ICU data で落ちる リソースの置き場所 (第 3 章)

以降は、なぜそうなるのかと、pkg-config を使えない場合の対処です。必要になったときに
読んでください。


1. BlinkGTK が普通の GTK ライブラリと違うところ

BlinkGTK は中に Chromium を丸ごと抱えています。そのため、リンクと実行時に
普通の GTK ライブラリにはない前提があります。

前提を外すと、ビルドも起動も成功したように見えて、ページだけが表示されません
(白画面または黒画面)。エラーも出ないので原因が分かりにくい、というのがこのガイドの
存在理由です。

同梱サンプル blinkgtk_browser は pkg-config 経由でリンクしているので、この前提を
満たしています。


2. リンクが「直接」でなければならない理由

2.1 何が起きているか

Chromium は独自のメモリ確保方式 (PartitionAlloc) を使います。これを効かせるには、
malloc などの標準関数を横取りする部品をプロセス開始時に読み込む必要があります。
この部品を allocator shim と呼びます。

shim の読み込みが遅れると、Chromium の内部でメモリ確保の辻褄が合わなくなり、
ページの読み込みが最後まで進みません

2.2 なぜ pkg-config が要るのか

-lblinkgtk だけを書くと、shim は libblinkgtk.so 経由で間接的に読み込まれます。
間接だとタイミングが遅すぎて、横取りが間に合いません。

shim は実行ファイルが直接依存している必要があります。blinkgtk-0.1.pcLibs
shim が含まれているので、pkg-config を通せば自動的にそうなります。

確認するにはこうします。

readelf -d ./myapp |

grep allocator_shim
# 1 行以上出れば OK。何も出なければ pkg-config を通っていない

2.3 未リンク時の症状

shim を直接リンクしないと、Chromium 148 以降ではレンダラの navigation commit が失敗 し、
起動直後に黒画面になります。ログには次のような兆候が現れます。

2.4 バージョン依存

Chromium 147 では shim が間接ロードでも成立していました。Chromium 148 で PartitionAlloc が
レンダラの commit 経路により深く統合され、早期インターポーズが必須になったと考えられます。
この要件は Chromium 151 でも継続します(151 のビルドで simple_browser が shim を直接 NEEDED に持つことを確認済み)。


3. リンク方法

3.0 パッケージ構成(runtime / devel / gir、v1.1.0 以降)

v1.1.0 以降、BlinkGTK は WebKitGTK と同等に runtime / devel / gir の 3 分割
配布されます(バイナリのみ、GitHub Releases)。consumer 開発では runtime に加えて
devel(+ 必要なら gir)を導入します。

パッケージ RPM DEB 内容 consumer での役割
runtime blinkgtk-bin libblinkgtk-0.1-0 共有ライブラリ (libblinkgtk-0.1.so.0) + Chromium ランタイム (private dir /usr/lib64/blinkgtk-0.1/) + リソース アプリの実行に必要
devel blinkgtk-bin-devel libblinkgtk-0.1-dev ヘッダ + blinkgtk-0.1.pc + .so symlink アプリのビルドに必要
gir blinkgtk-bin-gir (同 devel) GObject Introspection typelib Python / GJS 等からの利用時
# Fedora/RHEL (開発時は runtime + devel + gir)
sudo dnf install ./blinkgtk-bin-<VER>-1.fc44.x86_64.rpm \
                 ./blinkgtk-bin-devel-<VER>-1.fc44.x86_64.rpm \
                 ./blinkgtk-bin-gir-<VER>-1.fc44.x86_64.rpm

# Debian/Ubuntu
sudo apt install ./libblinkgtk-0.1-0_<VER>-1_amd64.deb \
                 ./libblinkgtk-0.1-dev_<VER>-1_amd64.deb

devel パッケージが blinkgtk-0.1.pc を提供するため、導入後は下記 3.1 の pkg-config が
そのまま解決します(.pcLibs: は FHS 配置後も shim 直接リンクを維持します。
Issue #90)。runtime のみ導入した環境ではアプリの実行はできますが、ビルド
(pkg-config / ヘッダ)はできません。

tarball (FHS) で導入する場合は runtime / devel の 2 つを同一 prefix に展開し、
runtime の ld.so.conf.d 断片または LD_LIBRARY_PATH で private dir を解決、
devel の .pcPKG_CONFIG_PATH に追加します。詳細は
インストールガイド を参照。

3.1 推奨: pkg-config を使う

正規 SDK の blinkgtk-0.1.pc は、アロケータ shim を Libs: に含んでいます。したがって
pkg-config 経由でリンクすれば、shim は自動的に実行ファイルの直接依存になります。

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

Python / Rust などの FFI バインディング経由で利用する場合も、ビルドメタデータが
pkg-config を参照していれば同様に shim が含まれます。

3.2 手動リンク(Makefile 等でハードコードする場合)

pkg-config を使わずリンク行をハードコードする場合は、-lblinkgtk の後に shim を明示的に
追加
してください。

BLINKGTK_LIBS = -L$(BLINKGTK_LIBDIR) \
                -lblinkgtk \
                -lbase_allocator_partition_allocator_src_partition_alloc_allocator_shim

shim ライブラリは BlinkGTK のライブラリディレクトリ(SDK の lib/chromium/ 等)に同梱
されています。

3.3 検証: NEEDED 差分の確認

リンク後、実行ファイルが shim を直接 NEEDED しているかを確認します。これは描画不具合の
第一手としても有効です。

readelf -d ./your_app | grep NEEDED |

grep allocator_shim
# → 1 行出れば直接 NEEDED 済み。出なければ未リンク(黒画面の原因)。

内部サンプルとの差分比較も有効です。

readelf -d ./your_app        | grep NEEDED | sort > /tmp/app.needed
readelf -d ./blinkgtk_browser  | grep NEEDED |

sort > /tmp/ref.needed
diff /tmp/ref.needed /tmp/app.needed

4. ライフサイクルと WebView の埋め込み

4.1 初期化・メインループ・終了

BlinkGTK のライフサイクルは次の順序です。

int main(int argc, char** argv) {
    if (!blink_gtk_init(&argc, &argv)) {   // 最初に呼ぶ(メインスレッドから)
        return 1;
    }
    // ... ウィンドウ / WebView の構築、load_uri ...
    int rc = blink_gtk_run_main_loop();    // メインループ開始
    blink_gtk_shutdown();                  // 終了処理(必須)
    return rc;
}

終了処理を必ず呼ぶこと。 blink_gtk_shutdown() を呼ばずにプロセスを終えると、Chromium の
teardown が AtExitManager 破棄後に走り、終了時に NOTREACHED で異常終了することがあります
(過去 issue で観測)。安全網として未終了検出時の自動終了処理も登録されますが、consumer は
明示的に blink_gtk_shutdown() を呼ぶことを推奨します。

4.2 WebView の生成と UI への埋め込み

WebView は blink_web_view_new() で生成します。返り値は GtkWidget* で、BLINK_WEB_VIEW()
BlinkWebView* にキャストできます。

GtkWidget* web_view = blink_web_view_new();          // 自己描画する WebView
blink_web_view_load_uri(BLINK_WEB_VIEW(web_view), "https://example.com");

// 自前のレイアウトに埋め込む(例: GtkOverlay)
GtkWidget* overlay = gtk_overlay_new();
gtk_overlay_set_child(GTK_OVERLAY(overlay), web_view);

blink_web_view_new_container() は非推奨(deprecated)です。 旧コンテナ生成 API は
Chromium 148 以降で描画されません(#90 関連)。blink_web_view_new()(自己描画)を使い、
コンテナが必要なら 自前の GtkOverlay / GtkBox に載せてください。

4.3 繰り返しの load_uri

同一 WebView に対して blink_web_view_load_uri() を繰り返し呼ぶことは安全です。内部の
レンダラビューは再利用され、ページ遷移を繰り返してもリソースが累積しません(過去のリーク
は解消済み)。アプリ側で WebView を毎回作り直す必要はありません。


5. 描画・表示の落とし穴

5.1 GPU モードの選択

描画バックエンドは 3 モードあります。

モード enum 用途 要件
software BLINK_GPU_MODE_SOFTWARE(0) 既定。CPU 描画。最も安定 GPU 不要
swiftshader BLINK_GPU_MODE_SWIFTSHADER(1) CPU ベース GL エミュレーション GPU 不要
egl BLINK_GPU_MODE_EGL(2) ネイティブ GPU 描画(WebGL/WebGPU) GPU / DRM 必須
GtkWidget* web_view = blink_web_view_new_with_gpu_mode(BLINK_GPU_MODE_SOFTWARE);

環境変数 BLINKGTK_GPU_MODE=software|swiftshader|egl でも指定できます。まず software で
動作確認すること
を推奨します。egl は実 GPU と DRM が必要で、ヘッドレスや GPU 無し環境では
描画されません。

5.2 HiDPI と device-scale-factor

高 DPI 環境(scale=2 等)では、device-scale-factor の不整合により「描画が左上に小さく
出る
」症状が起きることがあります。software モードでは GTK のスケールに追従して自動処理
されます。egl など experimental 経路でスケール不整合が出る場合は、Chromium のコマンドライン
引数 --force-device-scale-factor=<n>blink_gtk_init(&argc, &argv) に渡す argv に含めることで
スケールを明示できます。WebView を入れ子のコンテナに深く埋め込む場合は、スケール伝播に注意
してください。

5.3 日本語描画とフォント

日本語ページを正しく描画するには、システムに CJK フォント(Harano Aji、Noto CJK 等)が
インストールされている必要があります。フォントが無いと豆腐(□)になります。配布環境に
フォントが無い可能性がある場合は、依存に CJK フォントパッケージを含めてください。


6. アプリ機能連携

6.1 シグナル(ロード状態・タイトル ほか)

BlinkWebView は GObject シグナルでイベントを通知します。利用可能なシグナルは次の 7 つです。

各シグナルの正確な発火条件と落とし穴は Signals API リファレンス を参照してください。

あわせて、uri / title / is-loading / zoom-level の各プロパティは値の変化時に
notify:: シグナルを発火します(g_signal_connect(view, "notify::uri", ...) で購読可能)。

g_signal_connect(web_view, "load-changed", G_CALLBACK(on_load_changed), NULL);
g_signal_connect(web_view, "title-changed", G_CALLBACK(on_title_changed), NULL);

6.2 ユーザースクリプト / スタイルシートの注入

blink_web_view_inject_user_script(BLINK_WEB_VIEW(web_view), js_source,
                                  TRUE /* inject_at_document_start */);
blink_web_view_inject_user_stylesheet(BLINK_WEB_VIEW(web_view), css_source);

inject_at_document_start=TRUE のスクリプトは、ナビゲーションが commit された後
document_start タイミングで実行されます。2 章のアロケータ shim が未リンクで commit が成立
しないと、'Stored' ログは出ても注入スクリプトが実行されません(過去 issue)。注入が走らない
場合は、まず 2 章のリンク要件を確認してください。

6.3 バージョン取得(ハードコード禁止)

サブタイトル等に表示する BlinkGTK / Chromium バージョンは、ハードコードせずランタイム
API で取得してください。これにより libblinkgtk.so の更新に自動追従します。

const char* blinkgtk_ver = blink_gtk_get_version();           /* BlinkGTK バージョン */
const char* chromium_ver = blink_gtk_get_chromium_version();  /* Chromium バージョン */

これらの API は公開ヘッダ <blink_gtk/blink_gtk.h> に宣言されています(extern 宣言は
不要)。返り値は内部の静的文字列のため free しないでください。シンボルを export する
libblinkgtk.soとリンクする必要があります。

6.4 コンテンツ保護ポリシー

電子書籍端末・キオスク端末向けに、コピー / 保存 / 印刷等を制限できます。

blink_web_view_set_content_policy(BLINK_WEB_VIEW(web_view),
                                  BLINK_CONTENT_POLICY_EBOOK_READER);

プリセット: BLINK_CONTENT_POLICY_ALLOW_ALL(既定)、BLINK_CONTENT_POLICY_EBOOK_READER
BLINK_CONTENT_POLICY_KIOSK。個別フラグ(NO_COPY / NO_SAVE / NO_PRINT /
NO_CONTEXT_MENU / NO_DEVTOOLS 等)のビットマスク組み合わせも可能です。ポリシーは即時
適用され、いつでも変更できます。

6.5 Web Fullscreen API(requestFullscreen)

Web コンテンツの element.requestFullscreen() / document.exitFullscreen() を機能させるに
は、フルスクリーンハンドラを登録してトップレベルウィンドウの全画面化に反映します。登録
しない場合、フルスクリーン要素は WebView の表示領域内で拡大するだけで、ウィンドウ自体は全画面
化されません(電子書籍リーダーの全画面ボタンが「効かない」ように見える主因です)。

static void on_fullscreen(BlinkWebView* view, gboolean enter, gpointer user_data) {
  (void)user_data;
  GtkRoot* root = gtk_widget_get_root(GTK_WIDGET(view));
  if (!root ||

!GTK_IS_WINDOW(root)) return;
  if (enter)
    gtk_window_fullscreen(GTK_WINDOW(root));
  else
    gtk_window_unfullscreen(GTK_WINDOW(root));
}

/* WebView 生成後に一度だけ登録 */
blink_web_view_set_fullscreen_handler(BLINK_WEB_VIEW(web_view), on_fullscreen, NULL);

補足:


7. 起動と実行環境

7.1 共有ライブラリ探索パス(LD_LIBRARY_PATH / rpath)

libblinkgtk.so および Chromium の共有ライブラリ群が解決できるよう、rpath または
LD_LIBRARY_PATH を設定してください。pkg-config の Libs: には -rpath 指定が含まれて
います。

LD_LIBRARY_PATH を実行時に設定する必要がある構成では、Chromium ライブラリがロードされる
にパスを確定させる必要があります。プロセス先頭で LD_LIBRARY_PATH を設定し直して
自プロセスを re-exec するパターンが有効です(環境変数設定 → execv で自分自身を再起動
→ 以降は正しい探索パスでロード)。

7.1.1 リソースの置き場所を教える

Chromium は起動時に icudtl.datcontent_shell.pak などを読み込みます。
探しに行くのは 実行ファイルと同じディレクトリです。カレントディレクトリでは
ありません。

自分のアプリを別の場所に置くと、これらが見つからず起動に失敗します。

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("/usr/lib64/blinkgtk-0.1/chromium");
blink_gtk_set_icu_data_path("/usr/lib64/blinkgtk-0.1/chromium");

blink_gtk_init(&argc, &argv);

RPM / DEB でインストールした場合、リソースは
/usr/lib64/blinkgtk-0.1/chromium/ にあります。

同梱の blinkgtk_browser もこの方法を使っています。実際のコードは
examples/blinkgtk_browser.c を見てください。

7.2 サンドボックス・単一プロセス

開発時はサンドボックスを無効化する --no-sandboxargv に渡すと取り回しが容易です。
BlinkGTK は単一プロセス構成で動作します。

7.3 スレッド affinity

blink_gtk_init(&argc, &argv) を含む BlinkGTK / GTK の API は、原則としてメインスレッド(GTK メイン
ループのスレッド)から
呼び出してください。別スレッドからの UI 操作は避けてください。

7.4 Wayland 専用

BlinkGTK は Wayland のみをサポートします(X11 は使用しません)。起動時に Ozone プラット
フォームは Wayland に強制されます。


8. ランタイムデータファイル

8.1 V8 三点ファイルのバージョン整合

V8 関連の 3 ファイルは同一ビルド由来でバージョンが一致していなければなりません。混在
すると起動時に V8 の致命的エラーで起動不能になります。

異なる Chromium バージョンのビルドツリーからファイルを混ぜないでください。

8.2 ランタイムデータファイルの同梱

実行時に次のファイル群が必要です。consumer アプリの配布物に同梱してください。

8.3 データファイルの探索パスと実行ディレクトリ

Chromium のデータファイルは実行ファイルからの相対位置で解決されます。データファイルを
実行ファイルと異なるディレクトリに置いて起動すると、Invalid file descriptor to ICU data
等のエラーで起動に失敗することがあります。データファイルは実行ファイルと同じディレクトリ
(または規定の相対パス)に配置してください。


9. ナビゲーション / 描画不具合のトラブルシュート

描画されない(黒画面 / 白画面)場合、上位の複雑な仮説を立てる前に、以下を順に確認します。

確認項目 コマンド / 兆候 異常時の対処
allocator shim 直接リンク readelf -d <app> | grep allocator_shim 出なければ 3 章でリンク追加
NEEDED 差分 内部サンプルと diff 欠落ライブラリを補う
navigation commit ログの HasCommitted 0 のままなら shim を疑う
フレーム供給 ログの set_dmabuf_pixels 0 のままなら shim / commit を疑う
終了時クラッシュ 終了時 NOTREACHED blink_gtk_shutdown() を呼ぶ
注入スクリプト非実行 'Stored' は出るが走らない commit を確認(shim)
描画が小さい scale=2 で左上に縮小 device-scale-factor / software モード
V8 整合 libv8.so と snapshot の由来 同一ビルドに揃える
データファイル content_shell.pak / icudtl.dat の同梱 実行ファイル隣に配置

第一手は常に NEEDED 差分の確認です。ビルドと起動が成功しても描画されない場合、原因の
多くはリンク不足かデータファイル不足という「足元」にあります。


10. 付録: 最小チェックコマンド

# 1) shim 直接リンクの確認
readelf -d ./your_app | grep -c allocator_shim    # 1 を期待

# 2) 必須ランタイムファイルの存在確認
for f in libblinkgtk.so libv8.so content_shell.pak \
         snapshot_blob.bin v8_context_snapshot.bin \
         icudtl.dat locales/ja.pak locales/en-US.pak; do
  [ -e "$f" ] && echo "OK  $f" || echo "MISSING  $f"
done

# 3) 起動ログの健全性(描画されない場合)
grep -E "HasCommitted|set_dmabuf_pixels|error=6" your_app.log | tail

関連ドキュメント