Open8

WPE WebKit を WPEBackend-direct でビルドしたい会

okuokuokuoku

前WPEをビルドしたときは気付かなかったけど、いつのまにか WPEBackend-direct というものができていた。

https://github.com/Igalia/WPEBackend-direct

こっちだと素のX11でも動くようなので、ビルドを試してみる。これをyuniframeのEGLエミュレータ上に移植してyuniframeのOpenGLES1やEGLの完成度を上げられるんじゃないかということで。

okuokuokuoku

チェックアウトと依存関係のインストール

とりあえずWebKitもビルドする。そうしないとデバッグが辛そうなので。。

$ git clone https://github.com/WebKit/WebKit

依存関係のインストールはスクリプトがある。自動的に sudo される。

$ ./Tools/wpe/install-dependencies

とりあえず最新のタグをチェックアウトしておく。 ...手元ではheadが問題なくビルドできた試しがない。。

$ git checkout -b wpe wpewebkit-2.42.1
okuokuokuoku

Configure (WebKit)

WebKitは普通のCMakeプロジェクトなので普通にconfigureできる。

$ cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/opt/wpe-testing \
 -DPORT=WPE -DENABLE_DOCUMENTATION=OFF -DENABLE_DEVELOPER_MODE=ON \
 -DENABLE_API_TESTS=OFF -DENABLE_LAYOUT_TESTS=OFF \
 -DDEVELOPER_MODE_FATAL_WARNINGS=OFF ../../repos/WebKit

メモリ10GiBの仮想マシンだと -j2 がリンクの都合上限界だった。

ビルド後、CMakeのビルドルールは -uninstalled.pc を生成するので、ビルドディレクトリを PKG_CONFIG_PATH に設定するとそちらが使われる。

$ PKG_CONFIG_PATH=/home/oku/build/webkit pkg-config wpe-webkit-2.0 --cflags
-I/home/oku/build/webkit/DerivedSources/ForwardingHeaders/wpe -I/home/oku/build/webkit/DerivedSources/WebKit/ -I/home/oku/build/webkit/DerivedSources/ForwardingHeaders/wpe-jsc -I/home/oku/build/webkit/JavaScriptCoreGLib/Headers -I/home/oku/build/webkit/JavaScriptCoreGLib/DerivedSources -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/sysprof-4 -I/usr/include/libsoup-3.0 -I/usr/include/libmount -I/usr/include/blkid -pthread -I/usr/include/wpe-1.0 -DWPE_ENABLE_XKB=1
okuokuokuoku

Configure (WPEBackend-direct)

とりえず、1.0 → 2.0して適当にconfigする。

