1. 程式人生 > >webkit在win32下的編譯規則

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檔案。

 image

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

在語言級別將COM思想的一些複雜實現簡化了。

在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 ?
  1. # Build, and abort if the build fails.   
  2. for my $dir (@projects) {   
  3.     chdir $dir or die;   
  4.     my $result = 0;  
  5.     # For Gtk and Qt the WebKit project builds all others   
  6.     if ((isGtk() || isQt()) && $dir ne "WebKit") {   
  7.         chdir ".." or die;   
  8.         next;   
  9.     }  
  10.     if (isGtk()) {   
  11.         $result = buildGtkProject($dir, $clean,  @options);   
  12.     } elsif (isQt()) {   
  13.         $result = buildQMakeQtProject($dir, $clean, @options);   
  14.     } elsif (isAppleMacWebKit()) {   
  15.         $dir = "MiniBrowser" if $dir eq "WebKitTools/MiniBrowser";   
  16.         my @local_options = @options;   
  17.         push @local_options, XcodeCoverageSupportOptions() if $coverageSupport && $dir ne "ANGLE";   
  18.         $result = buildXCodeProject($dir, $clean, @local_options, @ARGV);   
  19.     } elsif (isAppleWinWebKit()) {   
  20.         if ($dir eq "WebKit") {   
  21.             $result = buildVisualStudioProject("win/WebKit.vcproj/WebKit.sln", $clean);   
  22.         }   
  23.     }   
  24.     # Various build* calls above may change the CWD.   
  25.     chdirWebKit();  
  26.     if (exitStatus($result)) {   
  27.         my $scriptDir = relativeScriptsDir();   
  28.         if (usingVisualStudioExpress()) {   
  29.             # Visual Studio Express is so lame it can't stdout build failures.   
  30.             # So we find its logs and dump them to the console ourselves.   
  31.             system(File::Spec->catfile($scriptDir, "print-vse-failure-logs"));   
  32.         }   
  33.         if (isAppleWinWebKit()) {   
  34.             print "/n/n===== BUILD FAILED ======/n/n";   
  35.             print "Please ensure you have run $scriptDir/update-webkit to install dependencies./n/n";   
  36.             my $baseProductDir = baseProductDir();   
  37.             print "You can view build errors by checking the BuildLog.htm files located at:/n$baseProductDir/obj//./n";   
  38.         }   
  39.         exit exitStatus($result);   
  40.     }   
  41. }  
# 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 ?
  1. sub buildVisualStudioProject   
  2. {   
  3.     my ($project, $clean) = @_;   
  4.     setupCygwinEnv();  
  5.     my $config = configurationForVisualStudio();  
  6.     dieIfWindowsPlatformSDKNotInstalled() if $willUseVCExpressWhenBuilding;  
  7.     chomp($project = `cygpath -w "$project"`) if isCygwin();   
  8.     my $action = "/build";   
  9.     if ($clean) {   
  10.         $action = "/clean";   
  11.     }  
  12.     my @command = ($vcBuildPath, $project, $action, $config);  
  13.     print join(" ", @command), "/n";   
  14.     return system @command;   
  15. }  
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下面檔案的編譯順序和規則等。

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述