Hatena::ブログ(Diary)

最速チュパカブラ研究会

 | 

2007年9月27日 WebKitビルドガイド(ドザー用)

Safari for Windowsが出た直後にWindows上でWebKitビルドをしようとしたらうまくいかず、そのまま放置していたのですが、ふと思い立って再挑戦したらうまくいったので、注意点などをメモしておきます。

環境整備

Installing the Developer Toolsの通りに作業します。

注意点など。

cygwin
上記のページにWebKitビルド用の特製cygwinパッケージがありますので、よくわからない人はこれを入れるのが無難でしょう。
私はMozilla用のcygwin環境を使いまわしましたが、この場合はcurlperlなどを自分で入れておく必要があります。
Visual C++ 2005 Express SP1
SP1導入は必須です。これが無いと、リンク時に変なエラーC1900など)が出ます。
Safari for Windows
ビルドには必要ありませんが、インストールしておけば自家ビルドのWebKitをSafariに組み込んで起動することができます。ぜひインストールしておきましょう。

あと必須ではないですが、Rubyを入れておくと便利です(その理由は、この記事の後の方に書いてありますので、入れるかどうかは各自で判断してください)

ソース取得

Getting WebKitの通りに作業します。

以下は、c:\wk_tutorial 以下にソースツリーを構築する場合の例です

$ cd /cygdrive/c/
$ mkdir wk_tutorial
$ cd wk_tutorial
$ svn checkout http://svn.webkit.org/repository/webkit/trunk WebKit

WebKitSupportLibrary.zip

<WebKit Support Librariesのインストール>

$ WebKit/WebKitTools/Scripts/update-webkit

最後の WebKit/WebKitTools/Scripts/update-webkit は必須です。これを行わないと、libxml等の依存ライブラリソースツリーに入りません。

ビルド

いよいよビルド開始です。ここではDebug版を作ることにします。

$ WebKit/WebKitTools/Scripts/set-webkit-configuration --debug
$ WebKit/WebKitTools/Scripts/build-webkit --debug

成功すると C:\wk_tutorial\WebKit\WebKitBuild\bin に WebKit_debug.dll というファイルが生成されます。
…が、一発で成功するのはよほど運がいい人です。コケポイントがあるので以下で説明します。

ビルドログのチェック

とりあえず、初回のビルドが終わるまで待ってください。…どうでしょうか。何もメッセージが出ずに終了したと思います。何もメッセージが出てないと成功したのかと思ってしまいますが、WebKitのビルドシステムは、コンソールにエラーを出しません。コンパイラとリンカのエラーは、VisualStudioが生成するBuildLog.htmというファイルに記録されています。ところがこのファイルはプロジェクトごとに分かれているので、エラーがどこで起きたか調べるためには、ソリューションに含まれる全てのプロジェクトのBuildLog.htmを洗わなければいけません。

こんなことは人間様がやることではないので、自動化しましょう。以下のようなスクリプトを作成します。

  1. BuildLog.htmをビルドの順序と同じ順番でチェックする
  2. 致命的なエラーが発生していたら、そこでチェックを打ち切って該当するBuildLog.htmを開く

私はこれをRubyで記述しました(だからRubyを入れることを薦めたんです… 私はPerlが嫌いなので)

$KCODE = "SJIS"
require 'kconv'

# Debug or Release
$Configuration = "Debug"

# default: BuildLog.htm
$BuildLogFile = "BuildLog.htm"

# RegExp pattern for finding build results
$ResultLookUp = /<pre>[^<]+([0-9]+)、警告 ([0-9]+)[^<]+<\/pre>/m

$BuildLogs = []

# Don't change the order!

$BuildLogs << [false, "WebKit/WebKitBuild/obj/JavaScriptCore/dftables/#{$Configuration}/"]
$BuildLogs << [true,  "WebKit/WebKitBuild/obj/JavascriptCore/#{$Configuration}/"]
$BuildLogs << [true,  "WebKit/WebKitBuild/obj/WebKit/#{$Configuration}/Interfaces/"]
$BuildLogs << [true,  "WebKit/WebKitBuild/obj/WebKit/#{$Configuration}/WebKitGUID/"]
$BuildLogs << [true,  "WebKit/WebKitBuild/obj/WTF/#{$Configuration}/"]
$BuildLogs << [true,  "WebKit/WebKitBuild/obj/WebCore/#{$Configuration}/"]
$BuildLogs << [true,  "WebKit/WebKitBuild/obj/WebKit/#{$Configuration}/"]
$BuildLogs << [true,  "WebKit/WebKitBuild/obj/WebKitInitializer/#{$Configuration}/"]
$BuildLogs << [false, "WebKit/WebKitBuild/obj/JavaScriptCore/testkjs/#{$Configuration}/"]
$BuildLogs << [false, "WebKit/WebKitBuild/obj/TestNetscapePlugin/#{$Configuration}/"]
$BuildLogs << [false, "WebKit/WebKitBuild/obj/DumpRenderTree/#{$Configuration}/"]


def checkLog(fn)
	if !File.exists?(fn)
		puts "#{fn} not found"
		return 1
	end

	File.open(fn){|f|
		content = f.read.tosjis
		if !(content =~ $ResultLookUp)
			puts "cannot find build results in #{fn}"
			return 2
		end

		fatal_errors = $1
		warnings = $2

		puts "\n#{fn}\n  fatal: #{$1}  warning: #{$2}"

		return 3 if $1.to_i > 0
	}

	return 0
end

