馳騁wxWidgets系列之輕裝上陣跨平臺[未完成]

Utensil按:這篇文章寫的內容比當初想象的多,花的時間也長,暫時先把目前的進度貼上來。依然不整理走樣的格式。但是,走樣的也太難看了!!-_-| 大家對將來的pdf版要有信心……

第一章 輕裝上陣跨平臺

本章的目的是講述,如何實現在不依賴任何IDE[1]的情況下,使用gcc編譯器在WindowsLinuxMac OS三大平臺上編譯wxWidgetswxWidgets的例子,以及利用wxWidgets提供的Bakefile支持來編譯自己的wxWidgets程序。本章還涉及到了一些上下游的細節,一些初次嘗試者會卡殼的地方。

1.1 爲什麼要自己編譯wxWidgets

爲什麼要自己編譯wxWidgets這麼麻煩?wxWidgets爲什麼不提供一個只需要點“下一步”的安裝程序?爲什麼不提供一個IDE直接就支持wxWidgets,像安裝完了VC++直接就能在裏面寫wxWidgets程序,就能運行,效果直接?

關於第一個和第二個問題,一個很大的原因是wxWidgets是跨平臺的,在它作爲一個類庫發佈的時候,你說它提供哪些平臺上的安裝程序好呢?事實上,wxWidgets主要是以源代碼的形式發佈的,伴隨它的,還有各主要平臺上的Makefile,甚至一些主要IDE的工程文件(比如VC的工程,從6.02005都有支持),這已經爲我們編譯它提供了相當的便利了。

倒也有人在做wxWidgets的打包工作,就我注意到的而言,其中一個是wxPack[2],另外一個是wxWidgets installation wizard[3],而且現在官網上也有了Windows下的Installer。我沒有選擇它們的原因是:我們不應當等待和依賴他人,而應該“自己動手,豐衣足食”,這是一個人起碼的志氣。而且,今天我們學會了(並習慣了)編譯wxWidgets庫,明天就能夠編譯Boost庫、Linux內核等等等等,只要有源碼,我們就能編出最新的庫,編出最新的軟件,還可以邊改邊編,這就是DIY的自在與樂趣。

話雖這麼說,初次嘗試時因爲缺少指引而頻頻遭遇莫名其妙的錯誤實在讓人氣餒,我也曾經歷過這個階段,所幸堅持下來了,沒有放棄對wxWidgets的學習,這也是爲什麼我希望能夠爲初學者們寫一份清晰的指南。

至於第三個問題,就Windows下而言,wxDev-C++是一個不錯的選擇,它自帶MinGW編譯器,也幫你把wxWidgets編譯好了,甚至在你新建一個wxWidgets工程時,幫你寫好了該鏈接的庫。你只需要看着wxWidgets的教程,開始編程,並點菜單編譯,一切都爲你打點好了。但我個人並不推薦wxDev-C++作爲wxWidgets深入開發的IDE——它是用Delphi寫的,只能在Windows下運行,即它不是跨平臺的,而且它的RAD部份也過於像VB的思維,而不是更利於跨平臺開發的Sizer思維,甚至它可能嬌慣你寫出不能跨平臺的代碼,還有,它沒有提供太多我需要IDE提供的功能。下一章我將介紹我推薦的IDERAD工具——Code::BlockswxFormBuilder,它們都是用wxWidgets寫成,好用、開源、跨平臺、免費。

 

1.2 獲得wxWidgets

wxWidgets是以源代碼的形式發佈的。通常我們使用它的穩定版。本文寫作的時候的穩定版是2.8.7,而2.9.0即將推出。如果想試用最新的功能,又不怕它的Bug,可以玩玩最新的wxWidgets

1.2.1 下載最近的穩定版wxWidgets源代碼

http://www.wxwidgets.org/downloads/wxWidgets的下載頁面。看到Current Stable Release一節,裏面有三個小節,第一個小節Source Archives中的wxAll就是我們要下載的,裏面包含了所有平臺的源代碼,還可以選擇不同的壓縮格式,Windows下常見的zip格式,Linux下常見的tar.gz。下載下來後,解壓到某個地方,比如我在Windows下就是C:/,解壓出來會有一個wxWidgets-版本號的文件夾

