wxWidgets是一个C++程序开发框架/库, 支持Windows、Mac、Linux中使用相同的代码跨平台开发。它主要用C++写成,但也可以与其他语言绑定比如Python、Perl、Ruby。本教程中我将向你展示如何在基于Debian的linux中如Ubuntu和Linux Mint中编译wxwidgets 3.0+。
从源码编译wxWidgets并不困难,仅仅需要几分钟。库可以按不同的方式来编译,比如静态或者动态库。
1. 下载 wxWidgets
第一步你需要从wxwidgets.org下载wxWidgets源码文件。
做完后,解压到目录。
2. 设置编译环境
要编译wxwidgets,我们需要一些工具包括C++编译器,在Linux上是g++。所有这些可以通过apt-get工具从仓库中安装。
我们还需要wxWidgets依赖的GTK开发库。
$ sudo apt-get install libgtk-3-dev build-essential checkinstall
这个叫做checkinstall的工具允许我们为wxwidgets创建一个安装包,这样之后就可以轻松的使用包管理器来卸载。
3. 编译 wxWidgets
进入到wxWidgets解压后的目录。为了保持清洁,创建一个编译用的目录。
$ mkdir gtk-build
$ cd gtk-build/
现在运行configure和make命令。每个将花费一些时间来完成。
$ ../configure --disable-shared --enable-unicode
$ make
"--disable-shared"选项将会编译静态库而不是动态库。
make命令完成后,编译就成功了。是时候安装wxWidgets到正确的目录。
更多信息请参考install.txt和readme.txt,这可在wxwidgets中的/docs/gtk/目录下找到。
4. 安装 checkinstall
现在我们不使用"make install"命令,我们使用checkinstall命令来创建一个wxwidgets的deb安装包。运行命令:
$ sudo checkinstall
checkinstall会询问几个问题,请保证在提问后提供一个版本号,否则将会失败。
完成这一切后,wxWidgets就安装好了,deb文件也会创建在相同的目录下。
5. 追踪安装的文件
如果你想要检查文件安装的位置,使用dpkg命令后面跟上checkinstall提供的包名。
$ dpkg -L package_name
/.
/usr
/usr/local
/usr/local/lib
/usr/local/lib/libwx_baseu-3.0.a
/usr/local/lib/libwx_gtk3u_propgrid-3.0.a
/usr/local/lib/libwx_gtk3u_html-3.0.a
/usr/local/lib/libwxscintilla-3.0.a
/usr/local/lib/libwx_gtk3u_ribbon-3.0.a
/usr/local/lib/libwx_gtk3u_stc-3.0.a
/usr/local/lib/libwx_gtk3u_qa-3.0.a
/usr/local/lib/libwx_baseu_net-3.0.a
/usr/local/lib/libwxtiff-3.0.a
6. 编译示例
编译wxWidgets完成后就可以马上编译示例程序了。在相同的目录下,一个新的sample目录已经创建了。
进入它并运行下面的命令
$ compile samples
$ cd samples/
$ make
make命令完成后,进入sample 子目录,这里就有一个可以马上运行的Demo程序了。
7. 编译你的第一个程序
你完成编译demo程序后,可以写你自己的程序来编译了。这个也很简单。
假设你用的是C++,这样的话你还可以使用编辑器的高亮特性。比如gedit、kate、kwrite等等。或者用全功能的IDE像Geany、Codelite、Codeblocks等等。
然而你的第一个程序只需要用一个文本编辑器来快速完成。
如下:
#include <wx/wx.h>
class Simple : public wxFrame
{
public:
Simple(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
{
Centre();
}
};
class MyApp : public wxApp
{
public:
bool OnInit()
{
Simple *simple = new Simple(wxT("Simple"));
simple->Show(true);
return true;
}
};
wxIMPLEMENT_APP(MyApp);
现在保存并用下面的命令编译。
# compile
$ g++ basic.cpp `wx-config --cxxflags --libs std` -o program
# run
$ ./program
和非标准的库一起编译
面展示的wx-config命令默认只支持标准的库。如果你使用的是Aui库,那么你需要指定额外用到的库。
$ g++ code.cpp `wx-config --cxxflags --libs std,aui` -o program
更多的信息参考这里这里。
资源
下载wxWidgets的源码和帮助 https://www.wxwidgets.org/downloads/
wxWidgets编译的wiki页面 https://wiki.wxwidgets.org/Compilingandgetting_started
使用wxWidgets最新版本(3.0+)的事项 https://wiki.wxwidgets.org/UpdatingtotheLatestVersionofwxWidgets
安装wxWidgets遭遇的两个问题解解决办法
问题1:编译中“内存耗尽”
按照相关材料的提示,
(1)在PATH变量中加入F:\Program Files\CodeBlocks\MinGW\bin;
(2)打开MS-DOS窗口,将当前目录设置为F:\wxWidgets-2.8.7\build\msw;
(3)运行编译wxWidgets的命令:
编译方法:
mingw32-make -f makefile.gcc MONOLITHIC=1 SHARED=1 UNICODE=1 BUILD=debug
编译很慢。伤心的是,最后出来的结果,提示error。最后两行的提示是:
gcc_mswuddll\monodll_xh_bmpcbox.o: file not recognized: Memory exhausted
collect2.exe: error: ld returned 1 exit status
居然是Memory exhausted!
得不到解释,也想不出道道。换了几次关键词搜索,终于找到了http://www.cnblogs.com/aozima/archive/2011/10/03/2198653.html,其中提到“内存耗尽,是因为32位系统最大只能为应用程序分配2G的内存.”我的系统恰也是32位的。
怎么解决?
解决方法:在编译时加入 -fno-keep-inline-dllexport 参数(内联符号不导出),这样DLL文件也小了,链接时占用内存也小了。
具体步骤:
(1)找开F:\wxWidgets-2.8.7\build\msw中的config.gcc文件;
(2)修改config.gcc中的几个参数:
UNICODE ?= 1
CPPFLAGS ?= -Os -fno-keep-inline-dllexport
LDFLAGS ?= -s
RUNTIME_LIBS ?= static
(3)查看了一下GCC的版本,顺便修改了GCC版本参数
GCC_VERSION ?= 4.7.1
再运行。
顺利,再没有出现Memory exhausted
问题2:连接中缺少文件
利用Code::Blocks提供的向导,生成一个GUI应用,作为体验的开始。
步骤按向导做就行。生成的程序要运行,有不少的问题,参考“CodeBlocks编译wxWidgets设置”,工作得以继续进行。
语法错误就此消除,无非就是头文件找不到之类的。
而挑战,出现在连接阶段。
出现的错误提示是:
ld.exe||cannot find -lwxmsw28d_core|
ld.exe||cannot find -lwxbase28d|
|=== Build finished: 2 errors, 0 warnings (0 minutes, 1 seconds) ===
这是找不到库文件。
然而,这样的库文件在哪儿呢?
查看F:\wxWidgets-2.8.7\lib\gcc_dll中,出现的文件如下:
按搜索到的资料,lwxbase28d要对应libwxbase28d.a,期望的文件不存在。
这时,必须正视编译时运行的命令中的参数了。
编译命令是:
mingw32-make -f makefile.gcc BUILD=release SHARED=1 MONOLITHIC=1 UNICODE=1
搜索得知,设置想要如何编译wxWidgets,要编辑文件confg.gcc,以,其中主要设置了如下选项:
SHARED = 1 编译成动态链接库
UNICODE = 1 使用UNICODE(我是中文用户,当然要它了)
BUILD = release 生成正式发行版
MONOLITHIC = 1 生成单一动态链接库
其实,作为初体验,懒得琢磨这些参数。
换参数BUILD=debug再次编译:
mingw32-make -j2 -f makefile.gcc SHARED=1 BUILD=debug MONOLITHIC=1 UNICODE=1
在F:\wxWidgets-2.8.7\lib\gcc_dll中增加的文件是
干脆,改SHARED=0 BUILD=release再来,运行
mingw32-make -j2 -f makefile.gcc SHARED=0 BUILD=release MONOLITHIC=1
这次,增加了F:\wxWidgets-2.8.7\lib\gcc_lib文件夹,其中的文件是:
将F:\wxWidgets-2.8.7\lib\gcc_lib加入到项目的search directories中,Built项目。令人沮丧的是还有错误,而高兴的是,只有cannot find -lwxbase28d了。
Build Target现在是“Debug”,试着改为“Release”。再Built项目。好事,通过,没有问题。运行,利用向导生成的项目,正确运行!
改回“Debug”,问题依然。我希望我的环境中,能够编译Debug版本的程序,这个问题要解决。
然而,观察发现,BUILD=release时,SHARED=0和SHARED=1的两种情况都已经做过,无论用动态链接库,还是用静态链接库,只要是生成正式发行版(release),现有的库函数都已经具备。而缺少的lwxbase28d嘛,从名称上看,这个d正是debug之意。
于是,修改参数再编译一遍,这次要生成的是支持静态链接的Debug库文件:
mingw32-make -j2 -f makefile.gcc SHARED=0 BUILD=debug MONOLITHIC=1
出现的文件:
迫不急待地运行项目。万岁,Build Target是“Debug”时也正常了。
记录下这个过程。明天开始可以运行wxWidgets自带的Demo了。找到些感觉后,看书,再试着自己写些小程序,适合我的菜鸟学生做的那种。
这个安装过程的经验是:(1)遇到问题不退缩;(2)搞不清和不到搞清参数的时候,就调整参数,多产生些版本出来。其实,好多经验之谈,也是从这种试探中来的。