webkit在win32下的編譯規則
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
最近有人在windows 7下的webkit編譯不過去,問我該怎麼解決。我看了一下,主要是SVGAnimationElement.cpp等檔案編譯不過去,這裡面使用了開啟svg後的一些列舉變數,但webkit在編譯時生成的WebKitBuild/include/WebCore/CSSPropertyNames.h檔案裡面並沒有生成這些列舉變數,我檢查一些編譯選項,配置都是OK的,我又看了一下webkit的編譯規則,發現CSSPropertyNames.h的生成是依賴CSSPropertyNames.in等檔案。解決方法也簡單:將CSSPropertyNames.in等檔案裡面加上一行後再刪除,再編譯就OK了。為什麼這樣就可以了呢?願意是windows下的makefile的編譯依賴並不像linux下那麼可靠,有時候windows版的makefile工具在編譯出錯了也更新了檔案的修改時間,導致下次makefile再檢查時認為檔案沒改變,從而跳過去了,上面所說的CSSPropertyNames.in就是這種情況。前面我的blog裡面也寫了一下webki編譯方面的文章,網上也有一些類似的文章,也有很多網友在webkit編譯不過時發帖詢問,所以我覺得很多人對webkit是如何編譯的並不是太清楚,導致編譯出錯了不知道原因,自然也不知道如何去解決這個問題。久而久之,越來越多的人就會發現編譯webkit都是一個問題,更不用說去研究webkit了。為了幫助這些人克服對webkit編譯的恐懼,我這幾天詳細看了一下webkit在windows下的編譯規則,寫也這篇類似於總結的文章。
1. 目錄劃分
在webkit原始碼的根目錄下,有Makefile,CMakeLists.txt,android.mk,WebKit.pro等檔案與編譯有關,其中makefile主要用於linux環境下,windows上雖然用了cygwin,卻並沒有使用這個makefile去編譯;CMakeLists.txt主要是用於cmake環境下,這是一個跨平臺的編譯環境,但我發現在windows下使用cmake編譯的人並不多,這可能主要是因為webkit官網介紹的主要是cgywin+vs的編譯方式導致的;WebKit.pro是qt環境下的編譯規則,qt自己定了一套編譯規則,做了一個類似於makefile的工具qmake,是跨平臺的,但是得下一套qt的編譯環境或sdk,所以這個也主要是qt的人在維護,不過qt版的webkit發展還是不錯的;android.mk是android下webkit的編譯規則。這篇檔案要介紹的windows編譯規則在根目錄並沒有包含,而是在下面的子目錄下實現的,原因可能是這套規則(cygwin+vs)只適合於windows平臺,不是一個common的東西,所以不能放在根目錄下,cygwin+vs這套環境主要是apple的人在維護,safari的windows版本應該也是使用這套環境編譯出來的。順便提一下,chrome下的編譯規則字尾是gypi,例如webcore目錄下的WebCore.gypi檔案。
webkit主要由3部分組成:JavaScriptCore,WebCore,WebKit。JavaScriptCore下主要是瀏覽器使用的javascript引擎程式碼,當使用v8引擎時,這個目錄是不參加編譯的;WebCore下的程式碼是瀏覽器的核心了,包括網頁解析,layout,render等,dom規範和css規範的也是在這裡面實現的,如果像知道瀏覽器裡面的window物件是如何實現的,可以去WebCore/dom下看看,WebCore下與平臺相關的是針對不同平臺有不同的目錄,編譯依賴也是不一樣的;WebKit下是提供給瀏覽器外殼的介面的實現程式碼。最終,JavaScriptCore被編譯成了JavaScriptCore.dll,webcore和webkit目錄被編譯成了webkit.dll。JavaScriptCore.dll以dll export的方式匯出了函式供webcore和webkit使用,webkit.dll則是以COM的方式提供介面給瀏覽器外殼(例如safari.exe)使用。如果你對比一下webkit目錄在mac和windows上的實現,就會發現Object-C和COM的概念有很多方面是相似,只不過Object-C
在webkit的其他目錄,與編譯相關的目錄還有WebKitLibraries,WebKitTools等。WebKitLibraries裡面放著編譯依賴的標頭檔案和lib,例如icu,libxml,sqlite的標頭檔案和lib,當我們執行update-webkit命令時,有一步就是從apple官網下載WebKitSupportLibrary.zip,然後解壓到WebKitLibraries目錄下;WebKitTools主要放著一些工具和例子,與編譯相關的主要放著WebKitTools/Scripts目錄下,例如update-webkit和build-webkit都是放在這下面,這個目錄下perl指令碼居多,bat(cmd)和py佔少數。這種多種語言混在一起在編譯環境裡面是很常見的,從中我們可以學到一點的是用最適合的工具和語言做你想做的事情,沒必要去爭誰好誰壞,每個工具和語言都有自己的優點和弱點,用刀就要用刀刃。工具始終是工具,總有被淘汰的時候和地方,我們真正要關注的是我們的目標。
在windows下,很多人第一次編譯webkit都是在cygwin的命令列裡面執行build-webkit開始的,build-webkit其實也是呼叫vs的devenv.exe編譯的,只不過它是在命令列編譯,而更多人在後期都會使用vs ide去編譯,因為比較直觀和熟悉。當vs ide有一個問題是有點佔記憶體,它的智慧提示會經常掃描檔案,弄得cpu佔有率很高,最終智慧提示生成的ncb檔案也很大,不過這個有一個好處是除錯的時候比較好找對應的函式實現(如果你的機器夠強勁,裝上Visual Assist X外掛會更好)。vs工程在各個目錄的位置如下:
JavaScriptCore:D:/tools/cygwin/home/xufan/WebKit/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj,D:/tools/cygwin/home/xufan/WebKit/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj等
WebCore:D:/tools/cygwin/home/xufan/WebKit/WebCore/WebCore.vcproj下的WebCore.vcproj等
Webkit:D:/tools/cygwin/home/xufan/WebKit/WebKit/win/WebKit.vcproj下的WebKit.vcproj等
整個webkit solution的檔案是D:/tools/cygwin/home/xufan/WebKit/WebKit/win/WebKit.vcproj/WebKit.sln,雙擊可以用vs ide開啟。
下面將從webkit的目錄挑出一些代表性的編譯規則進行討論:
2. WebKitTools/Scripts目錄
首先從update-webkit指令碼說起,這個指令碼主要是呼叫svn update(或git)去更新程式碼(80,81行),然後呼叫update-webkit-auxiliary-libs,update-webkit-auxiliary-libs通過curl下載WebKitSupportLibrary.zip(92行),最後解壓到WebKitLibraries目錄下(96行,116行)。
接下來看build-webkit指令碼,build-webkit指令碼的前344行主要是將命令列引數轉換為perl裡面的變數,289行到315行可以看到build-webkit支援的引數:
Usage: $programName [options] [options to pass to build system]
--help Show this help message
--clean Cleanup the build directory
--debug Compile in debug mode
--wincairo Build using Cairo (rather than CoreGraphics) on Windows
--chromium Build the Chromium port on Mac/Win/Linux
--gtk Build the GTK+ port
--qt Build the Qt port
--efl Build the EFL port
--inspector-frontend Copy changes to the inspector front-end files to the build directory
--install-headers= Set installation path for the headers (Qt only)
--install-libs= Set installation path for the libraries (Qt only)
--v8 Use V8 as JavaScript engine (Qt only)
--prefix= Set installation prefix to the given path (Gtk/Efl only)
--makeargs= Optional Makefile flags
--minimal No optional features, unless explicitly enabled.
build-webkit接下來呼叫的很多函式都是在webkitdirs.pm裡面定義的(build-webkit的第40行:use webkitdirs),例如productDir(),這個是webkit輸出結果的目錄,從productDir的實現來看,輸出目錄主要是由WEBKITOUTPUTDIR這個環境變數決定的(webkitdirs.pm的119行),如果不存在則用根目錄下的WebKitBuild目錄(154行:$baseProductDir = "$sourceDir/WebKitBuild";)。360行到500行都是做一些檢查工作,開始編譯是從500行到551行,如下:
[python] view plain copy print ?- # Build, and abort if the build fails.
- for my $dir (@projects) {
- chdir $dir or die;
- my $result = 0;
- # For Gtk and Qt the WebKit project builds all others
- if ((isGtk() || isQt()) && $dir ne "WebKit") {
- chdir ".." or die;
- next;
- }
- if (isGtk()) {
- $result = buildGtkProject($dir, $clean, @options);
- } elsif (isQt()) {
- $result = buildQMakeQtProject($dir, $clean, @options);
- } elsif (isAppleMacWebKit()) {
- $dir = "MiniBrowser" if $dir eq "WebKitTools/MiniBrowser";
- my @local_options = @options;
- push @local_options, XcodeCoverageSupportOptions() if $coverageSupport && $dir ne "ANGLE";
- $result = buildXCodeProject($dir, $clean, @local_options, @ARGV);
- } elsif (isAppleWinWebKit()) {
- if ($dir eq "WebKit") {
- $result = buildVisualStudioProject("win/WebKit.vcproj/WebKit.sln", $clean);
- }
- }
- # Various build* calls above may change the CWD.
- chdirWebKit();
- if (exitStatus($result)) {
- my $scriptDir = relativeScriptsDir();
- if (usingVisualStudioExpress()) {
- # Visual Studio Express is so lame it can't stdout build failures.
- # So we find its logs and dump them to the console ourselves.
- system(File::Spec->catfile($scriptDir, "print-vse-failure-logs"));
- }
- if (isAppleWinWebKit()) {
- print "/n/n===== BUILD FAILED ======/n/n";
- print "Please ensure you have run $scriptDir/update-webkit to install dependencies./n/n";
- my $baseProductDir = baseProductDir();
- print "You can view build errors by checking the BuildLog.htm files located at:/n$baseProductDir/obj//./n";
- }
- exit exitStatus($result);
- }
- }
在cygwin+vs的環境下執行的是:buildVisualStudioProject("win/WebKit.vcproj/WebKit.sln", $clean),buildVisualStudioProject的程式碼如下(在webkitdirs.pm的1205行):
[vb] view plain copy print ?- sub buildVisualStudioProject
- {
- my ($project, $clean) = @_;
- setupCygwinEnv();
- my $config = configurationForVisualStudio();
- dieIfWindowsPlatformSDKNotInstalled() if $willUseVCExpressWhenBuilding;
- chomp($project = `cygpath -w "$project"`) if isCygwin();
- my $action = "/build";
- if ($clean) {
- $action = "/clean";
- }
- my @command = ($vcBuildPath, $project, $action, $config);
- print join(" ", @command), "/n";
- return system @command;
- }
setupCygwinEnv主要是通過環境變數去查詢vs的安裝位置,然後呼叫pdevenv指令碼(1094行)去根據vs的版本呼叫不同的指令碼去設定vs編譯環境。vsvars32.bat和devenv.com應該大家都比較熟(不知道的可以看看開始選單裡面的Visual Studio 2005 Command Prompt快捷方式的指向),呼叫它們就是在pdevenv腳本里面做的。
最終呼叫vs的指令碼展開後的形式可以看cygwin的命令列輸出(見上面的my @command = ($vcBuildPath, $project, $action, $config);及其下面的一行),我這邊是:
/home/xufan/Webkit/WebKitTools/Scripts/pdevenv win/WebKit.vcproj/WebKit.sln /build Debug_Cairo_CFLite
呼叫devenv.exe之後,編譯規則就完全是vs的規則了,入口是WebKit/win/WebKit.vcproj/WebKit.sln,比較重要的工程是上面所說的JavaScriptCore.vcproj,WebCore.vcproj和WebKit.vcproj這幾個工程了。
今天就先到這了,明天接著寫這些比較重要的vs工程,重點包括js dom的物件(例如window物件)粘合(glue)到javascriptCore的程式碼是如何自動生成的,如果根據css關鍵字生成程式碼,webcore下面檔案的編譯順序和規則等。