stopped = false
$BuildLogs.each{|logent|
	showstopper = logent[0]
	fn = logent[1]

	res = checkLog(fn + $BuildLogFile)
	if  res != 0
		stopped = true

		if showstopper
			puts "** stop **"

			file_to_open = "#{fn}#{$BuildLogFile}".gsub(/\//, '\\')
			`cmd /c start "#{file_to_open}"` if res != 1

			break
		else
			puts "  ** This is an optional project. Ignored fatal errors. **"
		end
	end
}

puts "\nCongratulations! All projects seem to be built successfully." if !stopped

cssmakevaluesの修正

早速、前述のスクリプトを c:\wk_tutorial に pickerr.rb という名前で置いて実行します。

$ ruby pickerr.rb

WebKit/WebKitBuild/obj/JavaScriptCore/dftables/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/JavascriptCore/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebKit/Debug/Interfaces/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebKit/Debug/WebKitGUID/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WTF/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebCore/Debug/BuildLog.htm
  fatal: 1  warning: 1
** stop **

6つ目(WebCore)でエラーが出ていますか? 出ていなければ、このセクションを無視してください。

改行コードDOS式(CR-LF)の環境でビルドしている場合は、以下のようなエラーが出ます。

この問題は修正されました。最新のソースをビルドする場合は、このセクションを無視してください。

Use of uninitialized value in length at /cygdrive/c/WK_TUT~1/WebKit/WebCore/ksvg2/scripts/cssmakevalues line 162.
Died at /cygdrive/c/WK_TUT~1/WebKit/WebCore/ksvg2/scripts/cssmakevalues line 162.
make: *** [ksvgcssvalues.h] Error 29

これは、cygwinのperlがDOS式の改行コード(CR-LF)をうまく扱えないことによるエラーです。

C:\wk_tutorial\WebKit\WebCore\ksvg2\scripts\cssmakevalues の70行目付近を以下のように修正してください:

while (<IN>) {
    chomp;
    my $prop = $_;

	$prop =~ s/[\r\n]+$//; # ← この行を追加

	if(not($prop =~ /#/) and (length($prop) > 0)) {
	    $num = $num + 1;

	    my $up = uc($prop);

ファイルから読み込んだ文字列からCR/LFを強制的に削ります。

では、もう一度ビルドします。

$ WebKit/WebKitTools/Scripts/build-webkit --debug

winres.hのコピー

ビルドが終わったら、もう一度 pickerr.rb を実行します。

$ ruby pickerr.rb

WebKit/WebKitBuild/obj/JavaScriptCore/dftables/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/JavascriptCore/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebKit/Debug/Interfaces/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebKit/Debug/WebKitGUID/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WTF/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebCore/Debug/BuildLog.htm
  fatal: 0  warning: 86

WebKit/WebKitBuild/obj/WebKit/Debug/BuildLog.htm
  fatal: 1  warning: 1
** stop **

今度は7つ目のプロジェクト(WebKit)でエラーが出ました。エラーの内容は以下:

.\WebKit.rc(5) : fatal error RC1015: cannot open include file 'winres.h'.

このエラーが出た場合は、以下のようにしてPlatform SDKに含まれているwinres.hをコピーしてください。

$ cp /cygdrive/c/Program\ Files/Microsoft\ Platform\ SDK/Include/mfc/WINRES.H ./WebKit/WebKit/win/WebKit.vcproj/

もう一度ビルドして、pickerr.rb を叩いてみます。今度はどうでしょうか。

$ WebKit/WebKitTools/Scripts/build-webkit --debug
$ ruby pickerr.rb

WebKit/WebKitBuild/obj/JavaScriptCore/dftables/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/JavascriptCore/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebKit/Debug/Interfaces/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebKit/Debug/WebKitGUID/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WTF/Debug/BuildLog.htm
  fatal: 0  warning: 0

WebKit/WebKitBuild/obj/WebCore/Debug/BuildLog.htm
  fatal: 0  warning: 86

WebKit/WebKitBuild/obj/WebKit/Debug/BuildLog.htm
  fatal: 0  warning: 2

WebKit/WebKitBuild/obj/WebKitInitializer/Debug/BuildLog.htm
  fatal: 0  warning: 4

WebKit/WebKitBuild/obj/JavaScriptCore/testkjs/Debug/BuildLog.htm
  fatal: 0  warning: 2

WebKit/WebKitBuild/obj/TestNetscapePlugin/Debug/BuildLog.htm
  fatal: 1  warning: 1
  ** This is an optional project. Ignored fatal errors. **

WebKit/WebKitBuild/obj/DumpRenderTree/Debug/BuildLog.htm
  fatal: 0  warning: 0

TestNetscapePlugin というプロジェクトでエラーが出ていますが、これは必須ではないので無視しています。その他は成功していますので、WebKit_debug.dll が完成しているはずです。

$ ls WebKit/WebKitBuild/bin/
DumpRenderTree_debug.exe  WebKit_debug.ilk    testkjs_debug.exe
DumpRenderTree_debug.ilk  WebKit_debug.pdb    testkjs_debug.ilk
DumpRenderTree_debug.pdb  dftables_debug.exe  testkjs_debug.pdb
WebKit.resources          dftables_debug.ilk
WebKit_debug.dll          dftables_debug.pdb

…ありましたか?

実行

Safari for Windowsが入っている状態で以下のように入力すると、今ビルドしたWebKit_debug.dllを使用してSafariを起動します。

$ WebKit/WebKitTools/Scripts/run-safari --debug

立ち上がりましたか?

screenshot

デバッグビルドなので、Visual Studioプロセスをアタッチすれば、デバッガで動作を追うことが可能です。これが自家ビルドの醍醐味です(と言っても実は、webkit.orgでもデバッグ情報入りのビルドが配布されているのですが)

debugger

↑これは、はてなのトップページを読み込んで、DOMツリーが構築されている途中を捕まえたところです。

 |