Sep 23

汇编语言是一种最贴近机器硬件、运行效率很高的低级编译型语言。由于它与硬件紧密相关,因此它的开发完全受平台限制,所开发的程序代码基本上不具有移植性。当然,只要硬件(主要是中央处理器)相近,那就有可能在不同平台上采用同一套汇编语言编程工具进行程序开发。MSYS2 是 GCC 工具链在 MS Windows 平台上极为成功的移植!利用 MSYS2 提供的编程工具,就可以通过 C/C++/Python 等编程语言在 MS Windows 平台上进行原生程序开发。这既可以借鉴 GNU Linux 平台上优秀开源软件的成功开发经验,还可以将这些优秀的软件移植到 MS Windows 平台。不过,这里要介绍的是如何利用 MSYS2 中基于 MinGW x64 工具链提供的 GNU as 与 ld 工具进行 64 位 GNU 汇编(也即采用 AT&T 语法)程序的开发。

先来看一个示例,它主要通过指令 call 调用了标准 C 函数(比如 printf、exit 等):

    /* test.s */
    .section .rodata
msg: .asciz "Hello, MSVC Library!"
    .section .text
    .global _start
_start:
    # align RSP
    push %rbp
    mov %rsp, %rbp
    sub $0x20, %rsp

    lea msg(%rip), %rcx
    call printf

    xor %eax, %eax
    call exit

上述汇编源代码在 MSYS2 环境下的编译以及运行过程是这样的:

$ as -o test.o test.s
$ ld -o test.exe test.o -lmsvcrt
$ ./test.exe

为了正确编写 GNU 汇编源代码,除了熟悉 AT&T 汇编语法与 Amd64 指令集之外,特别需要了解 MS Windows x64 的调用协定(FASTCALL 的一种变体)、MS Windows C/C++ 运行库,请参看 https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170、https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170。有一点要特别强调一下:微软的 C 运行时库中还存在着一些以单下划线开头并跟有标准 C 函数名的接口(比如 _printf、_exit 等),这些接口是微软实现的但并不是标准 C 函数,不同版本的 MS Windows 中的 C 运行时库(例如 msvcrt 等)可能提供了标准 C 接口,也可能提供了微软的扩展接口,或者两者兼有,或者只有其中之一。

再来看如何调用 MS Windows 的应用程序编程接口?

    /* test.s */
    .section .rodata
msg:
    .asciz "Hello, Win32 ASM World"
    len = .-msg
    .section .text
    .global _start
_start:
    # align RSP
    push %rbp
    mov %rsp, %rbp
    sub $0x20, %rsp

    # https://learn.microsoft.com/en-us/windows/console/getstdhandle
    # get handle for standard I/O
    # GetStdHandle(STD_OUTPUT_HANDLE)
    mov $-11, %rcx
    call GetStdHandle

    # https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
    # WriteFile(hstdOut, msg, len, &bytes, 0)
    mov %rax, %rcx
    lea msg(%rip), %rdx
    mov $len, %r8
    lea -0x20(%rbp), %r9
    push $0
    call WriteFile

    # https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess
    # exit with zero
    # ExitProcess(0)
    xor %ecx, %ecx
    call ExitProcess

上述源代码在 MSYS2 环境下的编译以及运行过程如下:

$ as -o test.o test.s
$ ld test.o -lkernel32 -o test.exe
$ ./test.exe

上面的汇编代码中用到了 Windows 应用程序编程接口中最重要的动态链接库:Kernel32.dll (包含那些用于管理内存、进程和线程的函数,例如 GetStdHandle、WriteFile、ExitProcess 等函数)。另一个值得一提的是:User32.dll(包含那些用于执行用户界面任务的函数,例如 MessageBoxA 等 函数)。如果想生成对话框程序,可试试下述汇编代码

    /* test.s */
    .section .rodata
mba_msg:
    .asciz "Hello ASM world!"
mba_title:
    .asciz "Simple Message Box"
    .section .text
    .globl _start
_start:
    # align RSP
    push %rbp
    mov %rsp, %rbp
    sub $0x20, %rsp 

    # https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxa
    # display a message box
    # MessageBoxA(NULL, mba_msg, mba_title, MB_ICONINFORMATION)
    xor %ecx, %ecx
    lea mba_msg(%rip), %rdx
    lea mba_title(%rip), %r8
    mov $0x40, %r9d
    call MessageBoxA
 
    # ExitProcess(0)
    xor %ecx, %ecx
    call ExitProcess

它的编译与执行过程如下:

$ as -o test.o test.s
$ ld test.o -lkernel32 -luser32 -o test.exe
$ ./test.exe

MS Windows 的应用程序编程接口被分为两种:一种是遵循 Win32 时代的应用程序编程接口,这部分被称为本地应用程序编程(Native API);另一种则是以 .NET Framework 为基础开发的,称为 Managed API。本地应用程序编程接口(https://learn.microsoft.com/en-us/windows/win32/api/) 以二进制方式发布、供 C/C++ 程序直接调用。这些本地应用程序开发接口的名称大多以 Nt/Zw 开头,而所有系统调用都以字母 Nt 开头。换而言之,MS Windows 的系统调用是本地应用程序编程(Native API)的子集。来看一下 Linux 与 MS Windows 的应用程序编程接口对照表(https://www.cnblogs.com/UnGeek/p/2981439.html):

如果 GNU 汇编代码中调用了 Nt/Zw 开头的 MS Windows 应用程序编程接口,那么只需在使用 GNU 链接器时增加 -lntdll 选项。

实际上,GCC 工具链为 GNU 汇编语言提供了第三代系统调用指令 syscall,若想通过它调用 MS Windows 的系统调用,那就需要提前知道相应的系统调用号。然而 MS Windows 并没有提供任何相关细节,好在已有开发者对动态库 NTDLL.dll 进行了逆向工程,得到了有关每个 Windows 内核的部分系统调用号的一些非官方信息:

  • https://github.com/ikermit/11Syscalls
  • https://j00ru.vexillium.org/syscalls/nt/64/
  • http://j00ru.vexillium.org/syscalls/win32k/64/
  • https://github.com/j00ru/windows-syscalls

请注意,即使是在 MS Windows 10 的不同版本之间,MS Windows 的同一个系统调用的调用号也会发生变化。

/* NtCreateThreadEx on Windows 10 (1511) */
mov %rcx, %r10
mov $0xB4, %rax
syscall

有关 Win32 汇编的基础知识,可参考 https://www.cnblogs.com/LyShark/p/11136319.html。还有一点值得提到的是,通过 MinGW64 制作 MS Windows 上动态库(DLL)的方法,它与 Linux 稍有不同,请参考 https://nullprogram.com/blog/2021/05/31/。

Feb 19

GTK+ 是一套跨平台的图形用户界面(Graphical User Interface)开发工具包,按 LGPL 许可协议发布的。此地介绍一下 GTK+ 开发工具包在 MS Windows 上的安装配置。

〇、预备工作

由于 GTK+ 是由 C 语言开发,因此要开发 GTK+ 应用程序,首先需要配置好 C 编译环境。在 MS Windows 平台,C 编译器的选择很多,主流的有 MSVC、GCC 的移植版本 MinGW 与 Cygwin。由于 GTK+ 是 GNU 项目,因此,这里推荐使用 GNU 的编译器,当然并不是说不能使用其他 C 编译器,这完全取决于个人喜好。MinGW 的下载与安装参考其官方网站 http://www.mingw.org 的说明。由于 MinGW 最初是 32 位,近年来,TDM-GCC 推出了 MinGW 的 64 位版本,详见其官方主页 http://tdm-gcc.tdragon.net/。至于 Cygwin,请到它的官方网站 http://www.cygwin.com/ 了解详情。在 Cygwin 与 MinGW 两者之间,一般推荐 MinGW 作为 C/C++ 编译工具链,除非需要在 MS Windows 平台上开发 Unix/Linux 应用程序。当然,在 MS Windows 平台上开发大型应用程序,少不得使用集成开发环境。集成开发环境也有很多选择,例如 MSVS、Code::Blocks、QtCreator 等。下面的介绍中使用的 Code::Blocks,请到其官网 http://codeblocks.org 下载最新版本(留意 Code::Blocks 的安装包是否已带有 MinGW)。

一、下载与配置 GTK+ 开发包

在 MS Windows 中安装 GTK+ 有多种选择,可利用 Cygwin 或 MinGW 工具自行由源码编译 GTK+ 工具包,不过要解决 GTK+ 依赖,工程相对浩大。目前,GTK+ 官方推荐利用 MSYS2(官网地址为 http://msys2.github.io)提供的包管理器 pacman 来自动完成 GTK+ 的编译与安装。这些 GTK+ 安装方法的共同特点是,安装过程都会顺带安装预备工作中提到的编译器。为了与预备工作中相衔接,这里直接利用预编译的 GTK+ 集成开发包来完成它们安装。

虽然预编译的集成开发包有些陈旧,集成开发包有些陈旧,但好处也是明显地,它包含了所有开发与运行 GTK+ 应用程序的头文件与库文件。需要 GTK+ 2 的用户,可到 http://ftp.gnome.org/pub/GNOME/binaries/ 下载 32 位的集成开发包 gtk+-bundle_2.24.10-20120208_win32.zip 或 64 位的集成开发包 gtk+-bundle_2.22.1-20101229_win64.zip;需要 GTK+ 3 的用户,可到 http://win32builder.gnome.org/ 下载 32 位的集成开发包 gtk+-bundle_3.10.4-20131202_win32.zip 或 64 位的集成开发包 gtk+-bundle_3.10.4-20131202_win64.zip。它们的安装非常简单,只需要将这些压缩包解压缩即可,一般建议将它们安装磁盘的根目录(如 C:\GTK+-2.12C:\GTK+-3.10),但不推荐安装到 MS Windows 的应用程序文件夹。为了能够使用 GTK+ 提供的 pkg-config 来配置 GCC 的编译、链接选项,还需配置环境变量 PATH。只需在 MS Windows 的文件管理器中鼠标右击 "My Computer" -> "Properties" -> "Advanced system settings" -> "Environment variables",接着双击 "System variables" 页面中的 PATH 行,将 GTK+ 目录中的 bin 路径(如 ;C:\GTK+-2.12\bin;C:\GTK+-3.10\bin)添加到原 PATH 变量的末尾。命令行操作也可完成 PATH 的设置,也即打开命令行窗口(CMD.exe),然后执行

> setx PATH "%PATH%;C:\GTK+-2.12\bin"

或者

> setx PATH "%PATH%;C:\GTK+-3.10\bin"

设置好环境变量 PATH 之后,可选择性的做下述设置

> pango-querymodules > C:\GTK+-2.12\etc\pango\pango.modules
> gdk-pixbuf-query-loaders > C:\GTK+-2.12\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
> gtk-query-immodules-2.0 > C:\GTK+-2.12\lib\gtk-2.0\2.12.11\immodules.cache

二、开发环境的测试与 Code::Blocks 的整合

在正式开始 GTK+ 开发工作之前,要确保 GTK+ 环境配置的正确性,为此还需做一些简单的测试。前述 GTK+ 集成开发包带有 GTK+ 的开发演示文档,可到相应目录查找。此地,以命令行方式演示一个由 GTK+ 2 开发简单应用的例子:

> notepad.exe hellogtk.c

#include <gtk/gtk.h>

int main(int argc, char *argv[])
{
    GtkWidget *window;
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), "destroy",
    G_CALLBACK(gtk_main_quit), NULL);

    gtk_widget_show(window);
    gtk_main();
    return 0;
}

现在在 MinGW Shell 中执行

> gcc hellogtk.c -o hellogtk.exe `pkg-config --cflags --libs gtk+-2.0`

一切正常的话,会在 hellogtk.c 所在目录生成一个可执行文件 hellogtk.exe,鼠标双击运行它。

要开发一个大型的 GTK+ 程序,除了使用 Makefile 管理源代码文件之外,使用集成开发环境是方便的。下面以 Code::Blocks 作为集成开发环境演示如何进行 GTK+ 的开发工作,而这仅需搞清楚如何在 Code::Blocks 中配置 GTK+ 的库文件与头文件路径,当然有很多方法达到这个目的,这里只给出针对 GTK+ 工程相关的配置方法。为此,先按下述操作新建一个 GTK+ 工程:启动 Code::Blocks,点击 "File" -> "New" -> "GTK+ Project" 创建一个 GTK+ 2 项目。下面点击该工程对应的菜单 "Project" -> "build options" 子标签。下面从简到烦介绍三种在 GTK+ 工程属性中配置 GTK+ 开发环境的方法:

1、利用 pkg-config 直接设置编译选项与链接选项

由于 pkg-config 已在 PATH 中,故而 GTK+ 的编译选项与链接选项的设置非常简捷,只需在 "Project build options "-> "Compiler settings" -> "Other Compiler options" 中增加编译选项设置 pkg-config --cflags gtk+-2.0;再在 "Project build options" -> "Linker settings" -> "Other linker options" 增加链接选项为 pkg-config --libs gtk+-2.0

2、利用 pkg-config 的输出设置编译选项与链接选项

2.1、设置编译选项。先在命令行窗口(CMD.exe) 中执行

> pkg-config --cflags gtk+-2.0
-mms-bitfields -IC:/GTK+-2.12/include/gtk-2.0 -IC:/GTK+-2.12/lib/gtk-2.0/include -IC:/GTK+-2.12/include/atk-1.0 -IC:/GTK+-2.12/include/cairo -IC:/GTK+-2.12/include/pango-1.0 -IC:/GTK+-2.12/include/glib-2.0 -IC:/GTK+-2.12/lib/glib-2.0/include -IC:/GTK+-2.12/include/libpng12

然后开启 Code::Blocks,将 -mms-bitfields -IC:/GTK+-2.12/include/gtk-2.0 -IC:/GTK+-2.12/lib/gtk-2.0/include -IC:/GTK+-2.12/include/atk-1.0 -IC:/GTK+-2.12/include/cairo -IC:/GTK+-2.12/include/pango-1.0 -IC:/GTK+-2.12/include/glib-2.0 -IC:/GTK+-2.12/lib/glib-2.0/include -IC:/GTK+-2.12/include/libpng12 拷贝到 "Project build options" -> "Compiler settings" -> "Other Compiler options";

