V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
raawaa
V2EX  ›  程序员

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

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

    想尝试一下自己能不能入门 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   ·   实用小工具   ·   3042 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 13:43 · PVG 21:43 · LAX 05:43 · JFK 08:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.