现在的位置: 首页 > 综合 > 正文

转贴:编译wxWidgets

2014年01月22日 ⁄ 综合 ⁄ 共 9333字 ⁄ 字号 评论关闭

第一章 轻装上阵跨平台

本章的目的是讲述,如何实现在不依赖任何IDE[1]的情况下,使用gcc编译器在Windows、Linux、Mac OS三大平台上编译wxWidgets、wxWidgets的例子,以及利用wxWidgets提供的Bakefile支持来编译自己的wxWidgets程序。本章还涉及到了一些上下游的细节,一些初次尝试者会卡壳的地方。

1.1 为什么要自己编译wxWidgets

为什么要自己编译wxWidgets这么麻烦?wxWidgets为什么不提供一个只需要点“下一步”的安装程序?为什么不提供一个IDE直接就支持wxWidgets,像安装完了VC++直接就能在里面写wxWidgets程序,就能运行,效果直接?

关于第一个和第二个问题,一个很大的原因是wxWidgets是跨平台的,在它作为一个类库发布的时候,你说它提供哪些平台上的安装程序好呢?事实上,wxWidgets主要是以源代码的形式发布的,伴随它的,还有各主要平台上的Makefile,甚至一些主要IDE的工程文件(比如VC的工程,从6.0到2005都有支持),这已经为我们编译它提供了相当的便利了。

倒也有人在做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提供的功能。下一章我将介绍我推荐的IDE和RAD工具——Code::Blocks和wxFormBuilder,它们都是用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

★ 下载wxWidgets的Daily Snapshot

要获得最新的wxWidgets,一个简单点的办法是下载wxWidgets的Daily Snapshot,它是对每天的SVN版本的wxWidgets的一个打包。在http://www.wxwidgets.org/downloads/最下面有一个Daily Snapshot的链接,它会链接到一个文件列表,里面的文件的最后修改日期都是今天。可以下载里面的wxWidgets.zip或wxWidgets.tar.gz,相当于最新的wxAll。而wxWidgets-snapshot.tar.gz这个大家伙,则还包含wxWidgets网站内容、开发者用到的一些脚本,甚至SVN的版本信息——这样一来,你可以在下面这种方法中,省去检出(check out)的一步,直接svn update就可以了。

★ 从SVN trunk中检出(checkout)最新的wxWidgets

上面这种方法中,如果下载的是wxWidgets.zip或wxWidgets.tar.gz,虽然第一次简单,可每次都要重新下载,相当麻烦。另外一个第一次复杂些的办法,是用Subversion从wxWidgets的开发砂箱(trunk)中检出(check out)wxWidgets,以后每次只需要更新那些又被开发团队修改过的文件,这就方便多了。

先要下载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-C,Ada,Java等语言的编译器,更重要的是它构建了一整套程序的“生产流水线”,由各个相对小的程序分工协作,完成程序的最终生成过程。VC在底层所用的工具集,也具有相类似的分工,在MinGW里学到的方法,很容易移植到VC的工具集上。

为什么选择MinGW而不是VC的编译器?主要是觉得从在Windows下就开始用gcc编译,可以更大程度地保证程序可以移植到Linux和Mac下。另外,众所周知,仍被广泛使用的VC6.0的编译器很不支持C++标准。不过,VC2005/2008的Express版是免费下载的,对标准的支持也比较好,如果要选用VC的编译器,选用它们比较好,它们在编译速度和生成的可执行文件大小方面也较MinGW有一定优势。

又为什么不将之与MSYS合在一起使用configure?主要是觉得在Windows下Make就够用了,configure就太Linux化了,而且纯属浪费。而且从GNU make中学到的,可以运用到VC的nmake上。

★ 下载和安装MinGW

http://www.mingw.org/点左边的Download,出现一个好长的英文文章,再在Contents中点Downloads,就到了一段非常短的英文,里面有1个链接Sourceforge File Release,点它就到了MinGW在Sourceforge上的下载页面。如果你喜欢开源软件,以后少不了跟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 4中2007年8月14日4.2.1-sjlj版的下载过程,你可以对整个下载页面做个页面内搜索找到它。(本文写作时已经有更新的Release,但是我还是先写着我熟悉的这个版本,讲解它的细节问题。)这个版本是可以工作在Vista下的,更早的版本则未必。

其中gcc-core和gcc-g++是在GCC Version 4一栏里的,binutils在GNU Binutils一栏里,mingw32-make在 GNU Make一栏里,mingw-runtime在GNU Source-Level Debugger一栏里,w32api 在MinGW API for MS-Windows一栏里, mingw-runtime 在MinGW Runtime一栏里,很简单的一一对应,各自选最新的版本下载吧。

