想尝试一下自己能不能入门 C++,给自己设了一个小目标:撸一个跨平台带 GUI 的 Hello World。GUI 库选择了 wxWidgets。最后花了一整个礼拜的下班时间才搞出来。在这里记下折腾过程。需要分几篇才能写完:
废话不多,开始吧!
下载源码包之后根据源码目录里的文档进行编译。编译过程非常顺利。
Windows 下编译 wxWidgets 有很多选择,微软 msvc 或者 MinGW gcc 都行。我下载时( 2018 年 5 月) wxWidgets 的最新稳定版 3.0.4 直接提供了各种编译器的 Makefile,直接使用即可——据说之后新版会用 CMake 来管理构建。
最终编译结果(二进制库文件)会根据所使用的编译器和编译选项,存储在源码目录的 lib
子目录中。例如我使用 msvc 编译器,并指定要带 UNICODE 支持的 DEBUG 版本。则编译结果存储在 <wxWidgets 源码根目录>/lib/mswud
中。mswud
中的 u
和 d
分别代表 UNICODE 支持和 DEBUG 版本。
有了所依赖的 GUI 图形库,就可以着手新建自己的项目了。项目结构如下:
wxtest
└── main.cpp
main.cpp
的内容直接拷贝了 wxWidgets 官网文档中的范例。
因为要跨平台( Windows 和 Linux ),同时不想框死在某个 IDE 下,试着用 CMake 作为构建工具。项目根目录下加入 CMakeLists.txt
:
wxtest
├── CMakeLists.txt
└── main.cpp
第一次写 CMakeLists.txt
,能不能 work 全靠人品😒(事后证明不 work,哈哈😂):
# wxtest/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(wxtest)
aux_source_directory(. srcs)
include_directories($ENV{WXWIN}/include/msvc
$ENV{WXWIN}/include)
link_directories($ENV{WXWIN}/lib/mswud)
add_executable(${PROJECT_NAME} ${srcs})
target_link_libraries(${PROJECT_NAME} 加入的库太多了不想打字了此处省略)
解释一下。WXWIN
是我自己设置的系统环境变量,指定了 wxWidgets 源码根目录的路径。include_directories
和 link_directories
指令告诉编译器该去哪里找 wxWidgets 的头文件和链接库。target_link_libraries
告诉连接器把先前编译好的 wxWidgets 库文件链接进来。
看起来很完美啊,我们来编译一下……
> cmake . -G "MinGW Makefiles"
> mingw32-make -f makefile
编译过程中发生了许多链接错误,显然是有些依赖的库没有找到。我尝试了在 CMakeLists.txt
中改变 wxWidgets 链接库的顺序;也试过重新把 wxWidgets 编译成单个库文件(默认编译选项为编译成多个独立模块库文件)。都没法解决。最可疑的还是自己手写的 CMakeLists.txt
。研究了一阵子后,重写了 CMakeLists.txt
:
# wxtest/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(wxtest)
aux_source_directory(. srcs)
add_executable(${PROJECT_NAME} ${srcs})
set(wxWidgets_ROOT_DIR $ENV{WXWIN})
set(wxWidgets_CONFIGURATION mswud)
find_package(wxWidgets COMPONENTS net gl core base)
if(wxWidgets_FOUND)
include(${wxWidgets_USE_FILE})
target_link_libraries(${PROJECT_NAME} ${wxWidgets_LIBRARIES})
endif()
改写后的 CMakeLists.txt
通过 find_package
指令调用 FindwxWidgets
这个 CMake 模组去自动寻找 wxWidgets 的头文件和库文件位置。
读 FindwxWidgets.cmake
的源码可以知道,在 Windows 下 FindwxWidgets
模组的行为是根据 wxWidgets_ROOT_DIR
和 wxWidgets_CONFIGURATION
这两个变量的值去寻找相关文件。所以在 find_package
指令前,需要正确设置这两个变量的值。
尝试再次编译,成功!
读 FindwxWidgets.cmake
的源码可以知道,在 Windows 平台下,编译 wxWidgets 项目还需要链接一些额外的库:winmm comctl32 oleacc rpcrt4 shlwapi version wsock32 (推测是 wxWidgets 自身在 Windows 平台下的依赖)。而这些库在之前的 CMakeLists.txt
中都没有手动加进去,就会 link 不到啦。
wxWidgets 自身在 Windows 下还依赖哪些库,可能只有 wxWidgets 的作者自己才会知道——当然,如果有心看一下作者源码目录里示例项目的 makefile 也能发现——但是这次吃瘪的教训是,加入第三方库依赖的时候,还是要利用 CMake 提供的模组比较靠谱。好怀念那些带包管理器的「现代」语言😂。
在 Windows 下一个简单的 GUI 程序终于可以运行了。但是还有许多事情要做呢,因为:
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.