2.2、设置链接选项。在命令行窗口(CMD.exe) 中执行

> pkg-config --libs gtk+-2.0
-LC:/GTK+-2.12/lib -lgtk-win32-2.0 -lgdk-win32-2.0 -latk-1.0 -lgio-2.0 -lgdk_pixbuf-2.0 -lpangowin32-1.0 -lgdi32 -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lintl

然后将 -LC:/GTK+-2.12/lib -lgtk-win32-2.0 -lgdk-win32-2.0 -latk-1.0 -lgio-2.0 -lgdk_pixbuf-2.0 -lpangowin32-1.0 -lgdi32 -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 -lintl 拷贝到 "Project build options" -> "Linker settings" -> "Other linker options"。

3、将搜索路径、编译选项、链接选项分开设置

3.1、设置编译选项。在 "Project build options" -> "Compiler settings" -> "Other Compiler options" 加入编译选项 -mms-bitfields

3.2、设置链接选项与库文件。在 "Project build options" -> "Linker settings" -> "Link libraries" 中将 GTK+ 2 库的所有库文件(动态库或者静态库)加入,也即点击 ADD 按钮后弹出的文件选择对话框中将 atk-1.0cairogdi32gdk-win32-2.0gdk_pixbuf-2.0gio-2.0glib-2.0gmodule-2.0gobject-2.0gtk-win32-2.0intlpango-1.0pangowin32-1.0pangocairo-1.0 逐一加入;在 "Project build options" -> "Linker settings" -> "Other linker options" 中加入链接选项 -mwindows

3.3、设置搜索目录。在 "Project build options" -> "Search directories" -> "Compiler" 子标签中加入 GTK+ 2 的头文件路径:C:\GTK+-2.12\include\atk-1.0C:\GTK+-2.12\include\cairoC:\GTK+-2.12\include\glib-2.0C:\GTK+-2.12\include\gtk-2.0C:\GTK+-2.12\include\libpng12C:\GTK+-2.12\include\pango-1.0C:\GTK+-2.12\lib\glib-2.0\includeC:\GTK+-2.12\lib\gtk-2.0\include。一般来说就这些,如果安装了新的库再加。若上一步的 "Link libraries" 已带有绝对路径,就不必设库文件的搜索路径了;如若不然,还需在 "Project build options" -> "Search directories" -> "Linker" 子标签中加入库文件路径,也即 C:\GTK+-2.12\lib

介绍第三种比较麻烦的配置方法的目的是让那些使用 MSVC 作为编译工具的用户看清楚如何配置 GTK+ 开发环境。

三、GTK+ 程序界面的快速构建工具

Glade 用来为 GTK+ 和 GNOME 程序快速地设计图形用户界面,并自动生成图形界面的 C 源代码。历史上,Glade 有三个版本,不过目前主要的是 Glade2 与 Glade3,推荐使用 Glade3。Glade2 和 Glade3 的主要区别是: Glade2 会自动生成 makefile 等文件,而 Glade3 只是用来生成界面,然后采用 Libglade 和 GtkBuilder 格式调用 .glade 文件,这样的好处是代码和界面完全分开,避免代码的改变又需要重新编译。与 GTK+ 类似,在 MS Windows 中安装 Glade 的方法很多种,如前,此地直接利用预编译的 Glade 工具包。安装方法很简单,到 http://ftp.gnome.org/pub/GNOME/binaries/ 下载安装包 glade3_3.8.1-1_win32.zip 即可,由于 Glade 是来生成布局文件的,因此无须在意是否是 32 位还是 64 位。当然,为了避免在运行时出现依赖错误,也可安装带有完整 GTK+ 库的版本,例如 glade3-3.6.7-with-GTK+.exe。若使用 Libglade 格式的布局文件,还需调用 libglade 库,为此安装 libglade 库,也即到 http://ftp.gnome.org/pub/GNOME/binaries/下载 32 位安装包 libglade-dev_2.6.4-1_win32.zip 或 64 位安装包 libglade-dev_2.6.3-1_win64.zip 即可;并假设 Glade 的安装目录均在 C:\Glade,据此设置环境变量 PKG_CONFIG_PATH,也即在命令行窗口(CMD.exe) 中执行

> setx  PKG_CONFIG_PATH "%PKG_CONFIG_PATH%;C:\Glade\lib\pkgconfig"

接着试试下述命令行

> pkg-config --modversion libglade-2.0

看是否有版本信息输出?若找不到该命令,就需要重启电脑;若有,说明系统变量设置正确。

四、GTK+ 的 C++ 开发包的安装与配置

GTKmm 便是 GTK+ 的 C++ 开发包。与 GTK+ 类似,在 MS Windows 中安装 GTKmm 有多种选择,如前,这里直接利用预编译的 GTKmm 开发包包来完成安装,不过需要注意,它是以 GTK+ 包的安装为前提,要预先配置好 GTK+ 才行。从 http://ftp.gnome.org/pub/GNOME/binaries/ 下载 32 位的 GTKmm 开发包 gtkmm-win32-devel-2.22.0-1.exe 或者 64 位的 GTKmm 开发包 gtkmm-win64-devel-2.22.0-1.exe,然后点击它们安装即可,假设安装目录是 C:\GTKmm-2.22。在使用 GTKmm 之前,还需设置系统变量,打开命令行窗口(CMD.exe) ,执行:

> setx PKG_CONFIG_PATH "%PKG_CONFIG_PATH%;C:\GTKmm-2.22\lib\pkgconfig"

在打开命令行窗口(CMD.exe)中再试试

> pkg-config --modversion gtkmm-2.4

若一切正常,可以简单测试一下 GTKmm 是否正常工作?在 MinGW Shell 中,执行下述命令行

> notepad.exe hellogtkmm.cpp

/*Gtkmm程序的基本头文件,下面用到的两个类就由它定义*/
#include <gtkmm.h>

int main (int argc, char *argv[])
{
   /* 
   每一个Gtkmm应用程序都必须有这样一个类的实例,并且必需是第一个生成的Gtk对象。
   它对环境进行必要的初始化,需要用 argc 和 argv 两个参数对它进行实例化。
   */
   Gtk::Main app(argc, argv);
   
   /* 定义一个GTK的窗口类,默认地它以可执行程序名作为窗口标题。*/
   Gtk::Window main_win;
   
   /* 显示窗口,并进入监听事件的循环状态,当窗口关闭时返回。*/
   app.run(main_win);
   
   return 0;
}

> g++ hellogtkmm.cpp -o hellogtkmm `pkg-config --cflags --libs gtkmm-2.4`
> hellogtkmm.exe

附录

MS Visual C/C++(MSVC) 是由 Mirosoft 公司在 MS Windows 操作系统开发的 C/C++ 编译器,目前对应的集成开发环境是 MS Visual Studio(MSVS)。因此,开发 GTK+,使用 MSVS 也是一个不错的选择,这里介绍一下如何利用 MSVS(或 MSVC)进行开发工作。

先来说说在命令行环境中测试 GTK+ 开发环境的方法。通常,安装完 MSVS 之后,并不会将 MSVC 的命令行路径加入到系统环境变量 PATH 之中,但 MSVS 带有配置好环境变量 PATH 的 MSVS 命令行提示窗口。因此,要使用 MSVC 命令行,可在启动 MSVS 之后调用 MSVS 命令行提示窗口,也即启动 MSVS -> "Open the Visual Studio Command Prompt",在打开的命令行窗口中试试 pkg-config 的输出 :

> pkg-config --cflags gtk+-2.0

若一切正常的话,将这些选项保存下来,并删去其中 -mms-bitfields,并在末尾增加 -Dinline= /link /libpath:C:\GTK+-2.12\lib gtk-win32-3.0.lib gobject-2.0.lib。例如编译前述 hellogtk.c,在 MSVS 命令行提示窗口中执行

> cl hellogtk.c -IC:/GTK+-2.12/include/gtk-2.0 -IC:/GTK+-2.12/lib/gtk-2.0/include -IC:/GTK+-2.12/include/atk-1.0 -IC:/GTK+-2.12/include/cairo -IC:/GTK+-2.12/include/pango-1.0 -IC:/GTK+-2.12/include/glib-2.0 -IC:/GTK+-2.12/lib/glib-2.0/include -IC:/GTK+-2.12/include/libpng12 -Dinline= /link /libpath:C:/GTK+-2.12/lib gtk-win32-3.0.lib gobject-2.0.lib

其中 "gtk-win32-3.0.lib gobject-2.0.lib" 是编译 GTK+ 应用程序最少的链接选项要求;更多的链接选项请执行

> pkg-config --libs gtk+2.0

之后,自行添加需要的 .lib 项。

跟以往一样,开发大型程序,还是使用集成开发环境比较好。不过 MSVS 并没有提供 GTK+ 工程向导,因此只能通过在 MS Visual Studio 中新建一个空的 C++ 项目,然后在该项目的工程属性中配置 GTK+ 所需要的编译、链接参数。具体来说,

1、配置头文件搜索目录:鼠标右键新建的 C++ 工程属性->配置属性->C++目录->包含目录,把下述目录 C:\GTK+-2.12\include\atk-1.0C:\GTK+-2.12\include\cairoC:\GTK+-2.12\include\glib-2.0C:\GTK+-2.12\include\gtk-2.0C:\GTK+-2.12\include\libpng12C:\GTK+-2.12\include\pango-1.0C:\GTK+-2.12\lib\glib-2.0\includeC:\GTK+-2.12\lib\gtk-2.0\include 添加进去。

2、配置库文件搜索目录,鼠标右键新建的 C++ 工程属性->配置属性->C++目录->库目录,把 C:\GTK+-2.12\lib 目录添加进去;

3、配置附加依赖项, C++ 工程属性->配置属性->链接器->输入->附加依赖项,把 atk-1.0.libcairo.libgdi32.libgdk-win32-2.0.libgdk_pixbuf-2.0.libgio-2.0.libglib-2.0.libgmodule-2.0.libgobject-2.0.libgtk-win32-2.0.libintl.libpango-1.0.libpangowin32-1.0.libpangocairo-1.0.lib 等项添加进去,注意每项要换行。

要注意,不同的 GTK+ 版本,每个链接项的版本可能不同,请根据 pkg-config 的输出自行调整。

Nov 7

一、Python 的安装

众所周知,目前 Python 有两个分支,也即 Python2 与 Python3。尽管从版本号上看,后者是前者的更新版本,但可惜的是 Python3 不完全兼容 Python2。这就导致了众多使用 Python 的 Linux 系统中需要安装两套 Python 工具。在 MS Windows 中存在同样的问题,不过由于 MS Windows 系统本身不依赖于 Python,因此,安装哪个版本的 Python 取决于使用的 Python 应用程序的依赖关系了。如果作为全新的 Python 开发环境,安装哪个版本的 Python 都无所谓。

安装 Python2 与 Python3 的方法几乎是一样的。例如,要安装 Python2(当前版本是 2.7.10),先到它的官方网站 http://www.python.org 下载安装包

> wget --no-check-certificate https://www.python.org/ftp/python/2.7.10/python-2.7.10.amd64.msi

然后将它安装到 C:\Python27 目录。再如安装 Python3(当前版本是 3.5.0)完全类似,先到它的官方网站 http://www.python.org 下载安装包

> wget --no-check-certificate https://www.python.org/ftp/python/3.5.0/python-3.5.0.amd64.msi

然后将它安装到 C:\Python35 目录。请注意,为了防止 MS Windows 升级过程中影响 Python 的使用,一般不建议将 Python 安装到 MS Windows 系统的应用程序文件目录 %PROGRAMFILES% 中。这就是为什么将 Python 安装到磁盘根目录的原因。

Python 安装完毕之后,需要它们的可执行目录添加到 MS Windows 的 PATH 环境变量中。例如

> setx PATH "%PATH%;C:\Python27;C:\Python27\Scripts"

其中 C:\Python27 里存放的是 Python 解释器;而 C:\Python27\Scripts 则提供了很多工具。现在打开 CMD.EXE 窗口,试试下述命令查看 Python 版本以确认否正常工作

> python.exe -V

一切正常的话,可以进入 Python 解释器了

> python.exe
>>> 

其中 >>> 是 Python 解释器的提示符。里面可以运行 Python 命令,例如想获取 Python 模块 sys 的帮助,可执行

>>> help('sys')

一般而言,Python 内置模块的帮助文档的阅读器默认是 less,因此翻页、退出方法很简单,只需操作键盘上的方向键与 q 即可。退出 Python 解释器的方法是

>>> exit()

实际上,Python 的帮助文档也可直接在命令行或者 Web 界面中调用 pydoc,例如在 CMD.EXE 窗口中执行

> pydoc sys

若不知晓模块名,可按下述方式搜索关键字

> pydoc -k sys

或者启动用小型 Web 服务器,也即在 CMD.EXE 窗口中执行

> pydoc -p 8000

打开网页浏览器,访问 http://localhost:8000 即可查看文档。甚至可到 Python 的官方网页下载帮助文档 http://docs.python.org/download.html。另外,Python 命令也可以写到文件中,这样的文件称为 Python 脚本,一般以 .py 为扩展名。通常,在 Linux 系统中编写 Python 脚本,脚本文件的第一行比较特殊,例如

#!/bin/python

该行被称为 Shebang,它的作用是告诉 Linux 系统执行 Python 脚本所调用的 Python 解释器的版本。不过在 MS Windows 中,Shebang 是没有用处的。例如编写如下的 Python 脚本 test.py:

> notepad test.py
print "Hello, Python World!"

保存后,运行它的方法是

> test.py

会根据环境变量 PATH 调用默认的 Python 解释器。当然也可指定 Python 解释器执行 Python 脚本

> C:\Python35\python.exe test.py

