Open7

WPE WebKitをCygwin+Clangでビルドする

okuokuokuoku

とりあえずclangは何となく動くレベルにビルドできたと思うので、今までサボっていたGStreamerをビルドして真面目にexecutableをlinkするまで行きたいと思う。

okuokuokuoku

GStreamerのビルド

最近のGStreamerは、いわゆるmonorepo化 https://gitlab.freedesktop.org/gstreamer/gstreamer したので、1つチェックアウトして meson で全体をビルドできる。 ...ビルドできるが絶妙に上手くいかないので適当にワークアラウンドする。

meson --default-library=static \
-Dgst-full-libraries=app,audio,fft,gl,mpegts,pbutils,tag,video,codecparsers \
"-Dgst-full-plugins=coreelements;playback;typefindfunctions;app;pbtypes" \
-Dintrospection=disabled builddir

meson のCMakeサポートは壊れていて、正常にreconfigureできない。オプションを変更した場合都度ビルドディレクトリを消せばOK。

https://github.com/mesonbuild/meson/issues/9431

生成された all ターゲットは正常にビルドできない( gobject-introspection がsubprojectなのに他のsubprojectから依存されている)ので、直接ターゲットを指定してビルドする。

ninja cyggstreamer-full-1.0.dll libgstreamer-full-1.0.a
okuokuokuoku

pkg-config が暴走する

... そこ!?

pkgconf --static --libs-only-l gstreamer-full-1.0

これがビジーループになり返ってこなくなる。