1.2.2 獲得最新的wxWidgets

下載wxWidgetsDaily Snapshot

要獲得最新的wxWidgets,一個簡單點的辦法是下載wxWidgetsDaily Snapshot,它是對每天的SVN版本的wxWidgets的一個打包。在http://www.wxwidgets.org/downloads/最下面有一個Daily Snapshot的鏈接,它會鏈接到一個文件列表,裏面的文件的最後修改日期都是今天。可以下載裏面的wxWidgets.zipwxWidgets.tar.gz,相當於最新的wxAll。而wxWidgets-snapshot.tar.gz這個大傢伙,則還包含wxWidgets網站內容、開發者用到的一些腳本,甚至SVN的版本信息——這樣一來,你可以在下面這種方法中,省去檢出(check out)的一步,直接svn update就可以了。

SVN trunk中檢出(checkout)最新的wxWidgets

上面這種方法中,如果下載的是wxWidgets.zipwxWidgets.tar.gz,雖然第一次簡單,可每次都要重新下載,相當麻煩。另外一個第一次複雜些的辦法,是用SubversionwxWidgets的開發砂箱(trunk)中檢出(check outwxWidgets,以後每次只需要更新那些又被開發團隊修改過的文件,這就方便多了。

先要下載Subversion,它是一個版本控制工具。

可在http://subversion.tigris.org/project_packages.html#binary-packages 下載到它在各平臺上的可執行文件。其中Ubuntu只需要在終端鍵入命令

apt-get install subversion

Fedora只需要終端鍵入命令:

yum install subversion

安裝之後,可在命令行中輸入svn並回車,如果出來信息叫你輸svn help,就說明你安裝成功了。這時,可將目錄更換到一個你打算放wxWidgets的地方(比如我在Windows下就是D:/SVN),然後輸入命令

svn checkout http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk wxWidgets

就可以了。

下一次你想要更新的wxWidgets,只需要進入wxWidgets所在目錄(對於我是D:/SVN/wxWidgets),並鍵入命令:

svn update

更多的信息,可參見http://www.wxwidgets.org/develop/svn.htm

1.3 Windows (XP/Vista)

1.3.1 安裝MinGW環境

什麼是MinGW

MinGW是一個編譯工具集,對於第一次聽說它的人來說,這個名字可比較嚇人,究竟什麼意思啊?其實,它是Minimal GNU[4] for Window的縮寫,可以理解爲在Windows下用GNU自由軟件最小集合,我們在這裏只使用它的Gcc部份。Gcc全稱是GNU Compiler Collection,它其實不只是C/C++編譯器,還有Objective-CAdaJava等語言的編譯器,更重要的是它構建了一整套程序的“生產流水線”,由各個相對小的程序分工協作,完成程序的最終生成過程。VC在底層所用的工具集,也具有相類似的分工,在MinGW裏學到的方法,很容易移植到VC的工具集上。

爲什麼選擇MinGW而不是VC的編譯器?主要是覺得從在Windows下就開始用gcc編譯,可以更大程度地保證程序可以移植到LinuxMac下。另外,衆所周知,仍被廣泛使用的VC6.0的編譯器很不支持C++標準。不過,VC2005/2008Express版是免費下載的,對標準的支持也比較好,如果要選用VC的編譯器,選用它們比較好,它們在編譯速度和生成的可執行文件大小方面也較MinGW有一定優勢。

又爲什麼不將之與MSYS合在一起使用configure?主要是覺得在WindowsMake就夠用了,configure就太Linux化了,而且純屬浪費。而且從GNU make中學到的,可以運用到VCnmake上。

下載和安裝MinGW

http://www.mingw.org/點左邊的Download,出現一個好長的英文文章,再在Contents中點Downloads,就到了一段非常短的英文,裏面有1個鏈接Sourceforge File Release,點它就到了MinGWSourceforge上的下載頁面。如果你喜歡開源軟件,以後少不了跟Sourceforge打交道,熟悉一下它的界面吧。

上面好長的一個文件列表,下哪個呢?一個最爲簡單的方法是下載個嚮導,它幫你下你需要的,這個嚮導是Automated MinGW Installer,在第一行。我們這裏不採用這個方法,這一方面因爲我個人用它時下得好慢,另外一方面是我喜歡自己動手。

我們主要要下載的東西的關鍵字有:

1.         gcc-core                       GCC的核心

2.         gcc-g++                        GNU C++編譯器

3.         gdb                               GNU調試器

4.         mingw32-make          GNU Make,我們需要它來自動化編譯多文件的程序

5.         mingw-runtime           MinGW運行時環境,包括C頭文件、一些靜態庫、平臺專有起始代碼等。

6.         binutils                          編譯、鏈接等必需的一些工具。

7.         w32api                         Windows API的頭文件和靜態庫,沒有它們根本無法編譯出GUI程序。

8.         mingw-utils                  小工具。

清楚了這些關鍵字之後,我們就可以在大量的文件中開始搜尋。下面我具體講講我使用的GCC Version 420078144.2.1-sjlj版的下載過程,你可以對整個下載頁面做個頁面內搜索找到它。(本文寫作時已經有更新的Release,但是我還是先寫着我熟悉的這個版本,講解它的細節問題。)這個版本是可以工作在Vista下的,更早的版本則未必。

其中gcc-coregcc-g++是在GCC Version 4一欄裏的,binutilsGNU Binutils一欄裏,mingw32-make GNU Make一欄裏,mingw-runtimeGNU Source-Level Debugger一欄裏,w32api MinGW API for MS-Windows一欄裏, mingw-runtime MinGW Runtime一欄裏,很簡單的一一對應,各自選最新的版本下載吧。

MinGWwxWidgets的環境配置

下載下來的這些tar.gztar.bz2包,用WinRAR7-zip都是可以解壓的。把它們都解壓到一個文件夾,比如我的就是C:/MinGW。注意,解壓出來的結果,應該是在C:/MinGW下出現binincludeliblibexecdocmaninfo等文件夾,而不是長得像gcc-core-4.2.1-sjlj-2這樣的文件夾。

解壓之後,要建一些快捷方式。請進入C:/MinGW/bin,爲mingw32-gcc-sjlj.exemingw32-g++-sjlj.exe建立分別名爲gccg++的快捷方式,或者直接把它們複製一份並重命名也可以。這是因爲gccg++纔是它們的標準名字(它們加上了mingw前綴和版本號後綴),如果不這樣做,本文後面的makefile就找不到它們了。

接下來設置環境變量。由於我同時使用wxWidgets2.8.7版本和trunk版本,所以我並不把環境變量設成全局的,而是每次在運行MinGW之前,都運行一個Batch腳本來設置一個暫時的環境。(不太嚴格地沿用C++術語,這叫不想污染全局命名空間,呵呵)

下面是我的Batch腳本,命名爲evnset.bat,放置於D:/wxBuildPack。其中我設了一些參數,你可以根據你的實際情況進行微調。這個腳本已經設置了wxWidgets-2.8.7的所在地。我還有另外一個evnset9.bat,用來設置適用於wxWidgets trunk版本的環境變量。

set MinGW_PATH=C:/MinGW

set MinGW_SubBin=i686-pc-mingw32

set MinGW_Ver=4.2.1-sjlj

set wx_PATH=C:/wxWidgets-2.8.7

 

set PATH=%PATH%;%MinGW_PATH%/bin;%MinGW_PATH%/%MinGW_SubBin%/bin

set LIBRARY_PATH=%MinGW_PATH%/lib;%MinGW_PATH%/lib/gcc/mingw32/%MinGW_Ver%

set C_INCLUDE_PATH=%MinGW_PATH%/include

set CPLUS_INCLUDE_PATH=%MinGW_PATH%/include;%MinGW_PATH%/lib/gcc/mingw32/%MinGW_Ver%/include;%MinGW_PATH%/lib/gcc/mingw32/%MinGW_Ver%/include/c++;%MinGW_PATH%/lib/gcc/mingw32/%MinGW_Ver%/include/c++/backward;%wx_PATH%/include;%wx_PATH%/contrib/include;

這個腳本臨時地設置了PATH(系統到哪裏去找可執行文件)、LIBRARY_PATH(系統到哪裏去找需要的庫文件),C_INCLUDE_PATH(系統到哪裏去C頭文件)、CPLUS_INCLUDE_PATH(系統到哪裏去C++頭文件)。

如果你下載的是不同版本的gcc,你需要自行檢查MinGW內部的文件夾結構是否像上面這個腳本所勾勒的一樣,你可能需要根據實際情況加以調整。同時注意一下libexec/gcc/mingw32/版本號,這下面有cc1cc1plusMinGW在有些系統上可能會找不到它們。

接下來我們把這個腳本所在的文件夾加到全局的環境變量中。右擊我的電腦[5],屬性[6],高級,環境變量。在用戶變量或者系統變量中找到PATH,然後編輯,在所有其他路徑的最後面,先加上;作爲分隔符,然後加上D:/wxBuildPack(我們剛剛放evnset.bat的文件夾)。最後,一路確定,環境變量就設好了。

現在測試一下:開始,運行。輸入cmd,這樣彈出命令行提示符窗口,輸入evnset,如果顯示出了腳本中的那一大堆命令,就說明大環境搭好了。注意,evnset所設置的路徑,只作用於當前窗口,如果你另開一個窗口,你需要重新evnset。你可以試着用它編譯一個最簡單的HelloWorld程序了。假設當前目錄下你的HelloWorld源文件爲main.cpp,內容爲:

#include <iostream>

using namespace std;

int main()

{

cout << "Hello World!" << endl;

cin.get();

return 0;

}

在運行完evnset後,輸入

g++ main.cpp –o main.exe

就應該能生成一個main.exe了。

1.3.2 編譯wxWidgets

定製wxWidgets

你可能已經注意到,在wxWidgets的根目錄,散落着一些readme-平臺install-平臺文本文件,其中平臺包括mswMicrosoft Windows的縮寫),gtkLinux下的GTK+框架)和mac(蘋果Mac OS)。install就是該平臺下編譯wxWidgets的指引。在編譯之前,最好先看一看。不過它們在記事本下看起來就好像從來不換行一樣。這是因爲它們是按照linux下的換行方式,比Windows少一個/rWindows就認不出來哪換行了。不過Word還是認得出來的,用Word來讀吧。

