在Windows中使用MinGW編譯V8

 Thu, 09 Sep 2010 22:50:38 +0800

之前使用VC2005~2008 Express及Microsoft Windows SDK來編譯V8都很順利,不過改用MinGW編譯時發現問題還不少。

首先,scons雖然支援toolchain=gcc選項,但是...編譯器跟連結器的執行檔名沒有放在scons的程式中,所以一定找不到。所以除了在PATH環境中要加入 [MinGW安裝目錄]\bin 之外,還需要修改scons套件...這篇文章中有一些說明,可以參考他的說明來修改。不過如果你下載的是最新版的V8 (2.2之後),光靠他文章中的設定是沒有辦法成功的。

V8從2.2版之後,會使用Windows Server 2003 SDK之後版本的winnt.h中才會有的巨集,這個巨集在MinGW中的winnt.h是不存在的...不過只是巨集,所以可以想辦法直接從Windows Server 2003 SDK中移植過來,但是要把其中的asm語法改成gcc的語法。例如我自己在MinGW中的winnt.h中加上:

#if defined(_M_IX86)
#if !defined(_M_CEE_PURE)
#pragma warning( push )
#pragma warning( disable : 4793 )
FORCEINLINE
VOID
MemoryBarrier (
    VOID
    )
{
    LONG Barrier;
    __asm__ __volatile__(
    "xchgl %%eax, %0;"
    :
    : "m" (Barrier)
    : "memory");
}
#pragma warning( pop )
#define YieldProcessor() __asm__ __volatile__( "rep\n\tnop" );
#endif /* _M_CEE_PURE */
#endif /*_M_IX86*/
在windows sdk中原本長這樣:
#if !defined(MIDL_PASS) && defined(_M_IX86)
#if !defined(_M_CEE_PURE)
#pragma warning( push )
#pragma warning( disable : 4793 )
FORCEINLINE
VOID
MemoryBarrier (
    VOID
    )
{
    LONG Barrier;
    __asm {
        xchg Barrier, eax
    }
}
#pragma warning( pop )
#define YieldProcessor() __asm { rep nop }
#endif /* _M_CEE_PURE */

接下來要調整一下SConstruct檔案。首先找一下 "LIBRARY_FLAGS = {" ,在我的版本中是104行,然後往下找到 "'gcc': {" ,接下來找 "'os:win32': {" ,這裡面原本只有兩行設定:

    'CCFLAGS':      ['-DWIN32'],
    'CXXFLAGS':     ['-DWIN32'],
然後在CXXFLAGS之下加一行 "'LIBS' : ['winmm', 'ws2_32']," ,這樣在連結時才不會出錯。(在我的檔案,這一行會是185行)

另外一個需要調整的是要把 -Werror 選項拿掉,避免因為warning被視為error而無法編譯。找一下 "V8_EXTRA_FLAGS = {" (在我的檔案中的292行),在下面可以找到 "'WARNINGFLAGS'" ,把下面的 "'-Werror" 這行行首加個 "#" 把他註解掉。

另外,在使用scons時,一定要加上visibility=default選項,否則會出現錯誤。

不知道還有沒有遺漏,不過在我的機器上,這樣就可以用MinGW編譯V8了。我的MinGW安裝在D:\MinGW,為了方便修改選項,我寫了一個簡單的batch檔來執行編譯:

 
scons env="INCLUDE:D:\MinGW\include,LIB:D:\MinGW\lib" toolchain=gcc mode=release snapshot=off library=shared visibility=default sample=shell,process,lineprocessor