というかコレよく見たらpkgconf( https://github.com/pkgconf/pkgconf )じゃん。

$ pkg-config --version
1.6.3

とりあえずcygwinのsetupで差し替え。

$ pkg-config --version
0.29.1
okuokuokuoku

Clangでビルド

cmake -GNinja -DCMAKE_C_COMPILER=/cygdrive/f/webkit/llvm/bin/clang \
 -DCMAKE_CXX_COMPILER=/cygdrive/f/webkit/llvm/bin/clang++ \
-DCMAKE_BUILD_TYPE=Debug -DPORT=WPE \
-DWPE_INCLUDE_DIR=/cygdrive/f/webkit/proj/libwpe/include \
-DWPE_LIBRARY=/usr/lib/libelf.a \
-DUSE_SOUP2=ON -DENABLE_JOURNALD_LOG=OFF -DENABLE_JIT=OFF \
-DENABLE_C_LOOP=ON -DENABLE_SAMPLING_PROFILER=OFF \
-DENABLE_UNIFIED_BUILDS=OFF ../../proj/WebKit

デバッグ情報はサイズ的にリンクできないのが分かっているので、リンカのオプションで落としてしまうことにした。

diff --git a/Source/cmake/OptionsCommon.cmake b/Source/cmake/OptionsCommon.cmake
index c3ae81234f57..a52eddb56e08 100644
--- a/Source/cmake/OptionsCommon.cmake
+++ b/Source/cmake/OptionsCommon.cmake
@@ -97,6 +97,13 @@ if (DEBUG_FISSION)
     endif ()
 endif ()

+if (CYGWIN)
+    # Strip debug information for now
+    string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-S")
+    string(APPEND CMAKE_SHARED_LINKER_FLAGS " -Wl,-S")
+    string(APPEND CMAKE_MODULE_LINKER_FLAGS " -Wl,-S")
+endif()
+
 set(GCC_OFFLINEASM_SOURCE_MAP_DEFAULT OFF)
 if (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
     set(GCC_OFFLINEASM_SOURCE_MAP_DEFAULT ON)

ClangはPDBも出力できるはずなので、そっちに寄せるのがたぶん簡単だろう。。 BFD ldじゃリンクできないじゃん。。lldがCOFF+PEもリンクできるのでそれをビルドして使うのが多分早道ではあるが。。

okuokuokuoku

UninstalledなGLibが正常に使えない

... マジでダメっぽいので次からはGLib(とgobject-introspection)は別途ビルドしてインストールしてから使う方が良さそうだな。。

最終的に、CMakeが検出するGLibのヘッダ/ライブラリパスは正常に使えなかったのでoverrideした。

GLIB_INCLUDE_DIR:PATH=/cygdrive/f/webkit/proj/gstreamer/subprojects/glib/glib;/cygdrive/f/webkit/proj/gstreamer/subprojects/glib;/cygdrive/f/webkit/proj/gstreamer/builddir/subprojects/glib;/cygdrive/f/webkit/proj/gstreamer/subprojects/glib/gmodule
GLIB_LIBRARIES:FILEPATH=/cygdrive/f/webkit/proj/gstreamer/builddir/subprojects/glib/glib/libglib-2.0.a;-lpcre;-liconv;-lintl

WebKit供給の FindGLIB.cmake は、このとき GLIB_LIBRARY_DIR が1つだけということに依存していたので適当に修正した。

diff --git a/Source/cmake/FindGLIB.cmake b/Source/cmake/FindGLIB.cmake
index 07f984ac09cf..8761cba76f2c 100644
--- a/Source/cmake/FindGLIB.cmake
+++ b/Source/cmake/FindGLIB.cmake
@@ -50,9 +50,14 @@ find_library(GLIB_LIBRARIES
           ${PC_GLIB_LIBRARY_DIRS}
 )

+# FIXME: Handle multiple libraries returned from find_library
+
+list(GET GLIB_LIBRARIES 0 GLIB_LIBRARIES0)
+
 # Files in glib's main include path may include glibconfig.h, which,
 # for some odd reason, is normally in $LIBDIR/glib-2.0/include.
-get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES} PATH)
+get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES0} PATH)
+unset(GLIB_LIBRARIES0)
 find_path(GLIBCONFIG_INCLUDE_DIR
     NAMES glibconfig.h
     HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${_GLIB_LIBRARY_DIR}

ヘッダ

/cygdrive/f/webkit/proj/gstreamer/subprojects/glib/glib/glib.h:30:10: fatal error: 'glib/galloca.h' file not found
#include <glib/galloca.h>
         ^~~~~~~~~~~~~~~~
1 error generated.
/cygdrive/f/webkit/proj/gstreamer/subprojects/glib/glib/glib-object.h:25:10: fatal error: 'gobject/glib-enumtypes.h' file not found
#include <gobject/glib-enumtypes.h>
         ^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

GLIB_INCLUDE_DIR は1つのディレクトリしか検出しないようなので、自動生成されるヘッダが含まれるディレクトリを手動で追加してやる必要があった。

config.h

↑ のようにインクルードパスを追加すると、 WebKit 側の config.h と GLib側の config.h が衝突してしまって正常にリンクできなくなってしまった。

#if ENABLE(ALLOCATION_LOGGING)
    ^
/cygdrive/f/webkit/proj/WebKit/Source/JavaScriptCore/llint/LLIntCommon.h:36:5: error: function-like macro 'ENABLE' is not defined


#include "..." search starts here:
#include <...> search starts here:
 JavaScriptCore/Headers
 /cygdrive/f/webkit/proj/gstreamer/subprojects/glib/glib
 /cygdrive/f/webkit/proj/gstreamer/subprojects/glib
 /cygdrive/f/webkit/proj/gstreamer/builddir/subprojects/glib // ★ ← ここに config.h がある
 /cygdrive/f/webkit/proj/gstreamer/subprojects/glib/gmodule
 /cygdrive/f/webkit/proj/gstreamer/builddir/subprojects/glib/glib
 . // ★ ← ここの config.h を #include したい
 /cygdrive/f/webkit/proj/WebKit/Source/JavaScriptCore
 /cygdrive/f/webkit/proj/WebKit/Source/JavaScriptCore/API
 /cygdrive/f/webkit/proj/WebKit/Source/JavaScriptCore/assembler
 /cygdrive/f/webkit/proj/WebKit/Source/JavaScriptCore/b3
 /cygdrive/f/webkit/proj/WebKit/Source/JavaScriptCore/b3/air
   :

こればっかりはどうしようもないので、 glib 内の config.h を手で削除した。これはGLibのビルド時にしか必要ないはずだし。。

ライブラリ

... なぜか PCRE と libintl、libiconvの依存が正常にリンクされなかった。shared libraryになることを前提にしている。。??

okuokuokuoku

大文字小文字の区別が必須

どうもまだコンパイルがうまくいかないのでプリプロセスしてみたら

  • Source/WebKit/Shared/API/c/wpe/WebKit.h
  • Source/WebKit/UIProcess/API/wpe/webkit.h

の2ファイルが存在し、これらは大小文字で区別されていることがわかった。

CygwinはNTFSのcase insensitive filesystemを使えるので、

chattr +C .

してからファイル消して再チェックアウトすればOK。

okuokuokuoku

オープンするファイルが多すぎてリンクに失敗する

EDIT: そもそもWebKitのビルドオプションに USE_THIN_ARCHIVE というのがあったのでそれを OFF にすれば良いだけだと思う。( ar の代わりに CMAKE_AR=llvm-ar するのとセットで。。)

コンパイルは全部通ったが、リンクに失敗する。

ld: lib/libWebCore.a: error adding symbols: malformed archive

とりあえず strace でsyscallを確認してみると、 EMFILE https://github.com/cygwin/cygwin/blob/fb1fe932038e5a9833fcc5fc53365a2212d76584/winsup/cygwin/errno.cc#L192 つまりオープンしたファイルが多すぎて失敗していることがわかった。

 1481 296127668 [main] ld 12990 open: open(lib/../Source/WebCore/CMakeFiles/WebCore.dir/editing/ReplaceNodeWithSpanCommand.cpp.o, 0x10000)
  229 296127897 [main] ld 12990 __set_errno: int dtable::extend(size_t, size_t):83 setting errno 24
   72 296127969 [main] ld 12990 open: -1 = open(lib/../Source/WebCore/CMakeFiles/WebCore.dir/editing/ReplaceNodeWithSpanCommand.cpp.o, 0x10000), errno 24

(errno 24 = EMFILE)

よく見ると、 WebCore.a は静的ライブラリのはずなのに .o をオープンしているのがわかる。これはCMakeがstatic libraryをthin archiveとして作っているのが原因で、 file コマンドで確認できる。

$ file lib/libWebCore.a
lib/libWebCore.a: thin archive with 2662554 symbol entries

というわけで thin archive を適当に通常のアーカイブに変換することでリンクができるようになった。

ar t lib/libWebCore.a | xargs ar rs temp.a

(実際には ar では小一時間掛かってもアーカイブが終わらなかったので llvm-ar を使った。)