用 CMake 和 wxWidgets 造一个跨平台 Hello World(1) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
raawaa
V2EX    程序员

用 CMake 和 wxWidgets 造一个跨平台 Hello World(1)

 1  
  •   raawaa
    raawaa 2018-05-13 02:08:49 +08:00 4593 次点击
    这是一个创建于 2708 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想尝试一下自己能不能入门 C++,给自己设了一个小目标:撸一个跨平台带 GUI 的 Hello World。GUI 库选择了 wxWidgets。最后花了一整个礼拜的下班时间才搞出来。在这里记下折腾过程。需要分几篇才能写完:

    1. Windows 下项目构建(本篇)
    2. Linux 下的项目构建
    3. 改进项目目录结构( out-of-source build )
    4. 将整个 wxWidgets 源码库变成项目内的 git submodule (更好地控制版本依赖)

    废话不多,开始吧!

    Windows 下编译 wxWidgets

    下载源码包之后根据源码目录里的文档进行编译。编译过程非常顺利。

    Windows 下编译 wxWidgets 有很多选择,微软 msvc 或者 MinGW gcc 都行。我下载时( 2018 年 5 月) wxWidgets 的最新稳定版 3.0.4 直接提供了各种编译器的 Makefile,直接使用即可据说之后新版会用 CMake 来管理构建。

    最终编译结果(二进制库文件)会根据所使用的编译器和编译选项,存储在源码目录的 lib 子目录中。例如我使用 msvc 编译器,并指定要带 UNICODE 支持的 DEBUG 版本。则编译结果存储在 <wxWidgets 源码根目录>/lib/mswud 中。mswud 中的 ud 分别代表 UNICODE 支持和 DEBUG 版本。

    构建 Hello World 项目

    有了所依赖的 GUI 图形库,就可以着手新建自己的项目了。项目结构如下:

    wxtest └── main.cpp 

    main.cpp 的内容直接拷贝了 wxWidgets 官网文档中的范例。

    用 CMake 管理编译

    因为要跨平台( 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_directorieslink_directories 指令告诉编译器该去哪里找 wxWidgets 的头文件和链接库。target_link_libraries 告诉连接器把先前编译好的 wxWidgets 库文件链接进来。

    看起来很完美啊,我们来编译一下……

    > cmake . -G "MinGW Makefiles" > mingw32-make -f makefile 
    连接器错误 & FindwxWidgets

    编译过程中发生了许多链接错误,显然是有些依赖的库没有找到。我尝试了在 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_DIRwxWidgets_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 程序终于可以运行了。但是还有许多事情要做呢,因为:

    • 它目前还并没有跨平台;
    • 编译出来的可执行文件和 CMake 过程文件混在源代码目录里,一片混乱;
    • 别人要编译我的项目怎么办?需要自己下载相同版本的 wxWidgets 源码自己编译。如果别人下载的版本不对怎么办呢。是不是可以把 wxWidgets 的整个源码包含在自己的项目里,尽可能地做到 self-contained 呢……?
    8 条回复    2018-08-16 11:24:16 +08:00
    WildCat
        1
    WildCat  
       2018-05-13 02:18:16 +08:00
    正需要这个!感谢
    raawaa
        2
    raawaa  
    OP
       2018-05-13 02:33:00 +08:00 via Android
    @WildCat 凭记忆写的。代码中说不定有些小错误,呵呵。
    MCVector
        3
    MCVector  
       2018-05-13 03:35:00 +08:00 via Android
    1. 用 cmake -D<param> 可以传入变量,一般不需要使用环境变量。2. find_package 加 required 参数可以让它在找不到包的时候 fatal, 不需要自己判断。
    3. CMake 的卖点就是 out of source 编译,在非代码的文件夹里 run cmake 就行了。

    其实上手了以后 CMake 蛮好用的。
    raawaa
        4
    raawaa  
    OP
       2018-05-13 03:51:39 +08:00
    @MCVector #3 感觉 CMake 上手还挺难的。不过折腾了一个礼拜基本有点信心了。
    waruqi
        5
    waruqi  
       2018-05-13 07:19:42 +08:00 via Android
    换 xmake,上手很容易。。
    raawaa
        6
    raawaa  
    OP
       2018-05-13 17:15:49 +08:00 via Android
    @waruqi 感觉挺小众的
    waruqi
        7
    waruqi  
       2018-05-13 21:21:51 +08:00
    @raawaa 是的,只要好用就行,你可以试试。。
    itfanr
        8
    itfanr  
       2018-08-16 11:24:16 +08:00
    @raawaa xmake 试试吧
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5780 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 01:37 PVG 09:37 LAX 18:37 JFK 21:37
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86