INSTALL-MSW.txt Basic options Advanced options兩節是非常重要的,這裏面的項可以讓你自己根據自己的需要定製wxWidgets。最基本的選項有:

l  UNICODE         如果你需要處理中文,或者你需要unicode,就將它設爲1

l  DEBUG             設爲1debug版(包含調試信息),0release版(體積小)

l  SHARED           設爲1你將來寫的wxWidgets程序運行會需要dlldll 10M左右,你的程序自身大小就很小,可能只有幾百k),0則可以獨立運行,但自身體積起碼是M

l  MONOLITHIC         設爲1則將wxWidgets編譯爲一個單一的大的庫文件,0則將其內部一個個小庫分別編譯,得到的是很多個小的庫文件。建議設爲1,這樣鏈接庫的時候方便。如果你對最終發佈的程序有體積要求,或者希望精細地選擇鏈接什麼不了鏈接什麼,可以設爲0

 

下面講講我自己的定製。

我的基本需求是,要能用XRC,能用OpenGL,能用ODBC,能用中文,用dll。在編譯之前,我先寫兩個簡單Batch腳本,分別爲我編譯的debug版本和release版本的wxWidgets。這兩個腳本以後編自己的wxWidgets程序依然有用。

第一個腳本名爲dbvdll.bat,意爲debug  version的動態庫,也放置於D:/wxBuildPack