类似,可指定 Python 解释器执行 Python 模块,例如用 Python3 调用模块 pdb 调试 Python 脚本

> C:\Python35\python.exe -m pdb test.py

再如用 Python3 启动小型 Web 服务器

> C:\Python35\python.exe -m SimpleHTTPServer

可在本地网页浏览器中输入 http://127.0.0.1:8000 访问该 Web 服务。

以上介绍的是 Python 官方提供的安装套件。由于 Python 的使用场景众多、应用范围广泛,因此出现了很多非官方的 Python 定制套件。其中比较出名的有 Anaconda(https://www.continuum.io)、Enthought Canopy(https://www.enthought.com) 与 PythonXY(http://sourceforge.net/projects/python-xy),它们在科学计算领域中很有市场。这些 Python 工具的安装方法一如前述官方的 Python 安装方法,当然,这么多 Python 套件也为用户维护、切换它们带来烦恼。鉴于这样的原因,在 Linux 服务器系统或者 Mac OS X 中率先开发了 pyenv 工具来管理这些 Python 套件。作为 MS Windows 用户也不必担心,pywin 提供了类似 pyenv 的管理功能,可惜功能上没那么强大。

二、Python 模块/包管理工具的安装与使用

熟悉开源工具的朋友都知道,很多大型开源开发工具都有相应的开发包集散地与管理工具,例如 TeX 有 tlmgr(http://www.ctan.org,也即 CTAN)、Perl 有 cpan(http://www. cpan.org,也即 CPAN),Ruby 有 gem(http://rubygems.org),PHP 有 pear(http://pear.php.net)。幸运地是,Python 也拥有 pip(http://pypi.python.org,也即 PyPI)。Python 提供了两组工具使用 PyPI,也即 easy_install 与 pip,推荐使用 pip。不过,某些时候,easy_install 还是很有用的,这里也介绍了一下它的用法。另外,最新的 Python 版本一般都自带这两个工具,但是考虑到这两个工具的重要性,还是稍微了解一下这两个工具的安装方法。

1、easy_install 的安装与使用

easy_install 是由 PEAK(Python Enterprise Application Kit) 开发的 setuptools 包里带的一个命令行,所以使用 easy_install 实际上是在调用 setuptools 来完成安装模块的工作。引导 setuptools 的 ez_setup 工具和随之而生的扩展后的 easy_install 与 PyPI(Python Package Index)一起工作来实现相同的功能。它可以很方便的让您自动下载、编译、安装和管理 Python 包。

setuptools 可以在 http://pypi.python.org/pypi/setuptools 页面上找到 MS Windows 的安装方式,现在官网建议使用的是下载 ez_setup.py 来安装。

> wget http://peak.telecommunity.com/dist/ez_setup.py

或者

> wget --no-check-certificate https://bootstrap.pypi.io/ez_setup.py

下载完 ez_setup.py,在 CMD.EXE 窗口中切换到下载目录,使用命令行:

> python.exe ez_setup.py 

该命令行会自动下载最新版本,之后会自动安装 setuptools。setuptools 安装完毕之后,在 C:\Python27\Scripts 下会有一个 easy_install.exe 可执行文件。有 setuptools 之后,剩下的就比较简单了。通常,easy_install 会将第三方 Python 模块安装到 C:\Python27\Lib\site-packages 目录中。

a、通过模块名称来安装。setuptools 会自动搜索 PyPI 以查找最新版本的模块。如果找到的话,它会自动下载、编译和安装。例如

> easy_install SQLObject
> easy_install "python_dateutil==1.5"
> easy_install "python_dateutil>=1.5"

通过 easy_install 安装 pip

> easy_install pip

b、指定查找页面来使用名称和版本信息来安装或升级一个模块:

> easy_install -f http://sqlobject.org/SQLObject
> easy_install -U SQLObject

c、从指定 PyPI下载镜像地址来下载模块源码并在下载成功之后编译安装

> easy_install -i http://e.pypi.python.org/simple pip

d、在 easy_install 编译及安装 Python 包的过程中,需要使用 C/C++ 编译工具。在 MS Windows 操作系统中,同样需要事先安装 Visual Studio 或者 MingGW 等编译软件。PyPI 还提供了已经编译好的二进制文件 egg 给用户直接使用。如果用户直接使用 egg 的话,就无需在操作系统中准备编译器了。egg 是以平台相关的形式发布的,多数面向 MS Windows 用户。在理想情况中,egg 是一个使用 zip 压缩的文件,其中包括了所有需要的包文件。但是在某些情况下,setuptools 会决定(或被开关告知)包不应该是 zip 压缩的。在这些情况下,egg 只是一个简单的未曾压缩的子目录,但是里面的内容是相同的。使用单一的版本可以方便地进行转换,并可以节省一点磁盘空间,但是 egg 目录从功能和组织结构上来说都是相同的。为第三方 Python 模块发布 egg 文件非常简单,只需要在 Python 源码包的 setup.py 所在目录中执行

> python setup.py bdist_egg

在本地已经存在的 egg 文件基础上来安装模块

> easy_install D:\Downloads\OtherPackage-3.2.1-py2.3.egg

e、如果 PyPI 中某个已安装模块有最新版本,可升级到最新版本:

> easy_install --upgrade PyProtocols

f、从源码中安装模块(源码已经下载并解压到当前文件夹下)

> easy_install .

g、手工删除 Python 模块

如果想删除通过 easy_install 安装的软件包,由于 easy_install 本身没有卸载功能,需要手动分步完成。比如说卸载 MySQL-python,首先,可以执行命令:

> easy_install -mxm MySQL-python

此操作会从 C:\Python27\Lib\site-packages\easy-install.pth 文件里把 MySQL-python 的相关信息抹去;接着可以手动删除 MySQL-python 的 egg 文件或 MySQL-python 文件夹;最后,查找 C:\Python27\Scripts\ 目录并删除相关的可执行文件。

一般的 Python 第三方模块或包删除方法就是到 Python 的第三方模块或包的存放位置进行手工删除文件和文件夹,然后删除 C:\Python27\Lib\site-packages\easy-install.pth 文件中的相应的行。卸载 .egg 的方法类似,只需到 C:\Python27\Lib\site-packages 目录删除相应的 egg 文件或目录,接着在从 C:\Python27\Lib\site-packages\easy-install.pth 中删除相应的行。

2、pip 的安装与使用

pip 是 easy_install 的替代,可在 https://pypi.python.org/pypi/pip 找到 pip 的详细信息。pip 的安装需要 setuptools 或者 distribute 模块。distribute 是 setuptools 的替代( setuptools 包后期不再维护了)。若使用的是 Python3,那么只能使用 distribute 来安装了,因为 Python3 不再支持 setuptools 了。

利用 Python 的 setup.py 安装 pip,它默认会使用 setuptools 构建并导入 Python 模块

> wget --no-check-certificate https://pypi.python.org/packages/source/p/pip/pip-7.1.2.tar.gz#md5=3823d2343d9f3aaab21cf9c917710196
> tar -zxf pip-7.1.2.tar.gz
> cd pip-7.1.2
> python setup.py install

利用 distribute_setup 安装 pip

> wget http://python-distribute.org/distribute_setup.py
> wget --no-check-certificate https://bootstrap.pypi.io/get-pip.py
> python distribute_setup.py
> python get-pip.py

安装完成之后,在 C:\Python27\Scripts 下会有一个 pip.exe 可执行文件。有了 pip,Python 模块的安装就非常简单了。通常,pip 也会将第三方 Python 模块安装到 C:\Python27\Lib\site-packages 目录中,除非指定 --user 选项。关于该选项的介绍,请参看 https://docs.python.org/2/install/index.html#inst-alt-install-user。请注意,将 %APPDATA%\Python\Scripts 加入环境变量 PATH,也即

> setx PATH "%PATH%;%APPDATA%\Python\Scripts"

a、在 PyPi 中搜索并安装 Python 模块

> pip search "SomePackage"
> pip install SomePackage
在 pip 编译及安装 Python 包的过程中,同样可能需要使用 C/C++ 编译工具;对于不同版本的包,pip 可以指定包的版本,例如
> pip install SomePackage==version
甚至安装开发版本,例如
> pip install --pre SomePackage

b、pip 可以从指定的文件中读取需要安装的 Python 模块名

> echo Django > requirements.txt
> pip install -r requirements.txt

c、还可为 pip 指定 Python 模块的源码包路径,包括源代码包的本地路径或者网络链接:

> pip install D:\Downloads\SomePackage-1.0.4.tar.gz
> pip install http://my.package.repo/SomePackage-1.0.4.zip
> pip install http://sourceforge.net/projects/pychecker/files/pychecker/0.8.19/pychecker-0.8.19.tar.gz/download 

当然,这些包能够安装的前提是包内都已经写好了 setup.py。

d、可用下述命令查看本地所安装的 Python 模块的文件列表

> pip show --files SomePackage

另外,可通过下述方法列出所有通过 pip 安装的第三方 Python 模块

> pip list

还可以按需求将由 pip 所安装的第三方 Python 模块输出为 pip 命令能辨认的格式供 pip 使用

> pip freeze

e、若 PyPI 中有本地已安装 Python 模块的更新时,可利用下述命令更新它

> pip install --upgrade SomePackage
> pip install --upgrade SomePackage==version
> pip install --upgrade -r requirements.txt

可以利用下述方法列出所有的可更新的 Python 模块

> pip list --outdate

还可升级 pip 自身

> python -m pip install -U pip

f、pip 命令不建议使用 egg 文件。如果你想使用 egg 安装的话,请使用 easy_install 命令。不过 pip 支持 wheel 文件。wheel 本质上是一个 zip 包格式,它使用 .whl 扩展名,用于 python 模块的安装,它的出现是为了替代 Eggs。模块 wheel 还提供了一个 bdist_wheel 作为 setuptools 的扩展命令,它可以用来生成 wheel 包。为第三方 Python 模块发布 whell 文件非常简单,只需要在 Python 源码包的 setup.py 所在目录中执行

> python setup.py bdist_wheel

pip 也提供了一个 wheel 子命令来发布 wheel 包,当然,需要先安装 wheel 模块。同时,pip 可直接安装 wheel 文件,例如

> pip install beautifulsoup4-py2-none-any.whl
实际上,pip 总是优先使用 .whl 文件;若没有 .whl 文件才会从源代码利用 wheel 模块编译;当然,即使有 .whl 文件,也可以让 pip 只从源码编译,例如
> pip install --no-binary :all: beautifulsoup

g、pip 比 easy_install 强大的地方之一是提供了卸载本地安装的第三方 Python 模块,例如

> pip uninstall SomePackage
> pip uninstall -r requirements.txt

pip 还有许多有用的选项,如 --download-cache=DIR 可以指定下载安装文件时缓存至 DIR 路径,下次需要时则直接读取缓存文件;再如 -i 可用来指定 pip 的安装镜像。更多的选项信息可以执行

> pip --help
> pip help install

除了命令行选项之外,还可通过环境变量设置 pip 的行为,例如 PIP_LOG_FILE、PIP_DOWNLOAD_CACHE、PIP_CONFIG_FILE。随后,还可以通过修改 pip 的配置文件来实现上述需求。在 MS Windows 下,pip 配置文件是 %HOMEPATH%\.pip\pip.conf,若在其中增加下述内容

> notepad.exe %HOMEPATH%\.pip\pip.conf
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/

这样在使用 pip 来安装时,会默认使用此源。更多的配置请参考 http://pip.readthedocs.org/en/latest/user_guide.html#configuration。配置的优先级如下:

  • 命令行选项 --host=foo 覆盖 PIP_HOST=foo;
  • 环境变量 PIP_HOST=foo 覆盖 pip 配置文件中的 [global] 小节中的 host = foo;
  • pip 配置文件中的命令 command 小节 [<command>] 中的 host = bar 覆盖配置文件中的 [global] 小节中的相应的配置。

作为使用 pip 的实例,下面来介绍一下 MS Windows 系统中 Python 套件管理工具 pywin 的安装以及使用方法。安装 pywin 之前需要首先确保安装了一套 Python 工具包,它是 pywin 正常工作的保障。pywin 的安装非常简单

> pip install --user pywin

首先初始化 pywin 环境

> pyassoc

搜索所有已安装的 Python 并在 pywin.bat 所在目录中创建相关启动文件

> pywin genlaunchers

若要启动现有 PATH 中的第一个 Python 套件,可执行

> pywin

若想在当前 CMD.EXE 窗口中启用 python 2.7,可执行

> pywin -2.7

若想将 Python 3.3 设置为默认的 Python 套件,可执行

> pywin setdefault 3.3

三、python 虚拟环境的创建与使用

Python 虚拟环境为 Python 模块的开发、测试提供了极大的便利,它可以有效的隔离无关模块。下面来介绍两个建立 Python 虚拟环境的典型方法。

1、利用 virtualenv 模块

安装 virtualenv:

> easy_install virtualenv==1.10.1

或者

> pip install virtualenv

安装完毕之后,同样在 C:\Python27\Scripts 下面可以看到 virtualenv.exe 文件。

安装完毕 virtualenv 之后,就可以创建虚拟环境了。先在 CMD.EXE 窗口中切换到需要创建虚拟环境的目录下,创建的虚拟环境是在该目录下的一个文件夹

> cd D:\some\directory\to\create\VirtualEnvs\
> virtualenv MyEnv

默认情况下,虚拟环境会依赖系统环境中的 site-packages,就是说系统中已经安装好的第三方 Python 包也会安装在虚拟环境 MyEnv 中。如果不想依赖这些 Python 包,那么可以加上参数 --system-site-packages 建立虚拟环境

> virtualenv --system-site-packages MyEnv

如果系统中安装有多个 Python 版本,要想使用指定版本的 Python 来创建虚拟环境,可执行

> virtualenv --python=C:\Python35\python.exe MyEnv

创建之后,可以检查一下 MyEnv 目录中是否有文件生成,同时确认一下 MyEnv\Scripts\ 目录中是否有 activate.bat 和 deactivate.bat 两个文件。至此,虚拟环境 MyEnv 就创建好了。运行虚拟环境只需要在 CMD.EXE 窗口中下执行

> cd D:\some\directory\to\create\VirtualEnvs\
> MyEnv\Scripts\activate.bat

虚拟环境 MyEnv 启动后,会在 CMD.EXE 窗口的提示符前多出一个 (MyEnv),在该 CMD.EXE 窗口中进行的所有操作均在虚拟环境 MyEnv 中,例如下述命令

(MyEnv)> pip install Pelican

会将 Python 模块 Pelican 安装到虚拟环境 MyEnv 所在目录 D:\some\directory\to\create\VirtualEnvs\MyEnv 中,而不是 Python 套件所在目录 C:\Python27 中。退出虚拟环境只需要在该 CMD.EXE 窗口中运行

(MyEnv)> deactivate.bat

简单说明一下与 virtualenv 相关的环境变量 VIRTUALENV_USE_ DISTRIBUTE。VIRTUALENV_USE_DISTRIBUTE 是向 Python 模块 distribute 指明 Python 运行信息的环境变量。如果在开发过程中,希望所开发的 Python 应用程序有“不兼容旧版本的 Python”或者“兼容最新版本 Python”的要求,最好对该环境变量进行设定。为了不在每次登录都输入这样的命令,可在 MS Windows 中设置环境变量,例如

> setx VIRTUALENV_USE_DISTRIBUTE=true

模块 distribute 会根据这个环境变量是否存在,判断虚拟运行环境的配置有效或无效。因此在不使用模块 distribute 的时候,建议取消该环境变量。

2、利用 virtualenvwrapper-win 模块

当然更好的虚拟环境封装是安装下述 Python 模块

> pip install virtualenvwrapper-win

并设置环境变量 WORKON_HOME 为虚拟环境的工作目录

> setx WORKON_HOME "%USERPROFILE%\Virtualenvs"

a、创建虚拟环境,例如下述命令行会创建一个名为 MyEnv 的虚拟环境

> mkvirtualenv MyEnv

使用指定版本的 Python 来创建虚拟环境,例如

> mkvirtualenv --python=C:\Python35\python.exe MyEnv

实际上,virtualenvwrapper 提供了更多的定制变量,例如 VIRTUALENVWRAPPER_PYTHON、VIRTUALENVWRAPPER_VIRTUALENV 以及 VIRTUALENVWRAPPER_VIRTUALENV_ARGS 等。

b、列出所有虚拟环境

> lsvirtualenv

切换到虚拟环境,例如

> workon MyEnv

此时在 CMD.EXE 窗口的提示符前多出一个 (MyEnv)。此时可进入虚拟环境的所在目录,例如

(MyEnv)> cdvirtualenv

根据环境变量 WORKON_HOME 的设定,会将目录切换到 %USERPROFILE%\Virtualenvs\MyEnv。

c、在虚拟环境中的创建工程,例如在 SomeEnv 虚拟环境中创建名为 ProInSomeEnv 的工程

(MyEnv)> mkproject ProInSomeEnv

进入虚拟环境中的工程目录,例如

(MyEnv)> cdproject ProInSomeEnv

退出当前虚拟环境

(MyEnv)> deactivate

d、移除虚拟环境,例如

> rmvirtualenv MyEnv

3、虚拟环境的迁移

当需要将虚拟环境 MyEnv 迁移或复制到另一个虚拟环境(可能不在同一台机器上)YourEnv 时,首先仍然需要在目的机器上安装 pip 和 virtualenv(或者 virtualenvwrapper-win),然后采用以下方法之一安装其他的 Python 模块。

a、直接将 MyEnv 里的文件全部复制到 YourEnv 里,然后修改涉及路径的文件。此种方法可能正常使用,但显然不是好办法。

b、进入原虚拟环境 MyEnv,然后执行

(MyEnv)> pip freeze > requirements.txt

将包依赖信息保存在 requirements.txt 文件中。然后进入目的虚拟环境 YourEnv,执行

(MyEnv)> pip install -r requirements.txt

pip 就会自动从网上下载并安装所有包。

c、pip 默认会从 PyPI 服务器(http://pypi.python.org/simple)下载包的安装文件,如果目的机器无法连外网,则可以采用以下办法:

c1、搭建自己的 PyPI 服务器。专业的,可以使用第三方的软件包来搭建一个完整的 PyPI 镜像服务器。更快速的方法只需要一条命令

> python -m SimpleHTTPServer

即可完成搭建服务器,具体的目录结构可参考原 PyPI 服务器,简而言之,就是把安装文件打包放入目录即可。搭建好服务器之后,在目的虚拟环境中,就可以使用 pip 来安装了,命令如:

(YourEnv)> pip install -i http://127.0.0.1:8000/ -r requirements.txt

c2、若不想搭建 PyPI 服务器,也有办法。首先将所有包的安装文件下载到本地目录中,可以手动下载,也可以使用 pip,例如

(MyEnv)> pip install -d D:\Downloads -r requirements.txt

然后将 D:\Downloads 中缓存的所有 Python 包以及 requirements.txt 文件复制到目标主机中,再在目的虚拟环境中使用 pip 安装,例如所有缓存的 Python 包也被复制到 D:\Downloads 中,则

(YourEnv)> pip install -d D:\Downloads -r requirements.txt

即可。

c3、还有一种途径,就是 pip 提供的 bundle 选项。首先执行

(MyEnv)> pip bundle MyEnv.pybundle -r requirements.txt

将生成一个 MyEnv.pybundle 文件,该文件夹包含所有包的安装文件(注意必须后缀名必须是 .pybundle),默认是重新从 PyPI 服务器下载安装文件的,如果愿意,也可以利用 c1 中的方法,指定本地的 PyPI 服务器。然后在目的虚拟环境中执行

(YourEnv)> pip install MyEnv.pybundle

即可。

四、图形用户界面相关的 Python 工具

GTK+ 是由 C 语言开发的跨平台图形用户界面库,PyGTK 是将 GTK+ 与 Python 语言绑定,它能够用 Python 语言进行图形用户界面的开发,它的项目主页是 http://www.pygtk.org。最新的 PyGTK 版本是 2.24.2,不过目前还不支持 Python3。PyGTK 有两种安装方式:一是安装将 GTK+、Python 等集成在一起的 PyGTK 包,可到 http://ftp.gnome.org/pub/GNOME/binaries/ 下载 32 位的安装包 pygtk-all-in-one-2.24.2.win32-py2.7.msi 或 64 位的安装包 pygtk-all-in-one-2.24.2.win64-py2.7.msi;二是分别单独安装 Python、GTK+ 与 PyGTK 工具包。为了行文统一,此地选择后者作为安装 PyGTK 的方法,Python 已由前述方案安装,请记住所安装的 Python 版本是 Python 2.7;可到 http://ftp.gnome.org/pub/gnome/binaries 下载最新版本 GTK+-2,也即 32 位安装包 gtk+-bundle_2.24.10-20120208_win32.zip 或者 64 位安装包 gtk+-bundle_2.24.10-20120208_win64.zip,若不需要用 C 语言开发 GTK+ 的话,也可只安装 GTK+ 的运行库,到 https://sourceforge.net/projects/gtk-win/files/GTK%2B%20Runtime%20Environment/GTK%2B%202.24 下载 gtk2-runtime-2.24.10-2012-10-10-ash.exe;至于 PyGTK,32 位的包可到 http://ftp.gnome.org/pub/GNOME/binaries/win32/pygtk/ 下载 pygtk-2.24.0.win32-py2.7.msi,64 位的包可到 http://ftp.gnome.org/pub/GNOME/binaries/win64/pygtk/ 下载 pygtk-2.24.0.win64-py2.7.msi。由于未集成的 PyGTK 工具包还依赖 PyGObject、PyCairo,32 位对应的到 http://ftp.gnome.org/pub/GNOME/binaries/win32/ 下载最新版本 pygobject-2.28.3.win32-py2.7.msi、pycairo-1.8.10.win32-py2.7.msi,64 位对应的到 http://ftp.gnome.org/pub/GNOME/binaries/win64/ 下载最新版本 pygobject-2.28.3.win64-py2.7.msi、pycairo-1.8.10.win64-py2.7.msi。安装过程相对容易,就不多言了。还需测试一下 PyGTK 开发环境,下面是一个简单 Hello PyGTK 的例子
> notepad.exe hellopygtk.py
from gtk import * 

window = GtkWindow(WINDOW_TOPLEVEL) # 创建一个顶层窗口 
window.set_title("Hello, world!") 
window.connect("destroy", mainquit) # 将注销事件与mainquit处理连接 

window.show() # 显示主窗口 
mainloop() # 进入事件循环 
> python hellopygtk.py
 
QT 是由 C++ 语言开发的跨平台图形用户界面库,PyQT 是将 QT 与 Python 语言绑定,它也能够用 Python 语言进行图形用户界面的开发,项目主页在 https://www.riverbankcomputing.com/software/pyqt。PyQT 只提供了一种预编译二进制包安装方式,也即集成除 Python 本身之外所有工具包(如 QT 等)的安装包,最新版本是 PyQT5-5.5.1,可到 http://sourceforge.net/projects/pyqt/files/PyQt5/ 下载 32 位安装包 PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x86.exe 或 64 位安装包PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x64.exe。将 PyQT下载后安装即可,安装它前需配置好 Python 开发环境,需要注意的是该包需要的 Python 版本是 Python 3.4,若是其他 Python 版本,需自行编译 PyQT 源代码。测试一下 PyQT 开发环境,下面是一个简单 Hello PyQT 的例子
> notepad.exe hellopyqt.py
import sys
from PyQt5 import QtWidgets, QtCore
app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QWidget()
widget.resize(360, 360)
widget.setWindowTitle("Hello, PyQt5!")
widget.show()
sys.exit(app.exec_())
> python hellopyqt.py
 
wxWidgets 也是由 C++ 语言开发的跨平台图形用户界面库,wxPython 是将 wxWidgets 与 Python 语言绑定进行图形用户界面的开发,它的项目主页在 http://www.wxpython.org。wxPython 只提供了一种预编译二进制包安装方式,也即集成除 Python 本身之外所有工具包(如 wxWidgets 等)的安装包,最新版本是 wxPython 3.0,可到 http://www.wxpython.org/download.php 下载 32 位安装包 wxPython3.0-win32-3.0.2.0-py27.exe 或 64 位安装包 wxPython3.0-win64-3.0.2.0-py27.exe。安装 wxPython 前需配置好 Python 开发环境,下载的安装包对应的 Python 版本应该是 Python 2.7。测试一下 wxPython 开发环境,下面是一个简单 Hello wxPython 的例子
> notepad.exe hellowxpy.py
import sys, os
from wxPython.wx import *

class main_window(wxFrame):
      def __init__(self, parent, id, title):
         wxFrame.__init__(self, parent, -1, title, size = (200, 100),style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
         self.control = wxTextCtrl(self, -1, style=wxTE_MULTILINE)
         self.Show(true)

class App(wxApp):
      def OnInit(self):
         frame = main_window(None, -1, "wxPython: (A Demonstration)")
         self.SetTopWindow(frame)
         return true

app = App()
app.MainLoop()
> python hellowxpy.py
 
五、各种科学计算相关的 Python 工具
 
iPython 是增强的交互环境,它支持变量自动补全、自动缩进、支持 Bash Shell 命令,内置了许多很有用的功能和函数。 它的项目主页是 http://ipython.org。由于 iPython 4.0 之后,iPython 将语言无关的部分从 iPython 分离出来成了 jupyter,例如它包含了 iPython.notebook 等。
> pip install ipython jupyter
 
Spyder 是 Python 集成开发环境。由于 spyder 依赖 pyQT,需先安装 pyQT 开发包并配置相关的环境变量才能使用 pip 安装 spyder:
> pip install spyder
如果先解决依赖比较麻烦,也可从它的主页 https://github.com/spyder-ide/spyder/releases 获取预编译二进制包。
 
NumPy 是 Python 的数学计算基础库,它包括了 N 维数组、线性代数计算、傅立叶变换、随机数等。它的项目主页是 http://numpy.org。由于 NumPy 几乎不存在外部依赖,可直接用 pip 安装
> pip install numpy
当然,如果有外部的 LAPACK、BLAS 等 C/C++ 库的话,会对于 NumPy 的安装更有帮助。
 
SciPy 是 Python 的数值计算库,它包括了线性代数、拟合与优化、插值、数值积分、稀疏矩阵、图像处理、统计等。它的项目主页是 http://scipy.org。由于 SciPy 依赖与外部的 LAPACK、BLAS、ATLAS 等 C/C++ 库以及 Numpy 包,若解决了这些依赖问题,可用 pip 安装
> pip install scipy
否则请从它的主页 http://sourceforge.net/projects/scipy/files/scipy/ 获取二进制包。
 
SymPy 是 Python 的符号运算库,它的项目主页是 http://sympy.org。由于 SymPy 不依赖非 Python 库,可直接用 pip 安装
> pip install sympy
 
matplotlib 是 Python 的绘图库,它可用来绘制二维图形和图表,它的项目主页是 http://matplotlib.org。由于 matplotlib 依赖众多外部库,不建议在 MS Windows 上用源码安装,不过好在 PYPI 提供了 wheel 包,可直接安装它
> pip install matplotlib
或从它的主页 http://sourceforge.net/projects/matplotlib/files 获取二进制包。
 
Pandas 是 Python 的数据分析库,它包括了数据导入、整理、处理、分析等功能,它的项目主页是 http://pandas.pydata.org。安装很容易:
> pip install pandas
 
Chaco 是 Python 用来处理交互式图表的,它的项目主页是 http://code.enthought.com/projects/chaco。直接用 pip 安装
> pip install chaco
 
OpenCV 是 Python 的计算机视觉库,它的项目主页是 http://opencv.org。由于依赖比较复杂,建议从项目主页上下载安装最新的预编译二进制包 opencv-3.1.0.exe。
 
Cython 是 Python 代码转 C 代码的转换器,它是编写高效运算扩展库的首选工具。项目主页在 http://www.cython.org。安装非常简单:
> pip install Cython
 
ipdb 是增强的 Python 调试器,也可通过 logging 模块提供的日志功能进行调试。用 pip 安装即可
> pip install ipdb logging
若不想因依赖外部包而不能成功安装上述 Python 包,而又比较简单地获得 MS Windows 上大部分常用的 Python 二进制包,可试试下述地址: http://www.lfd.uci.edu/~gohlke/pythonlibs

若对用 Python 处理计算流体的问题有兴趣,不妨仔细阅读 https://github.com/barbagroup/CFDPython 中的课程。

Aug 21

MinGW、Code::Blocks 和 wxWidgets 是三个著名的开源项目,分别是编译器(GNU Compiler Collections)、集成开发环境(IDE)和图形界面开发库(GUI Library)。由这三个工具搭建起来的全开源 C++ 开发环境,功能不逊色于 VC,由于使用的开源软件,这样的开发环境是免费的,并且是跨平台的。下面说一下在 MS Windows 下的搭建过程。

一、编译器

MinGW 是指只用自由软件来生成纯粹的 Win32 可执行文件的编译环境,它是 Minimalist GNU on Windows 的略称。实际上,MinGW 并不是一个 C/C++ 编译器,而是一套 GNU 工具集合在 MS Windows 系统上的一个移植。MinGW 官方网站为 http://www.mingw.org

1、MinGW 的安装

安装 MinGW 有两种安装方式:自动安装与手动安装。下面分别来介绍它们。

1.1、自动安装。

下载自动安装程序(http://sourceforge.net/projects/mingw/files/Installer/)mingw-get-setup.exe,然后一步步的来就行了。大致如下:设置安装目录,默认安装到 C:\MinGW;选择安装组件,这个根据大家需要选择安装组件( C 编译器、C++ 编译器、Fortran 编译器、ObjC 编译器、Ada 编译器等),一般选择 C/C++ 编译器即可,看各位用途确定,组件列表中还有 MSYS 基本系统等可供选择;等待下载并安装完成。

实际上, MinGW 提供了一个非常方便的包管理工具 mingw-get。在 MinGW 安装完成并适当的配置环境变量之后,可以在命令行窗口(cmd.exe)中或者 MSYS 基本系统中通过 mingw-get 命令来进行包管理。例如在命令行窗口(cmd.exe)中可以使用

> mingw-get --help

查看详细的使用方式,主要命令与各种 Linux 包管理器如 apt-get、dnf 等的操作类似,常用的几个包括

> mingw-get update
> mingw-get install packagename
> mingw-get remove packagename
> mingw-get upgrade packagename
> mingw-get list

1.2、手动安装。

简言之就是本来自动安装的内容要自己下载并且复制到自己设定的目录中。根据 MinGW 官方网站 http://www.mingw.org/wiki/InstallationHOWTOforMinGW 介绍,到 http://sourceforge.net/projects/mingw/files/MinGW/Base/ 下载保证 MinGW 正常工作所需要的下述文件

  • binutils (bin)
  • mingw-runtime (dev and dll)
  • w32api
  • Required runtime libraries for GCC:
    • mpc (dll)
    • mpfr (dll)
    • gmp (dll)
    • pthreads (dev and dll)
    • iconv (dll)
    • zlib
    • gettext
  • gcc-core (bin and dev and dll)

作为 C++ 开发工具,还需再到 http://sourceforge.net/projects/mingw/files/MinGW/Extension/ 下载下述文件

  • gcc-c++ (bin and dev and dll) for c++
  • mingw-gdb and libexpat for debugger
  • mingw32-make for make
  • mingw-utils for MinGW Utilities

然后将这些文件解压到同一个目录下,例如 C:\MinGW。实际上,利用 mingw-get 也可实现半自动化安装,也即将所有包放入它的缓存目录,也即 C:\MinGW\var\cache\mingw-get\packages,然后正常安装 mingw-get-setup.exe 便可利用已下载的包完成安装。半自动安装方法适用于那些暂时或者长时间网络条件比较差的电脑主机。

2、设置 MinGW 的环境变量

MinGW 环境的设置也有好几种方法,但通常的做法是要么类似 Linux 终端起一个 MinGW Shell,要么类似 Visual Studio 用 batch 脚本起一个配置好环境变量的命令行窗口(cmd.exe)。

2.1、若前面安装了 MSYS 基本系统,则在 MS Windows 的开始菜单中会有一个 MinGW Shell 子菜单,也即开始菜单 ->程序 -> MinGW -> MinGW Shell,运行它可在 MS Windows 中打开 MinGW Shell。需要注意,第一次运行 MinGW Shell 时,记得在打开的 MinGW Shell 中执行下述命令

$ /postinstall/pi.sh

它可以将 MinGW 与 MSYS 绑定在一起。以后每次使用 MinGW 时,只需点击该子菜单便可自动在命令行窗口中配置好 MinGW 的环境。如果 MinGW 没有安装在标准位置,那还可适当调整 MinGW Shell 的配置

> notepad.exe C:\MinGW\msys\1.0\etc\fstab
C:\MinGW /mingw

根据此配置,来设定 MinGW Shell 的根目录位置;MinGW Shell 的用户家目录由环境变量 %HOME%、%USERPROFILES% 等决定;还有,MS Windows 中盘符如 C:\、D:\ 等对应的是 /c/、/d/。实际上,安装 MSYS 基本系统的好处也在这里,它将 Linux 系统中那套 Bash Shell 工具搬到了 MS Windows 中来。特别是,在 MinGW shell 中能执行那些只能在 Bash Shell 中执行的 Linux 命令行。若 MinGW 安装过程中没有事先选择安装 MSYS 基本系统的话,可自行通过 C:\MinGW\msys\1.0\msys.bat 脚本创建 MinGW Shell 子菜单;当然,也可以在 MS Windows 桌面或者状态栏创建名为 MinGW Shell 的快捷方式。

2.2、若想全局的设置 MinGW 环境变量,可依次鼠标点击桌面“我的电脑”->选择左侧的“高级系统设置”,选择“高级”->“环境变量”,然后在 PATH 里增加 ;C:\MinGW\bin 声明。也可将 MSYS 的环境变量全局话,也即在 PATH 设置的最后加入 ;C:\MinGW\msys\1.0\bin;C:\MinGW\msys\1.0\local\bin。当然,也可在 MS Windows 的命令行窗口(cmd.exe)中执行

> setx PATH "%PATH%;C:\MinGW\bin;C:\MinGW\msys\1.0\bin;C:\MinGW\msys\1.0\local\bin"

请注意路径 C:\MinGW\msys\1.0\local,它是用户在 MinGW Shell 中安装第三方源码包编译执行 make install 时的安装目录。

2.3、若不想全局启用 MinGW 同时也没有安装 MSYS 基本系统,那么可在命令行窗口(cmd.exe)中临时启用 MinGW,也即

> SET PATH=C:\MinGW\bin;%PATH%

当然,每次都要执行这样的命令还不如建一个环境变量配置脚本来得简单。例如在命令行窗口(cmd.exe)中执行

> notepad.exe mingw32setvar.bat
SET PATH=C:\MinGW\bin;%PATH%

要启用 MinGW 时,可打开命令窗口(cmd.exe)执行

> mingw32setvar.bat

2.4、为了看到前述 MinGW 环境配置是否成功,做一些简单地测试。这里为了简单起见,就以环境变量的配置脚本为例,在命令行窗口(cmd.exe)中执行

> mingw32setvar.bat
> notepad.exe test.cpp
#include <iostream>
using namespace std;

int main(){
    cout << “hello world!”; 
}
> gcc test.cpp
> test.exe

3、为 MSYS 基本系统安装手册页

由于 MSYS 基本系统中没有手册页,一旦遇到不熟悉的 API 就麻烦了,下面介绍一下给 MSYS 基本系统安装手册页的方法。首先打开 MinGW Shell,然后执行

$ mingw-get install msys-groff msys-man

MSYS 基本系统中安装好了手册页工具,试试执行

$ man --help

测试一下。若一切正常,可到 http://www.kernel.org/pub/linux/docs/man-pages/ 下载手册 man-pages-4.02.tar.gz。下载后放到 MS Windows 的用户目录,例如 C:\Users\james,也即 MSYS 基本系统的用户家目录,故直接执行

$ cd ~
$ tar -xzvf man-pages-4.02.tar.gz

进行解压。进入目录手册页源码目录编译

$ cd man-pages-4.02
$ make && make install

大概几分钟后,man 手册就安装成功了。最后,执行

$ man printf

测试一下。

二、Code::Blocks 的安装与配置

1、Code::Blocks 的安装

Code::Blocks 是一个集成开发环境(IDE),本身不含编译,它支持多种编译器,界面近似于 VC。官方网站:http://codeblocks.org。到其官方网站下载最新版本并安装,目前是 codeblocks-13.12-setup.exe,例如安装到 C:\CodeBlocks 目录。

若不想单独配置 MinGW 环境(也即第一步 MinGW 的安装过程),可到 http://sourceforge.net/projects/codeblocks/files/Binaries/13.12/Windows/ 下载安装带有 MinGW 的 Code::Blocks,例如 32 位的 MS Windows 系统选择 codeblocks-13.12mingw-setup.exe、64 位的 MS Windows 系统选择 codeblocks-13.12mingw-setup-TDM-GCC-481.exe。若想在命令行状态下单独使用 MinGW 环境,则须配置系统的环境变量 PATH,例如

> setx PATH "%PATH%;C:\CodeBlocks\MinGW\bin;C:\CodeBlocks\MinGW\libexec\gcc\mingw32\4.7.1"

若第一次运行 Code::Blocks,会要求选 MinGW 为默认编译器。在主菜单 Settings -> Compiler..., Global Compiler settings 子标签页中将 Setected compiler 修改为 GNU GCC Compiler 编译器(就是 MinGW)。在同一个页面中选择 Toolchain executables 选项卡中先修改 Compiler's installation directory 为 MinGW 安装路径,这里就是 C:\MinGW。再在 program files 选项页中选择 C Compiler 为 gcc.exe、C++ Compiler 为 g++.exe、Links for dynamic libs 为 g++.exe、Links for static libs 为 gcc-ar.exe、Debugger 为 gdb.exe;Rescource Compiler 为 windres.exe 以及 Make Program 为 mingw32-make.exe。这样,集成开发环境和编译器就搭建好了。

2、字符编码的设置

自从上帝摧毁了人类建造巴别塔的企图之后,人类的语言就因地域不同而不能直接交流了。计算机中也同样存在着“语言”交流问题,这就是字符编码问题。计算机刚问世的一段时间内,只存储和显示由 8 位字长的二进制数表示的字符,这便是 ASCII 码表示的 ASCII 字符。随着计算机越来越普及,支持多国语言文字提上日程,由各个地区制定的由 ASCII 码衍生出来的表示各地字符的编码统称为 ANSI 编码。例如 GB18030、GB2312、GBK、Big5 等均是中文字符的 ANSI 编码,且前三个是超集关系。ANSI 编码规定:编码位于 0x00——0x7F 之间的字符,依旧是 1 个字节代表 1 个字符。除此而外,不同 ANSI 编码之间不一定兼容。由于这种混乱,Unicode 编码应运而生,它的目标是废除所有的地域性编码方案,重新搞一个包括地球上所有文化所使用的字母和符号的编码。Unicode 编码规定必须用两个字节表示字符(后来还有扩充,可以用以 4 个字节等表示字符),换而言之,所有的字符必须用 16 位字长的二进制数表示。同时,对于原先的 ASCII 字符,Unicode 保持其原编码不变,只是将其字长由原来的 8 位扩展为 16 位,而其他文化、语言的字符则全部重新统一编码。这一点是 ANSI 编码与 Unicode 编码之间的众多区别之一。另外,Unicode 只是规定了字符编码,但没有规定怎么在计算机中存储这些编码。如果直接存储这些编码的话,对于 ASCII 字符来说,第一个字节均是 0,浪费存储资源。这就产生了 Unicode 编码在存储的实现问题。一般,字符编码的存储实现也直接称为编码。UTF-8 编码、UTF-16 编码等都是 Unicode 编码的存储实现。前面的 GB18030 编码、GB2312 编码、GBK 编码、Big5 编码等中文字符的 ANSI 编码既是编码也可以是 ANSI 编码的存储实现。更一般地,ANSI 编码可以与其存储实现一致。在 Linux 世界中,使用 UTF-8 编码是共识。但在 MS Windows 中,字符编码的存储由 Windows 代码页实现。例如,Big5 编码在 MS Windows 中的存储实现是代码页 Windows 950 或者 cp950,GB18030、GB2302、GBK 对应的代码页是 cp54936、cp20936、cp936。另外,微软公司根据中国政府的规定在中国境内销售的中文版 Windows 系统必须设定 GB 编码。这在互联网时代之初带来了困扰中文用户很久的乱码问题,原因在于 GB 编码与 UTF-8 编码除去 ASCII 字符等很少一部分字符重合之外,两者并不完全一致。如此一来,若不对文本做一些额外的处理,跨平台文本交流就会出现乱码。

由于前面的编译器采用的是 MinGW 提供的 GCC,它在编译时默认编译源代码是由 UTF-8 编码编写,编译而成的可执行文本输出时也是 UTF-8 编码。因此,为了让程序正常工作,推荐 Code::Blocks 编辑器中的编码设定为 UTF-8。因此,需要确认一下该编码设置是否正确,也即 Setting -> Editor... -> General Setting -> Other setting 中 Encoding 栏的 Use encoding when opening files 复选框中选择 UTF-8 编码。

如果要用 Code::Blocks 打开久远年代用 GBK 编码写成的工程文件时,特别是打开那些带有久远的库文件的工程时,为了防止乱码,好的选择是再次修改 Code::Blocks 编码设置并更改编译选项设置。例如,老工程是 GBK 编码所写,那么先在 Setting -> Editor... -> General Setting -> Other setting 中 Encoding 栏的 Use encoding when opening files 复选框中选择 GBK 编码,代码页为 Windows 936;以保证 Code::Blocks 编辑器中源代码显示正常。其次,在 Setting -> Compiler... -> Global Compiler Settings -> Compiler Settings -> Other options 框中输入两个选项:-finput-charset=GBK-fexec-charset=GBK。总之,要做到源代码文件的编码和编译时输入、输出编码统一。

3、定制 F1 帮助系统

在主菜单 Settings -> Environment... -> Help files 子标签页中新建一个条目,名为 manual Pages,接着的对话框选 no,然后手动在下面的路径框中填写:man:/usr/share/man;再将使用 F1 快捷键勾上。这样就可以使用 man pages 了。在 Editor 中,将光标停在想要查询的内容上面,按 F1,就会弹出一个 panel,里面就有查询内容的 man 手册,非常的方便。比如 光标位于 printf,按 F1,弹出的 panel 中就显示 printf 的 man 手册。建议安装如下手册页:C API 手册页、posix 函数手册页、C API 手册页 glibc-doc、C++ 标准类库手册页、C++ API 手册页等。

4、变量声明、函数原型等自动提示

每个 Code::Blocks 工程都可在主菜单 Project -> Properties...,Project/Target options -> C/C++ parser options 中添入头文件所在目录,这样信息提示功能才可正常工作,如下是标准库头文件的目录:

  • C:\MinGW\include
  • C:\MinGW\include\c++\4.8.1
  • C:\MinGW\include\c++\4.8.1\mingw32
  • C:\MinGW\include\c++\4.8.1\backward

若项目中还使用了其他库,也可添加更多的头文件路径。例如将后面马上要提到图形界面开发库 wxWidgets 的文件路径添加进去

  • C:\wxWidgets-3.0.1\include
  • C:\wxWidgets-3.0.1\lib\gcc_dll\mswu\

需要注意,添上后不是立即起效,需要过一段时间后才能起作用!

5、自动补全与缩写

首先,打开主菜单 Settings -> Editor... -> Code-completion 标签页,点击 Code-completion 选项卡

  • 将 Keyword sets to additionally include 中1到9都勾上,1 ~ 9 对应的关键字可在 Settings -> Editor... -> Syntax highlighting 的 keywords... 按钮中设置,默认其中 1 是 C++ 关键字,3 是 Doxygen 关键字;
  • 将 Delay for auto-kick-in when typing [.::->] 拉到 200ms,这样快点出来提示;
  • 将 Automatically launch when typed # letters 中的 4 改成 2,这样打两个字母就会有提示了;
  • 将 Case-sensitive match 的勾去掉,它会帮你纠正大小写。

其次,在主菜单 Settings -> Editor... -> Abbreviation 标签页中定义了许多缩写(还可以自定义),只要输入这些缩写,并按 Ctrl+J,就可以自动完成常用的代码框架,并可将光标放在恰当的地方(自定义时用|表达),常用的有:guard、class、switch 等。

6、Code::Blocks 的汉化

Code::Blocks 的本地化(翻译)项目在 https://translations.launchpad.net/codeblocks/+translations 上,有兴趣的用户可以加入。Code::Blocks 的语言包也在该主页上,下载对应的语言包,不过下载前需要注册一个账号。能下载的压缩包有两种:mo 和 po 格式,本地化需要的是 mo 格式文件,下载并打开 mo 压缩包,解压得到里面的文件,找到对应语言的 mo 文件。接着在 Code::Blocks 安装目录下的建立相应语言的文件夹,例如

> mkdir C:\CodeBlocks\share\CodeBlocks\locale\zh_cn

并复制刚才找到的 mo 文件到该位置。启动 Code::Blocks,找到主菜单上的 Settings -> Environment...,Environment -> View 选项卡,在第二行 internationalization 上打钩,在右边选择 chinese(simplified),点 OK。重启 Code::Blocks,界面就汉化了。

安装 Code::Blocks 每日提示双语文件

本文件仅仅用于实现启动 Code::Blocks 时,出现的“今日提示”内容的汉化。请妥当备份本文件,因为在每次进行升级时,该文件都有可能被原英文提示文件覆盖掉。所在以每次升级之后,都需要进行本操作。下载 Code::Blocks 每日提示中英双语文件。请打开 Code::Blocks 安装目录下的 C:\CodeBlocks\share\CodeBlocks 子目录,找到 tips.txt,如有必要,请先备份原文件。然后解压上面下载的文件,覆盖原有文件。

7、为 Code::Blocks 创建新的工程向导文件

Code::Blocks 提供了很多工程向导模板,但是还有很多图形工程没有模板,例如 GTKmm。实际上,在 Code::Blocks 增加工程向导模板是非常容易的,这里以 GTKmm 模板为例。首先,在用户的 Code::Blocks 应用程序数据目录中新建工程向导文件目录 GTKmm,也即 %APPDATA%\codeblocks\share\codeblocks\templates\wizard\gtkmm,通常要在这个目录中创建如下几个文件 wizard.scriptlogo.pngwizard.png 以及模板文件夹 files;这些文件的创建方法可到 Code::Blocks 安装目录中查看相应例子。接着,向 Code::Blocks 注册新建的工程文件,也即编辑 %APPDATA%\codeblocks\share\codeblocks\templates\wizard\config.script,向其中写入如下的行 RegisterWizard(wizProject, _T("gtkmm"), _T("GTKmm project"), _T("GUI"));

8、Code::Blocks 配置文件备份与还原

Code::Blocks 的配置文件位于 %APPDATA%\codeblocks\default.conf 之中,用户可以修改或者保存它。不过 Code::Blocks 不建议直接备份它,而是在 Code::Blocks 的安装目录中提供了一个可执行文件 cb_share_config.exe,它可以用来导出、导入配置:

> C:\CodeBlocks\cb_share_config.exe

9、Code::Blocks 语法高亮配置

Code::Blocks 的知识百科上提供了 16 中语法高亮配置包,请看 http://wiki.codeblocks.org/index.php?title=Syntax_highlighting_custom_colour_themes,也即文件 colour_themes。使用方法非常简单,首先将该文件解压,接着关闭 Code::Blocks,用文本编辑器打开 %APPDATA%\codeblocks\default.conf,将解压文件中介于 <colour_sets></colour_sets> 之间的内容替换成原来内容。

10、Code::Blocks 的外部工具(Tools、Tools+)以及社区插件需要的外部程序

Code::Blocks 有内建插件、社区插件( contrib plugin)。有些插件直接就可以使用,例如代码补全、帮助文件等;有些插件在 MS Windows 平台直接可用,但在其他平台需要配置,例如代码格式化(Astyle)、拼写检查(Spellcheck);还有一些插件是需要安装外部程序才能使用的,例如

再有些插件只有特定平台才能使用,例如 Dev-pack 插件只能在 MS Windows 上使用,而检查内存泄漏的 Valgrind 插件无法在 MS Windows 上使用。

Code::Blocks 的 Tools、Tools+ 具有插件的功用,但那些功能还有没有插件实现。例如,代码的版本库功能对于管理代码非常有效,但目前 Code::Blocks 还没有完全实现这些插件。于是可以利用外部工具 Tools、Tools+ 与版本管理工具 git、svn 来实现一些简单的功能。当然,对这些强大的功能,还是希望有比较完善的插件来实现。

三、wxWidgets 界面库的编译与安装

wxWidgets 是一个由 C++ 编写的用来提供图形界面的开发框架。它最早是由 Julian Smart 于 1992 年开发的,包含了一个可以支持现今几乎所有操作系统(MS Windows、Unix/Linux with X11/GTK+/QT/Motif、MacOS、OS/2)的图形界面库,提供了类似微软基础类库(MFC)的功能。但是,wxWidgets 不仅仅是一个图形界面开发库,同时它也内置了基于 ODBC 的数据库、线程库以及网络通信库等类库。除此而外,wxWidgets 还有很多第三方库的支援,例如 wxSQLite、wxMathPlot、wxHTTPSever 等。特别要说一下,wxWidgets 库的后续版本还提供了对掌上电脑(SYMBIAN、iOS)的支持,还打算在新版本中对 Android 设备提供支持。wxWidgets 宣称使用其库所开发的软件只需要对源代码做少量更改(或者完全不用更改),就能在各种平台上编译并运行。wxWidgets 库使用了大量的宏,使用它开发的代码编译后尽量使用目标操作系统的本地图形界面样式。换而言之,wxWidgets 开发的程序界面,在 MS Windows 中显示 MS Windows 的样式,在 Linux 的 GNOME 桌面(KDE 桌面)显示的 GTK+ 样式(QT 样式),在 Mac OS X 中则显示 Aqua 样式。

虽然 wxWidgets 库本身使用 C++ 语言开发,但也有其它不同编程语言的绑定,例如:Python(wxPython)、Lua(wxlua)、Perl(wxPerl)、Ruby(wxRuby)、Smalltalk(wxSmalltalk)、Java(wx4j)、C#(wx.NET)甚至是 JavaScript(wxjs)等。

wxWidgets 的授权许可证是经过开放源代码促进会认证的,等同于 GNU 宽通用公共许可证(LGPL)。特别地,wxWidgets 授权允许修改者以自己的许可证发布。它的官方网址:http://www.wxwidgets.org/

wxWidgets 的安装方法大概有三种:稳定版源码包编译安装、开发版源码编译安装以及二进制版类库安装,下面开始逐一介绍。

1、到其官方网站下载最新版本的 wxWidgets 源码,目前最新版本为 3.0.1,推荐下载 wxMSW-3.0.1-Setup.exe,默认安装在 C:\wxWidgets-3.0.1 目录下。在 MinGW shell 中依次执行如下命令

$ cd /C/wxWidgets-3.0.1
$ ./configure
$ make
$ make install

请注意 make install 会将 wxWidgets 库文件安装到 MSYS 基本系统的根目录,此地便是 C:\MinGW\msys\1.0\local。这样的好处是,若在 MinGW Shell 中执行

$ wx-config --cxxflags
$ wx-config --libs

便可看到使用 wxWidgets 库文件的编译参数信息。

前述编译方法是 Linux 中源代码编译、安装的标准方法,甚至来编译参数设定也可以用典型的 Linux 方法,也即 wx-config 命令,当然,这一切以安装了 MSYS 基本系统为前提。但在 MS Windows 上,对于 wxWidgets 库文件来说,一般并不推荐安装,直接在源码的编译目录中使用它即可。鉴于这种处理方式,给出 wxWidgets 库文件在 MS Windows 平台的正常编译方法,也即在 MS Windows 的命令行窗口(cmd.exe)中执行:

> cd C:\wxWidgets-3.0.1\build\msw

里面有很多 Makefile,它们用来控制 wxWidgets 库文件的编译过程。实际上,wxWidgets 可被分别编译成 Release/Debug、ANSI/Unicode 与动态/静态版本的库。动态版本库的扩展名是 .dll,静态版本库的扩展名是 .lib 或者 .a;用 d 表示 Debug 版本,没有 d 则表示 Release 版本;u 表示 Unicode 版本,没有 u 表示 ANSI 版本。选择不同的版本库,编译出来的库文件路径及其头文件路径也是不一样的,例如 msw、mswd、mswu、mswud 分别对应采用 ANSI 字符集的 Release 版本、采用 ANSI 字符集的 debug 版本、采用 Unicode 字符集的 Release 版本、采用 Unicode 字符集的 Debug 版本;再如 wxbase30.lib、wxbase30d.lib、wxbase30u.lib、wxbase30ud.lib 分别对应采用 ANSI 字符集的 Release 版本、采用 ANSI 字符集的 Debug 版本、采用 Unicode 字符集的 Release 版本、采用 Unicode 字符集的 Debug 版本,且它们都是静态库。版本库在调试起见,使用 Debug 版;正式发布时,肯定需要 Release 版,这也是 Code::Blocks 源代码中的 cbp 工程文件所需要使用的 wxWidgets 版本;至于程序源代码字符集采用的是 ANSI 还是 Unicode,可在工程“属性”->“常规”->“字符集”里面查看与设置。例如采用 Unicode 字符集的 Release 版本动态库的编译方法

> mingw32-make -f makefile.gcc MONOLITHIC=0 SHARED=1 UNICODE=1 BUILD=debug

采用 ANSI 字符集的 Debug 版本静态库的编译方法

> mingw32-make -f makefile.gcc MONOLITHIC=0 SHARED=0 UNICODE=0 BUILD=debug

无论哪种编译结果,可分别在 C:\wxWidgets-3.0.1\lib\gcc_dll\mswudC:\wxWidgets-3.0.1\lib\gcc_lib\mswd 及其上层目录看到很多 wxWidgets 头文件与库文件。若想把 wxWidgets 库文件变成一个,可启用 MONOLITHIC 参数。另外一个参数 vendor 值得一提,它是指编译或者发布 wxWidgets 库的作者或机构,默认是 custom,而由 Code::Blocks 团队发布的 wxWidgets 库的 vendor 则是 cb。若重新调整编译参数之后再编译,最好先清理先前编译留下的残余。于是可尝试

> mingw32-make -f makefile.gcc MONOLITHIC=1 SHARED=1 UNICODE=1 BUILD=release vendor=juk clean
> mingw32-make -f makefile.gcc MONOLITHIC=1 SHARED=1 UNICODE=1 BUILD=release vendor=juk

编译之后可在 C:\wxWidgets-3.0.1\lib\gcc_dll\mswu 及其上层目录中看到编译好的头文件与库文件。 有关编译过程的详细参数说明请看文件 C:\wxWidgets-3.0.1\build\msw\config.gcc;详细安装说明看文件 C:\wxWidgets-3.0.1\docs\msw\install.txt

2、若想编译最新的 wxWidgets 源码,可从 wxWidgets 项目的源代码仓库中拖源代码。目前,该仓库由版本管理工具 git 管理,故先在 msysgit 提供的 Git Shell 中拖源代码:

$ cd /c/
$ git clone https://github.com/wxWidgets/wxWidgets.git wxWidgets_git

然后可在 MinGW Shell 中执行编译过程

$ cd /c/wxWidgets_git
$ ./autogen.sh
$ mkdir mswbuild && mswbuild
$ ../configure
$ make

当然,这是 Linux 中的开发版源代码的典型处理方法。如果没有安装 MSYS 基本系统,也可采用 MS Windows 平台的典型编译方法,例如在命令行窗口中执行

> cd C:\wxWidgets_git\build\msw
> mingw32-make -f makefile.gcc MONOLITHIC=1 SHARED=0 UNICODE=0 BUILD=release vendor=juk

编译之后可在 C:\wxWidgets_git\lib\gcc_lib\msw 及其上层目录中看到编译好的 Debug 版的头文件与静态库文件。如果有兴趣的话,自行比较一下 MS Windows 平台中不同编译参数下生成的库文件的大小。

3、如果不想自己编译,可以到 http://sourceforge.net/projects/wxpack 下载已经编译好的库(wxPack)的最新版本,目前是 wxPack_v2.8.12.01.exe。一般 wxPack 的版本相比源码编译的版本要老。wxPack 的安装目录可选在 C:\wxWidgets-2.8。值得一提的是,wxPack 包提供了供 VC、GCC 使用的各种版本的库文件,还提供了图形界面快速构建工具 wxformbuilder。wxformbuilder 对于本身没有为 wxWidgets 提供快速构建工具的集成开发环境(例如 Visual C++、Visual Studio、Xcode 等)提供了极大的方便。它的官方主页 http://www.wxformbuilder.org

4、现在,可以利用 wxWidgets 库创建 wxWidgets 项目应用程序。不过,由于库文件的使用是个比较复杂的问题,此地为简单起见,以稳定版源码包编译并安装到 MSYS 基本系统的 wxWidgets 库为例,测试一下前面编译的 wxWidgets 是否能够正常使用。在 MinGW Shell 中执行

$ notepad.exe sam.cpp
#include <wx/wx.h>

class Simple: public wxFrame
{
public:
    Simple(const wxString& title);
};

class MyApp: public wxApp
{
public:
    virtual bool OnInit();
};

Simple::Simple(const wxString& title) :
    wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 150))
{
    Centre();
}

IMPLEMENT_APP (MyApp)

bool MyApp::OnInit()
{
    Simple *simple = new Simple(wxT("Simple"));
    simple->Show(true);
    return true;
}

接着编译并运行它

$ g++ sam.cpp `wx-config --cxxflags --libs`
$ sam.exe

当然,如果没有安装 MSYS 基本系统的话,在 MS Windows 命令行窗口(cmd.exe)执行也可以,只要配置好了环境变量,也即配置好全局 PATH 保证能够找到 wx-config;不过最好还是等到将 wxWidgets 整合到集成开发环境之后再来试比较好。实际上,wxWidgets 自带了 demo 程序用来测试 wxWidgets 库是否正常工作,例如

> cd C:\wxWidgets-3.0.1\demos\bomb\
> mingw32-make -f makefile.gcc

不过由于 demo 程序很久没人维护,必定会报错。不过不用担心,编译报错的原因只是 makefile.gcc 中的 CXXFLAGS 需要增加 -I..\..\lib\gcc_dll\mswu\wx\include\msw-unicode-3.0,可试试下面的命令

> mingw32-make -f makefile.gcc
> bomb.exe

四、整合 MinGW、wxWidgets 与集成开发环境

使用 wxWidgets 开发库是个头疼的问题,首先,系统中可能同时有多个版本的 wxWidgets 开发库;其次,编译出来的开发库可能是静态库,也可能是动态库;再次,在程序编译与运行过程中,动态库的加载有顺序问题。此类问题对于如何在 Code::Blocks 使用 wxWidgets 开发库造成了一些麻烦。不过,稍微留意一下附录中提到的 MS Windows 系统中动态库的加载顺序,就会有很多解决方案。例如将库文件放在程序可执行文件的目录中;或者放在通过环境变量 PATH 指定的某个路径中。为了避免因设置全局 dll 路径而引起 dll 灾难(dll hell),MS Windows 程序发布往往采用前者。

刚刚指出了运行程序时如何解决库文件的搜索问题。但是,由于开发过程不仅牵涉到程序运行,还要保证程序的正常编译,这就要保证不仅库文件要被找到,还有与库文件关联的头文件也要被找到。要解决库及其头文件的放置能够让程序正常编译,比较好的办法是通过 GCC 编译器的编译参数。以下就来谈谈将 MinGW、wxWidgets 与集成开发环境整合成整体。

先来说说全局配置 wxWidgets 库,主要介绍 5 种方法。当然,这些方法之间还能相互共用产生更多的方法,特别是再结合后面要谈到的工程相关(局部)配置方法。作为日常使用 Code::Blocks 来说,只需要掌握工程相关(局部)配置方法就可以了。话说回来,集成开发环境的库配置方法所涉及的原理不仅限于 Code::Blocks,同样适用于众所周知的集成开发环境(例如 Visual C++、Visual Studio、Dev-C++、QT-Creator、CodeLite、Xcode 等)。

1、由于 GCC 编译器可以通过 GCC 编译参数的编译参数找到它们所需要的库文件与头文件,于是通过设置编译选项与链接选项即可达成目的。

1.1、设置编译选项。先在 MinGW Shell 中执行

$ wx-config --cxxflags
-I/usr/local/lib/wx/include/msw-unicode-3.0 -I/usr/local/include/wx-3.0 -D_LARGEFILE_SOURCE=unknown -DWXUSINGDLL -D__WXMSW__ -mthreads

然后开启 Code::Blocks,将 -IC:\MinGW\MSYS\1.0\local\lib\wx\include\msw-unicode-3.0 -IC:\MinGW\MSYS\1.0\local\include\wx-3.0 -D_LARGEFILE_SOURCE=unknown -DWXUSINGDLL -D__WXMSW__ -mthreads 拷贝到主菜单 Settings -> Compiler...,Global Compiler settings -> Compiler settings -> Other options;

1.2、设置链接选项。在 MinGW Shell 中执行

$ wx-config --libs
-L/usr/local/lib -Wl,--subsystem,windows -mwindows -lwx_mswu_xrc-3.0 -lwx_mswu_webview-3.0 -lwx_mswu_html-3.0 -lwx_mswu_qa-3.0 -lwx_mswu_adv-3.0 -lwx_mswu_core-3.0 -lwx_baseu_xml-3.0 -lwx_baseu_net-3.0 -lwx_baseu-3.0

然后将 -LC:\MinGW\MSYS\1.0\local\lib -Wl,--subsystem,windows -mwindows -lwx_mswu_xrc-3.0 -lwx_mswu_webview-3.0 -lwx_mswu_html-3.0 -lwx_mswu_qa-3.0 -lwx_mswu_adv-3.0 -lwx_mswu_core-3.0 -lwx_baseu_xml-3.0 -lwx_baseu_net-3.0 -lwx_baseu-3.0 拷贝到 Settings -> Compiler...,Global Compiler settings -> Linker settings -> Other linker options。

实际上,若在 Linux 上配置 wxWidget 库的话,那么编译选项与链接选项的设置更为简捷,只需主菜单 Settings -> Compiler...,Global Compiler settings -> Compiler settings -> Other options 编译选项设置为 `wx-config --cxxflags`;Settings -> Compiler...,Global Compiler settings -> Linker settings -> Other linker options 链接选项设置为 `wx-config --libs`。这种设置方法在 Linux 中很有优势,不过在 MS Windows 中无法使用。

另外,以上设置方法对于在非工程模式下编译源代码文件非常有效。例如按上法配置完 wxWidgets 库之后,在 Code::Blocks 中新建空文件,也即 File -> New -> Empty File,然后将前面 sam.cpp 的内容复制进来,并保存重命名为 sam.cpp。试试 Build。

2、通过分离 GCC 编译选项中的路径选项也可配置 wxWidgets 库。

2.1、设置编译选项。开启 Code::Blocks,进入主菜单 Settings -> Compiler...,Global Compiler settings -> Compiler settings -> Other Options,将 -D_LARGEFILE_SOURCE=unknown -DWXUSINGDLL -D__WXMSW__ -mthreads 加入。

2.2、设置链接选项与库文件。在 Settings -> Compiler...,Global Compiler settings -> Linker stettings 标签页中的 Other linker options 文本框中加入 -Wl,--subsystem,windows -mwindows;接着在 Global Compiler settings -> Linker stettings 标签页的对话框 Link libraries 下,点击 ADD 按钮,将 C:\wxWidgets-3.0.1\lib\gcc_dll\mswu\ 中所需要的库一一选中加入即可。

2.3、设置搜索目录。Settings -> Compiler...,Global Compiler settings -> Search directories -> Compiler 设置头文件目录为 C:\wxWidgets-3.0.1\includeC:\wxWidgets-3.0.1\lib\gcc_dll\mswu\wx\include\msw-unicode-3.0。注意,这里没有设置库文件的搜索路径,原因在于前一步中装入的库文件名是绝对路径。如果上一步加入的库文件只有文件名没有路径的话,那么这一步还要设置库文件的搜索路径,也即 Settings -> Compiler...,Global Compiler settings -> Search directories -> Linker 设置库文件目录为 C:\wxWidgets-3.0.1\lib\gcc_dll\mswu\

这种设置方法与第一种全局设置方法的差异在于 wx-config 输出中的 -I、-L 以及 -l 参数(也可部分地)替代成了路径与文件名。

3、通过环境变量配置全局设置库文件及其头文件的路径也是一种途径。

全局设置库文件及其头文件的路径是 Linux 的常用方法,例如 Linux 系统常常将库文件放入 /usr/lib 而头文件则放入 /usr/include。此地利用 MSYS 基本系统来做类似的事情,假设已将 wxWidgets 库装入 C:\MinGW\msys\1.0\local

3.1、设置编译选项。开启 Code::Blocks,进入主菜单 Settings -> Compiler...,Global Compiler settings -> Compiler settings -> Other Options,加入 -D_LARGEFILE_SOURCE=unknown -DWXUSINGDLL -D__WXMSW__ -mthreads

3.2、设置链接选项。在 Settings -> Compiler...,Global Compiler settings -> Linker stettings 标签页中的 Other linker options 文本框中加入 -Wl,--subsystem,windows -mwindows;接着在 Global Compiler settings -> Linker stettings 标签页的对话框 Link libraries 下面,点击 ADD 按钮后弹出的文件选择对话框中将 C:\MinGW\msys\1.0\local\lib\ 目录下的文件全选就可以将所有选中的文件一次性加。

3.3、设置全局环境变量来替代搜索目录的设定,例如

> SETX LIBRARY_PATH "%LIBRARY_PATH%;C:\MinGW\lib;C:\MinGW\msys\1.0\local\lib"
> SETX C_INCLUDE_PATH "C:\MinGW\msys\1.0\local\include"
> SETX CPLUS_INCLUDE_PATH "C:\MinGW\msys\1.0\local\include"

需要注意,这种方法毕竟与 MS Windows 习惯不同,故而在 MS Windows 平台很少使用。

4、通过 Code::Blocks 的全局变量也可配置 wxWidgets 库。

Code::Blocks 的全局变量可在工程创建期间使用,也可在各个配置选项卡中使用,下面通过全局变量配置 wxWidgets 库给出引用这些变量的方法。

4.1、设置全局变量。点击主菜单 Setting -> Global Variables...,会弹出一个 Global Variable Editor 的窗口, 在该窗口的 default 变量集下新建立一个 wx 变量,在左下 Build-in fields 的 base 中填入 C:\wxWidgets-3.0.1、include 中填入 C:\wxWidgets-3.0.1\include、lib 中填入 C:\wxWidgets-3.0.1\lib\gcc_dll\mswu、cflags 中填入 -D_LARGEFILE_SOURCE=unknown -DWXUSINGDLL -D__WXMSW__ -mthreads、lflags 中填入 -Wl,--subsystem,windows -mwindows -lwx_mswu_xrc-3.0 -lwx_mswu_webview-3.0 -lwx_mswu_html-3.0 -lwx_mswu_qa-3.0 -lwx_mswu_adv-3.0 -lwx_mswu_core-3.0 -lwx_baseu_xml-3.0 -lwx_baseu_net-3.0 -lwx_baseu-3.0。 除去 Build-in fields 之外,还可以有 user-defined fields(自定义域)。

4.2、使用全局变量。从主菜单 Settings -> Compiler...,Global Compiler settings -> Compiler settings -> Other Options 中填入 $(#wx.clfags);Global Compiler settings -> Linker settings -> Other linker options 中填入 $(#wx.lflags);在 Global Compiler settings -> Search directories -> Compiler 中填入 $(#wx.include)$(#wx.lib)\wx\include\msw-unicode-3.0.1;在 Global Compiler settings -> Search directories -> Linker 中填入 $(#wx.lib)

从配置过程可以看到引用 Code::Blocks 的全局变量 wx 的方法是 $(#wx),引用 Build-in fields(或 user-defined fields)lib 的方法是 $(#wx.lib)。另有一点,带域的全局变量,如 $(#wx.include)、$(#wx.lib) 等,有缺省值。例如不给定 $(#wx.lib) 的值,则默认为 (#wx)\lib。但是,带域的全局变量不能缺省,例如 $(#wx) 本身是不能缺省的,否则会报错。

实际上,也可以在 Code::Blocks 中定义全局定制变量(custom variable),也即打开主菜单 Settings -> Compiler...,Global Compiler settings -> Custom variables,点击 ADD 添加按钮增加变量,供 Global Compiler settings 子选项卡中的各个设定使用。例如设置定制变量(custom variable) VENDOR,引用的方法是 $(VENDOR)。一般而言,定制变量的使用不要太依赖于外部程序。

5、Code::Blocks 的全局变量结合系统环境变量也是一种方法。

由于 Code::Blocks 的全局变量可以引用系统的全局变量,因此可通过系统环境变量配置 wxWidgets 库。例如,在环境变量里添加一个 wxWidgets 根目录环境变量,这里命名为:WXWIN,值为 C:\wxWidgets-3.0.1,例如

> setx WXWIN "C:\wxWidgets-3.0.1"

然后再打开主菜单 Settings -> Global Variables...,在 Global Variables Editor 窗口的 default 变量集下新建立一个 wx 变量,在左下 Build-in fields 的 base 中填入 ${WXWIN},include 中填入 ${WXWIN}\include${WXWIN}\lib\gcc_dll\mswu\wx\include\msw-unicode-3.0.1,lib 中填入 ${WXWIN}\lib\gcc_dll\mswu。由此,可以看到 Code::Blocks 引用系统的环境变量方法类似与 Bash Shell 中的变量引用。

为了与前一种设定方法相比较体现出新意,这里将全局变量用在 wxWidgets 工程向导里。设置完成后,尝试建立 wxWidgets 工程。先通过菜单 File -> New -> Project...,选择最后面的 wxWidgets 工程。点击 Go 进入工程配置向导,首先会出来一个欢迎窗口,在这里直接下一步。在选择已安装的 wxWidgets 版本时请注意,由于安装的 wxWidgets 版本是 3.0.1,所以选择它。接下来的就是 wxWidgets 环境的一些设置了,这里根据刚才设置的 wxWidgets 根目录,直接填入 $(#wx)。剩下几步很容易自行完成。另外,该工程引用的全局变量是来自 default 变量集;如有需要,可在 Setting -> Global Variables... 弹出一个 Global Variable Editor 的窗口定义更多的变量集,同时可在主菜单 Project -> build options,Project build options -> EnvVars options 中选择要使用的变量集。

全局配置 wxWidgets 库的方法谈到这里。前 4 种全局配置方法(第 5 中全局变量配置已针对 Code::Blocks 工程了)对于使用 wxWidgets 库的非工程模式的源代码编译很有帮助。但是可以看到弱点,那就是很多用不到 wxWidgets 库的源代码也在不必要的使用这些编译选项、链接选项,这可能造成错误。因此,有必要说说如何避免全局配置 wxWidgets 库了。首先,对于非工程模式的(特别是单文件)源代码,尽量在命令行环境中而不要在集成开发环境中开发;如果非要在集成开发环境中进行的话,将非工程模式的源代码导入集成开发环境的工程中来。而对于那些由 Code::Blocks 工程管理的使用 wxWidgets 库的源代码,配置使用 wxWidgets 库的方法最好是基于项目的,也即局部配置。此种配置方法只需要使用 Code::Blocks 的工程属性便能实现。

下面仅给出局部配置 wxWidgets 库的一种方法。借鉴前面的全局配置方法,很容易给出更多的局部配置方法。 先启动 Code::Block,打开或者创建一个 wxWidgets 工程,随后点击主菜单 Project -> build options,打开的 Project build options 子标签。

1、设置编译选项。在 Compiler settings -> Other options 子标签页中加入编译选项 -D_LARGEFILE_SOURCE=unknown -DWXUSINGDLL -D__WXMSW__ -mthreads

2、设置链接选项与库文件。在 Linker settings -> Link libraries 中将 wxWidgets 库的所有库文件(动态库或者静态库)加入,也即点击 ADD 按钮后弹出的文件选择对话框中将 C:\wxWidgets-3.0.1\lib\gcc_dll\mswu\ 目录下的文件全选一次性加入;在 Linker settings -> Other Linker options 子标签页中加入链接选项 -Wl,--subsystem,windows -mwindows

3、设置搜索目录。在 Search directories -> Compiler 子标签中加入 wxWidgets 头文件的路径:C:\wxWidgets-3.0.1\includeC:\wxWidgets-3.0.1\lib\gcc_dll\mswu\wx\include\msw-unicode-3.0.1;若上一步的 Link libraries 已带有绝对路径,就不必设库文件的搜索路径了。不然还需在 Search directories -> Linker 子标签中加入库文件路径:C:\wxWidgets-3.0.1\lib\gcc_dll\mswu\。 同样地,也可以在工程属性中定义定制变量,也即 Project -> build options,Project build options -> Custom variables,点击 ADD 添加按钮增加变量,供 Project build options 的子选项卡中的各个设定使用。例如定义工程相关的定制变量 RELEASE,引用的方法是 $(RELEASE)。

五、编译 Code::Blocks 源代码

源码编译 Code::Blocks,也有两种方案:稳定版源码编译以及开发版源码编译。值得提到的是三点:一、不借助 MSYS 直接在 Windows 平台上编译 Code::Blocks 源代码,最好使用 Code::Blocks 二进制文件来完成源代码的编译,这就是所谓的自举;二、用 Code::Blocks 编译 Code::Blocks 源代码,需要使用 Unicode 字符集 Release 版的 wxWidgets 库,除非修改 cbp 工程文件;三、用 Code::Blocks 编译 Code::Blocks 源代码,还需确保 zip.exe 在环境变量 PATH 指定的路径中,最好还能保证 svn.exe 也在其中。

先来说说稳定版源码的编译过程,先到 Code::Blocks 的官网下载最新的稳定版源码,当前是 codeblocks_13.12-1.tar.gz,将它下载后解压到 C:\CBSC。现在用 Code::Blocks 打开 C:\CBSC\src\ 目录中的 CodeBlocks_wx30.cbp(根据 wxWidgets 库的版本以及 CPU 的类型选择),打开过程中会弹出两次 Global Variable Editor 窗口;第一次弹出的 Global Variable Editor 窗口中 Current Variable 项中的内容应该是 wx,在左下 Built-in fields 的 base 中填写 wxWidgets 库所在目录,例如 C:\wxWidgets-3.0.1,然后点 Close 按钮;第二次弹出的 Global Variable Editor 窗口中 Current Variable 项中的内容应该是 cb_release_type,左下 Built-in fields 的 base 中要填写 Code::Blocks 的编译版本类型,若是 Debug 版,请填写 -g,若是发布版本,请填写 -O2,一般选择 Debug 版本,然后点 Close 按钮;随后点主菜单上的 Build 开始编译 Code::Blocks。如果一切正常,会在 C:\CBSC\src\devel30 目录中出现编译好的 codeblocks.exe,试试运行它。如果没有发现任何问题,修改 cb_release_type 的值为 -O2,再次编译,并在命令行窗口中执行

> cd C:\CBSC\src
> update30.bat

这样会在 C:\CBSVN\src\output30 目录中出现正式发布的 codeblocks.exe。为了 Code::Blocks 运行不受动态库版本与路径的干扰,可复制 wxWidgets 库文件至该目录。当然,刚刚编译好的 Code::Blocks 是没有插件的,不过编译插件的步骤大同小异。用 Code::Blocks 打开 C:\CBSC\src 目录下的 ContribPlugins.workspace,根据需要选择要编译的插件项目,过程与 Code::Blocks 编译相仿。

若想编译最新的开发版代码,用 TortoiseSVN 或者在它的可执行文件路径下可执行

> cd C:\
> svn co svn://svn.code.sf.net/p/codeblocks/code/trunk CBSVN

从 SVN 版本库编译可在 MinGW Shell 中执行下述命令

$ cd /c/CBSVN
$ ./bootsrap
$ mkdir mswbuild && cd mswbuid
$ ../configure --with-contrib-plugins=all
$ make

需要注意这是以 Linux 的方式编译 Code::Blocks,一定要保证 wxWidgets 库已被安装到 MSYS 基本系统,且 wx-config 有正常输出。

对于没有 MSYS 基本系统的用户,可在 MS Windows 命令行窗口(cmd.exe)中设置环境变量

> cd C:\CBSVN\src
> set CB_ROOT=C:\CodeBlocks\
> set GCC_ROOT=C:\MinGW\bin\

主要是指定二进制版 Code::Blocks 的安装位置以及 GCC 编译器(这里是指 MingW)的可执行文件目录位置。接着执行

> batch_build_core_30.bat

之后与前面一样会两次弹出 Global Variable Editor 窗口;第一次弹出的 Global Variable Editor 窗口中 Current Variable 项中的内容应该是 wx,在左下 Built-in fields 的 base 中填写 wxWidgets 库所在目录,例如 C:\wxWidgets-3.0.1,然后点 Close 按钮;第二次弹出的 Global Variable Editor 窗口中 Current Variable 项中的内容应该是 cb_release_type,左下 Built-in fields 的 base 中要填写 Code::Blocks 的编译版本类型,填写 -g,然后点 Close 按钮;随后点主菜单上的 Build 开始编译 Code::Blocks。如果一切正常,会在 C:\CBSVN\src\devel30 目录中出现编译好的 codeblocks.exe,试试运行它。如果没有发现任何问题,那么可执行

> update30.bat

这样会在 C:\CBSVN\src\output30 目录中出现正式发布的 codeblocks.exe。当然,编译好的 Code::Blocks 是没有 contrib 插件的,要编译插件编译只需接着执行

> batch_build_all_30.bat
> update30.bat

即可。

若想发布刚刚编译好的 Code::Blocks,可以采用 zip 包的形式。当然,对于普通用户来说还是为它提供一个打包的安装程序比较合适。MS Windows 上收费的打包安装程序有很多,例如 Visual Studio 自带的安装程序、InstallShield 等;也有很多免费的打包安装程序,例如 NSIS 或者 Inno Setup 等。根据自己的需要选用它们,官方推荐使用的是 NSIS 脚本,如想使用可用下述方式检出

> svn co svn://svn.code.sf.net/p/codeblocks/code/setup

自行修改其中的 setup.nsi 脚本。

附录

MS Windows 中动态链接库(dll)的搜索顺序

MS Windows 系统可以包含同一个动态链接库(dll) 的多个版本。应用程序能够通过使用动态链接库重定向或清单文件指定要加载的 DLL 的全路径。下面谈谈具体的动态库搜选顺序,详细内容请参考 http://msdn2.microsoft.com/en-us/library/ms682586.aspx

一、标准的搜索顺序

DLL 的搜索顺序取决于是否安全 DLL 搜索模式是启用或禁用。安全 DLL 搜索模式在默认状态下是启用的。通过创建 HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode 注册表项并将它的值设为0可以关闭这个属性。直到 Windows XP 与 Windows 2000 with SP4,安全 DLL 搜索模式在默认状态下是禁用的。通过创建 HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode 注册表项并将它的值设为1可以启用这个属性。

假如安全 DLL 搜索模式启用,搜索顺序如下:

  • 应用程序所在的路径;
  • Windows SYSTEM 目录。通过调用 GetSystemDirectory 函数可以获取这个目录的路径;
  • 16 位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找;
  • Windows 目录。通过调用 GetWindowsDirectory 函数可以获取这个目录的路径;
  • 当前目录;
  • PATH 环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为 DLL 的搜索路径。

假如安全 DLL 搜索模式禁用,搜索顺序如下:

  • 应用程序所在的路径;
  • 当前目录;
  • Windows SYSTEM 目录。通过调用 GetSystemDirectory 函数可以获取这个目录的路径;
  • 16 位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找;
  • Windows 目录。通过调用 GetWindowsDirectory 函数可以获取这个目录的路径;
  • PATH 环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为 DLL 的搜索路径。

二、预备的搜索顺序

由系统指定的标准搜索顺序可以通过调用 LoadLibraryEx 函数加上 LOAD_WITH_ALTERED_SEARCH_PATH 参数值得到改变。标准搜索顺序也可以通过调用 SetDllDirectory 函数得到改变。如果您指定一个备用的搜索顺序,程序将按备用的搜索顺序进行搜索,直到所有相关的可执行模块被找到。系统启动后,DLL 初始化例程处理,该系统将恢复为标准的搜索顺序。

LoadLibraryEx 函数通过指定 LOAD_WITH_ALTERED_SEARCH_PATH 属性和 lpFileName 参数指定一个绝对路径支持一个预备的搜索顺序。请注意:标准搜索顺序和通过调用指定 LOAD_WITH_ALTERED_SEARCH_PATH 属性的 LoadLibraryEx 函数来设置的预备搜索顺序只是有一点不同:标准搜索顺序开始于搜索应用程序所在的路径而预备搜索顺序开始于 LoadLibraryEx 函数所要加载的可执行模块的所在目录。

假如安全 DLL 搜索模式启用,搜索顺序如下:

  • lpFileName 参数值所指定的目录;
  • Windows SYSTEM 目录。通过调用 GetSystemDirectory 函数可以获取这个目录的路径;
  • 16 位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找;
  • Windows 目录。通过调用 GetWindowsDirectory 函数可以获取这个目录的路径;
  • 当前目录;
  • PATH 环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

假如安全 DLL 搜索模式禁用,搜索顺序如下:

  • lpFileName 参数值所指定的目录;
  • 当前目录;
  • Windows SYSTEM 目录。通过调用 GetSystemDirectory 函数可以获取这个目录的路径;
  • 16 位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找;
  • Windows 目录。通过调用 GetWindowsDirectory 函数可以获取这个目录的路径;
  • PATH 环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

假如 lpPathName 参数指定了一个路径,SetDllDirectory 函数支持一个预备的搜索顺序。这个预备的搜索顺序如下:

  • 应用程序所在的路径;
  • lpFileName 参数值所指定的目录;
  • Windows SYSTEM 目录。通过调用 GetSystemDirectory 函数可以获取这个目录的路径;
  • 16 位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找;
  • Windows 目录。通过调用 GetWindowsDirectory 函数可以获取这个目录的路径;
  • PATH 环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

如果 lpPathName 参数为一个空字符串,当前目录将会从搜索顺序中删除。

SetDllDirectory 有效地禁用安全 DLL 搜索模式,而在搜索指定的目录路径。要恢复安全 DLL 搜索模式的 SafeDllSearchMode 注册表值的基础和恢复当前目录到搜索顺序,调用 lpPathName 的参数值为 NULL 的 SetDllDirectory 函数。