★ MinGW和wxWidgets的环境配置

下载下来的这些tar.gz或tar.bz2包,用WinRAR或7-zip都是可以解压的。把它们都解压到一个文件夹,比如我的就是C:/MinGW。注意,解压出来的结果,应该是在C:/MinGW下出现bin、include、lib、libexec、doc、man、info等文件夹,而不是长得像gcc-core-4.2.1-sjlj-2这样的文件夹。

解压之后,要建一些快捷方式。请进入C:/MinGW/bin,为mingw32-gcc-sjlj.exe和mingw32-g++-sjlj.exe建立分别名为gcc和g++的快捷方式,或者直接把它们复制一份并重命名也可以。这是因为gcc和g++才是它们的标准名字(它们加上了mingw前缀和版本号后缀),如果不这样做,本文后面的makefile就找不到它们了。

接下来设置环境变量。由于我同时使用wxWidgets的2.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/版本号,这下面有cc1和cc1plus,MinGW在有些系统上可能会找不到它们。

接下来我们把这个脚本所在的文件夹加到全局的环境变量中。右击我的电脑[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-平台文本文件,其中平台包括msw(Microsoft Windows的缩写),gtk(Linux下的GTK+框架)和mac(苹果Mac OS)。install就是该平台下编译wxWidgets的指引。在编译之前,最好先看一看。不过它们在记事本下看起来就好像从来不换行一样。这是因为它们是按照linux下的换行方式,比Windows少一个/r,Windows就认不出来哪换行了。不过Word还是认得出来的,用Word来读吧。

INSTALL-MSW.txt 中Basic options 和Advanced options两节是非常重要的,这里面的项可以让你自己根据自己的需要定制wxWidgets。最基本的选项有:

l  UNICODE         如果你需要处理中文,或者你需要unicode,就将它设为1。

l  DEBUG             设为1为debug版(包含调试信息),0为release版(体积小)

l  SHARED           设为1你将来写的wxWidgets程序运行会需要dll(dll 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

为了真的能用OpenGL和ODBC,还需要修改include/msw/setup.h。找到wxUSE_GLCANVAS,修改该行为

#define wxUSE_GLCANVAS 1

找到wxUSE_ODBC,修改该行为

#define wxUSE_ODBC 1

定制完成。

★ 编译wxWidgets

wxWidgets在Windows下用MinGW怎么编译,已经由wxWidgets/build/msw下的makefile.gcc指定清楚了。

确认下C盘有超过1G的硬盘空间(wxWidgets编译需要的硬盘不会超过1G,但是,你C盘空间少于1G,你的系统也不会稳定吧),然后点开命令行提示符,进入wxWidgets/build/msw,依次输入evnset和dbvdll,离开电脑休息半个小时不到,就可以编译出你的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结尾。例如非unicode的release版的静态库,这个子文件夹就是gcc_msw本身,没有任何后缀。而按我们刚刚的编译方法,会有gcc_mswuddll和gcc_mswudll两个子文件夹,里面是大量的.o目标文件和.o.d文件。

编译的真正成果在wxWidgets/lib的子文件gcc_dll(动态库)和gcc_lib(静态库)里。gcc_lib里面会散落着一些.a库文件。gcc_dll里面则散落着一些.a库文件和.dll动态链接库文件。.a的命名规则这里不详述,大家可自行观察。而.dll文件,按我们刚刚的编译方法,会有wxmsw28ud_gcc_cb.dll、wxmsw28ud_gl_gcc_cb.dll、wxmsw28u_gcc_cb.dll、wxmsw28u_gl_gcc_cb.dll四个。注意观察它们的后缀,意义是很明显的。需要说明一下,OpenGL支持,是不会被编译到wxWidgets的那个单一库的dll里而会单独编译为一个dll。

为了这些dll能被将来写的程序调用,我们将它们复制到D:/wxBuildPack中。

另:对sampes的编译如下

(假设我已经创建了 wxWidgets 的library)

就是命令行跑到:

D:/wxWidgets-2.8.10/samples/minimal

下面,然后运行

mingw32-make -f makefile.gcc

呵呵,这样子,对应的exe文件就生成了,我的由于wxWidgets生成的是monolithis的DLL库。

所以对应的exe文件就是:

D:/wxWidgets-2.8.10/samples/minimal/gcc_mswudll/minimal.exe
文件,双击就可以运行了,呵呵。(当然,需要把对应的DLL放到windows 的patch目录里面)

抱歉!评论已关闭.