diff --git a/meson.build b/meson.build
index a0f232d..1b7d191 100644
--- a/meson.build
+++ b/meson.build
@@ -7,7 +7,7 @@ project('wpebackend-direct', 'cpp',
 subdir('backend')

 build_args = []
-wpewebkit_dep = dependency('wpe-webkit-1.0', version: '>=2.38', required: true)
+wpewebkit_dep = dependency('wpe-webkit-2.0', version: '>=2.38', required: true)
 cc = meson.get_compiler('cpp')
 if cc.has_function('webkit_settings_set_enable_websecurity', dependencies: wpewebkit_dep, prefix: '#include <wpe/webkit.h>')
     build_args += '-DHAS_WEB_SECURITY'
$ PKG_CONFIG_PATH=/home/oku/build/webkit meson setup build

とりあえずビルドファイルは生成されるが警告が出る:

Checking for function "webkit_settings_set_enable_websecurity" with dependency wpe-webkit-2.0: NO

この webkit_settings_set_enable_websecurity はまだアップストリームされていないようだ。

エラーが結構でる。

../main.cpp: In function ‘WebKitWebView* {anonymous}::createWebView():
../main.cpp:45:23: エラー: ‘webkit_website_data_manager_new_ephemeral’ was not declared in this scope; did you mean ‘webkit_website_data_manager_is_ephemeral’?
   45 |     auto* wkManager = webkit_website_data_manager_new_ephemeral();
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                       webkit_website_data_manager_is_ephemeral
../main.cpp:46:5: エラー: ‘webkit_website_data_manager_set_tls_errors_policy’ was not declared in this scope; did you mean ‘webkit_website_data_manager_get_itp_summary_finish’?
   46 |     webkit_website_data_manager_set_tls_errors_policy(wkManager, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |     webkit_website_data_manager_get_itp_summary_finish
../main.cpp:48:26: エラー: ‘webkit_web_context_new_with_website_data_manager’ was not declared in this scope; did you mean ‘webkit_web_context_get_security_manager’?
   48 |     auto* wkWebContext = webkit_web_context_new_with_website_data_manager(wkManager);
      |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                          webkit_web_context_get_security_manager
../main.cpp:51:23: エラー: ‘webkit_web_view_new_with_context’ was not declared in this scope; did you mean ‘webkit_web_view_get_context’?
   51 |     auto* wkWebView = webkit_web_view_new_with_context(createWebViewBackend(), wkWebContext);
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                       webkit_web_view_get_context

この辺はCMakeに -DENABLE_2022_GLIB_API=OFF を渡してリビルドしないといけないようだ。

https://github.com/WebKit/WebKit/blob/29c5ff369592c83ac7da4d10cef8693b713de8d8/Source/WebKit/UIProcess/API/glib/WebKitWebsiteDataManager.h.in#L73-L79

というか良く見たら ENABLE_WPE_1_1_API ってのがあったな。。たぶんこっちが正解なんだろう。。

https://github.com/WebKit/WebKit/blob/29c5ff369592c83ac7da4d10cef8693b713de8d8/Source/cmake/OptionsWPE.cmake#L167-L173

okuokuokuoku

だめじゃん

[oku@fedora build]$ ./webview

** (process:48316): ERROR **: 12:28:01.672: Unable to spawn a new child process: Failed to spawn child process ?/opt/wpe-testing/libexec/wpe-webkit-2.0/WPENetworkProcess? (No such file or directory)

結局インストール要るのかよ!

okuokuokuoku

やりなおした

ビルドに2時間掛かるゾ。。

$ PKG_CONFIG_PATH=/opt/wpe-testing/lib64/pkgconfig meson setup build
[oku@fedora build]$ LD_LIBRARY_PATH=/opt/wpe-testing/lib64 ./webview
wpe: could not load the impl library. Is there any backend installed?: libWPEBackend-default.so: cannot open shared object file: No such file or directory

まだダメだな。。とりあえずsymlinkを張って、 LD_LIBRARY_PATH で適当に指定する。

$ ln -s backend/libwpebackend-direct.so libWPEBackend-default.so
$ LD_LIBRARY_PATH=/opt/wpe-testing/lib64:`pwd` ./webview

たぶんクラッシュしてるのはこの辺なのでブレークポイントを張って進めるのが良いかな。。ただ gdb だとロードするだけで数分掛かるのが超つらい。

https://github.com/WebKit/WebKit/blob/3a5521b1d7ea8451a71bbbb05bdd32def99a3249/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp#L129-L138

okuokuokuoku

そもそもバックエンドの選択機能がlibwpeのデバッグビルドにしか無いのでは説

https://github.com/Igalia/WPEBackend-direct/blob/537d403e777b061aab2f5610236f10d9d106ea89/main.cpp#L66

この環境変数 WPE_BACKEND_LIBRARY での指定が、libwpe側では:

https://github.com/WebPlatformForEmbedded/libwpe/blob/d7c669ca6f5ec0d544c264016d270669b336c931/src/loader.c#L75-L85

NDEBUG が定義されると処理されないようだ。。つまりFedoraのlibwpeには多分このロジックが無い。

というわけで libwpe をローカルビルドして再度。。

$ export LD_LIBRARY_PATH=/opt/wpe-testing/lib64:/home/oku/repos/WPEBackend-direct/build/backend:/home/oku/repos/libwpe/build:`pwd`
$ lldb -O "settings set symbols.enable-lldb-index-cache true" ./webview

... でも FDOバックエンドをロードしている。。

(lldb) bt
* thread #1, name = 'webview', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
  * frame #0: 0x00007fffe1496315 libWPEBackend-fdo-1.0.so.1`fdo_renderer_host::'lambda0'(void*)::_FUN(void*) + 37
    frame #1: 0x00007ffff7f3a8ab libwpe-1.0.so.1`wpe_renderer_host_create_client at renderer-host.c:44:12
    frame #2: 0x00007fffe6d8a8b2 libWPEWebKit-1.1.so.0`WebKit::WebProcessPool::platformInitializeWebProcess(this=0x00007fffd505c170, process=0x00007fff91000c00, parameters=0x00007fffffffd590) at WebProcessPoolGLib.cpp:82:47
    frame #3: 0x00007fffe69cbd4e libWPEWebKit-1.1.so.0`WebKit::WebProcessPool::initializeNewWebProcess(this=0x00007fffd505c170, process=0x00007fff91000c00, websiteDataStore=0x00007fffd502c110, isPrewarmed=No) at WebProcessPool.cpp:907:33
    frame #4: 0x00007fffe69caa48 libWPEWebKit-1.1.so.0`WebKit::WebProcessPool::createNewWebProcess(this=0x00007fffd505c170, websiteDataStore=0x00007fffd502c110, lockdownMode=Disabled, isPrewarmed=No, crossOriginMode=Shared) at WebProcessPool.cpp:673:28
    frame #5: 0x00007fffe69cd211 libWPEWebKit-1.1.so.0`WebKit::WebProcessPool::processForRegistrableDomain(this=0x00007fffd505c170, websiteDataStore=0x00007fffd502c110, registrableDomain=0x00007fffffffdca8, lockdownMode=Disabled) at WebProcessPool.cpp:1102:63
    frame #6: 0x00007fffe68b8959 libWPEWebKit-1.1.so.0`WebKit::WebPageProxy::launchProcess(this=0x00007fffd505c640, registrableDomain=0x00007fffffffdca8, reason=InitialProcess) at WebPageProxy.cpp:1018:60
    frame #7: 0x00007fffe68bc0f5 libWPEWebKit-1.1.so.0`WebKit::WebPageProxy::loadRequest(this=0x00007fffd505c640, request=0x00007fffffffdeb0, shouldOpenExternalURLsPolicy=ShouldAllowExternalSchemesButNotAppLinks, userData=0x0000000000000000) at WebPageProxy.cpp:1605:22
    frame #8: 0x00007fffe68bc3c8 libWPEWebKit-1.1.so.0`WebKit::WebPageProxy::loadRequest(this=0x00007fffd505c640, request=0x00007fffffffdeb0) at WebPageProxy.cpp:1622:112
    frame #9: 0x00007fffe6b7e9a1 libWPEWebKit-1.1.so.0`webkit_web_view_load_uri(webView=0x0000000000436910, uri="https://alteredqualia.com/three/examples/webgl_terrain_dynamic.html") at WebKitWebView.cpp:3187:33
    frame #10: 0x000000000040139a webview`main((null)=1, (null)=0x00007fffffffe148) at main.cpp:71:29
    frame #11: 0x00007fffe4f00b8a libc.so.6`__libc_start_call_main + 122
    frame #12: 0x00007fffe4f00c4b libc.so.6`__libc_start_main@@GLIBC_2.34 + 139
    frame #13: 0x0000000000401155 webview`_start + 37

どうもWebKitのWPE portではWebAudioサポートのためにこれを決めうちにしているようだ。

https://github.com/WebKit/WebKit/blob/d14f07282a9de962f9e0f3354bdc560227fdc12e/Source/WebCore/PlatformWPE.cmake#L74-L78

/usr/bin/ld: /usr/bin/ld: DWARF error: could not find abbrev number 75
Source/WebCore/CMakeFiles/WebCore.dir/./platform/graphics/gstreamer/WebKitAudioSinkGStreamer.cpp.o: in function `webKitAudioSinkHandleSample(_WebKitAudioSink*, WTF::GRefPtr<_GstSample>&&)':
WebKitAudioSinkGStreamer.cpp:(.text+0x3bb): undefined reference to `wpe_audio_source_start'
/usr/bin/ld: WebKitAudioSinkGStreamer.cpp:(.text+0x500): undefined reference to `wpe_audio_source_packet'
/usr/bin/ld: Source/WebCore/CMakeFiles/WebCore.dir/./platform/graphics/gstreamer/WebKitAudioSinkGStreamer.cpp.o: in function `webKitAudioSinkConfigure(_WebKitAudioSink*)::{lambda(_GstElement*, _WebKitAudioSink*)#3}::operator()(_GstElement*, _WebKitAudioSink*) const':
WebKitAudioSinkGStreamer.cpp:(.text+0x6be): undefined reference to `wpe_audio_source_stop'
/usr/bin/ld: Source/WebCore/CMakeFiles/WebCore.dir/./platform/graphics/gstreamer/WebKitAudioSinkGStreamer.cpp.o: in function `webKitAudioSinkConfigure(_WebKitAudioSink*)':
WebKitAudioSinkGStreamer.cpp:(.text+0x776): undefined reference to `wpe_audio_source_create'
/usr/bin/ld: WebKitAudioSinkGStreamer.cpp:(.text+0x7a0): undefined reference to `wpe_audio_source_has_receiver'
/usr/bin/ld: Source/WebCore/CMakeFiles/WebCore.dir/./platform/graphics/gstreamer/WebKitAudioSinkGStreamer.cpp.o: in function `webKitAudioSinkChangeState(_GstElement*, GstStateChange)':
WebKitAudioSinkGStreamer.cpp:(.text+0x11ef): undefined reference to `wpe_audio_source_pause'
/usr/bin/ld: WebKitAudioSinkGStreamer.cpp:(.text+0x12d2): undefined reference to `wpe_audio_source_resume'
/usr/bin/ld: Source/WebCore/CMakeFiles/WebCore.dir/./platform/graphics/gstreamer/WebKitAudioSinkGStreamer.cpp.o: in function `WTF::GPtrDeleter<wpe_audio_source>::operator()(wpe_audio_source*) const':
WebKitAudioSinkGStreamer.cpp:(.text._ZNK3WTF11GPtrDeleterI16wpe_audio_sourceEclEPS1_[_ZNK3WTF11GPtrDeleterI16wpe_audio_sourceEclEPS1_]+0x18): undefined reference to `wpe_audio_source_destroy'
collect2: エラー: ld はステータス 1 で終了しました
ninja: build stopped: subcommand failed.

この辺がfdoバックエンドにしか無いのか。とりあえずこの辺はオプションになっておらず、ライブラリが存在するとリンクが有効になる(何故!?)みたいなので WPEBACKEND_FDO_AUDIO_EXTENSION をUSEしないようにCMake側を書き換えて試してみる。

diff --git a/Source/cmake/GStreamerChecks.cmake b/Source/cmake/GStreamerChecks.cmake
index 5380617afc9c..b9131a766e4e 100644
--- a/Source/cmake/GStreamerChecks.cmake
+++ b/Source/cmake/GStreamerChecks.cmake
@@ -1,13 +1,14 @@
 if (ENABLE_VIDEO OR ENABLE_WEB_AUDIO)

     if (PORT STREQUAL "WPE")
-        find_package(WPEBackend_fdo 1.9.0)
-        if ((NOT WPEBACKEND_FDO_FOUND) OR WPEBACKEND_FDO_AUDIO_EXTENSION STREQUAL "WPEBACKEND_FDO_AUDIO_EXTENSION-NOTFOUND")
-            message(WARNING "WPEBackend-fdo audio extension not found. Disabling external audio rendering support")
-            SET_AND_EXPOSE_TO_BUILD(USE_WPEBACKEND_FDO_AUDIO_EXTENSION FALSE)
-        else ()
-            SET_AND_EXPOSE_TO_BUILD(USE_WPEBACKEND_FDO_AUDIO_EXTENSION TRUE)
-        endif ()
+        SET_AND_EXPOSE_TO_BUILD(USE_WPEBACKEND_FDO_AUDIO_EXTENSION FALSE)
+        #find_package(WPEBackend_fdo 1.9.0)
+        #if ((NOT WPEBACKEND_FDO_FOUND) OR WPEBACKEND_FDO_AUDIO_EXTENSION STREQUAL "WPEBACKEND_FDO_AUDIO_EXTENSION-NOTFOUND")
+            #message(WARNING "WPEBackend-fdo audio extension not found. Disabling external audio rendering support")
+            #SET_AND_EXPOSE_TO_BUILD(USE_WPEBACKEND_FDO_AUDIO_EXTENSION FALSE)
+        #else ()
+            #SET_AND_EXPOSE_TO_BUILD(USE_WPEBACKEND_FDO_AUDIO_EXTENSION TRUE)
+        #endif ()
     endif ()

     SET_AND_EXPOSE_TO_BUILD(USE_GSTREAMER TRUE)
okuokuokuoku

ばっちり動いた

... ただ操作できない。未実装なんではないか説。