mingw32-make -f makefile.gcc USE_XRC=1 USE_OPENGL=1 USE_ODBC=1 SHARED=1 MONOLITHIC=1 BUILD=debug UNICODE=1 clean

mingw32-make -f makefile.gcc USE_XRC=1 USE_OPENGL=1 USE_ODBC=1 SHARED=1 MONOLITHIC=1 BUILD=debug UNICODE=1 VENDOR=cb

第一行命令是清空以前的編譯殘留下來的.o目標文件和.o.d文件,它們的存在可能使編譯結果不正確。

第二行命令是正式編譯,注意VENDOR=cb這一句,這意味着編出來的dll會有一個_cb的後綴。你可以把它改成自己的名字、自己的公司名什麼的。我用的cb是指Code::Blocks

接下來是rlvdll.bat,意爲release  version的動態庫,大同小異:

mingw32-make -f makefile.gcc USE_XRC=1 USE_OPENGL=1 USE_ODBC=1 SHARED=1 MONOLITHIC=1 BUILD=release UNICODE=1 clean

mingw32-make -f makefile.gcc USE_XRC=1 USE_OPENGL=1 USE_ODBC=1 SHARED=1 MONOLITHIC=1 BUILD=release UNICODE=1 VENDOR=cb

爲了真的能用OpenGLODBC,還需要修改include/msw/setup.h。找到wxUSE_GLCANVAS,修改該行爲

#define wxUSE_GLCANVAS 1

找到wxUSE_ODBC,修改該行爲

#define wxUSE_ODBC 1

定製完成。

編譯wxWidgets

wxWidgetsWindows下用MinGW怎麼編譯,已經由wxWidgets/build/msw下的makefile.gcc指定清楚了。

確認下C盤有超過1G的硬盤空間(wxWidgets編譯需要的硬盤不會超過1G,但是,你C盤空間少於1G,你的系統也不會穩定吧),然後點開命令行提示符,進入wxWidgets/build/msw,依次輸入evnsetdbvdll,離開電腦休息半個小時不到,就可以編譯出你的debug版本的wxWidgets了,再輸入rlvdll,就可以把release版本的也編譯出來。以我自己編譯2.8.7爲例:

C:/Users/Utensil> cd C:/wxWidgets-2.8.7/build

C:/wxWidgets-2.8.7/build> evnset

[一長串輸出略]

C:/wxWidgets-2.8.7/build> dbvdll

[編譯時輸出略]

C:/wxWidgets-2.8.7/build> rlvlll

[編譯時輸出略]

編譯成果

編了那麼久,究竟編出了什麼東西來啊?

編譯的副產品在wxWidgets/build/msw的以gcc_msw開頭的子文件夾裏。如果編譯的是unicode版本,後綴會以u開頭;如果編譯的是debug版本,接下來會有一個d;如果編譯的是動態庫,會以dll結尾。例如非unicoderelease版的靜態庫,這個子文件夾就是gcc_msw本身,沒有任何後綴。而按我們剛剛的編譯方法,會有gcc_mswuddllgcc_mswudll兩個子文件夾,裏面是大量的.o目標文件和.o.d文件。

編譯的真正成果在wxWidgets/lib的子文件gcc_dll(動態庫)和gcc_lib(靜態庫)裏。gcc_lib裏面會散落着一些.a庫文件。gcc_dll裏面則散落着一些.a庫文件和.dll動態鏈接庫文件。.a的命名規則這裏不詳述,大家可自行觀察。而.dll文件,按我們剛剛的編譯方法,會有wxmsw28ud_gcc_cb.dllwxmsw28ud_gl_gcc_cb.dllwxmsw28u_gcc_cb.dllwxmsw28u_gl_gcc_cb.dll四個。注意觀察它們的後綴,意義是很明顯的。需要說明一下,OpenGL支持,是不會被編譯到wxWidgets的那個單一庫的dll裏而會單獨編譯爲一個dll

爲了這些dll能被將來寫的程序調用,我們將它們複製到D:/wxBuildPack中。


[1] Integrated Development Evironment,綜合開發環境,例如Visual C++

[4] GNU 工程創始於一九八四年,旨在開發一個類似 Unix ,且爲自由軟件的完整的操作系統:GNU 系統。GNU 的內核尚未完成,所以 GNU 使用 Linux 作爲其內核。GNU Linux 以這樣的方式組合成爲 GNU/Linux 操作系統,目前有數百萬用戶。GNULinux世界大多數基本自由軟件的來源。

[5] Vista下叫計算機

[6] Vista下還要在彈出來的控制面板窗口中點一下“改變設置”,這個需要管理員權限

發佈了37 篇原創文章 · 獲贊 2 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章