如何使用 CMake 按需构建 wxwidgets 并与之链接

ari*_*ert 5 c++ wxwidgets build cmake

我有以下情况:

  • 我正在开发一个依赖于许多第三方库的应用程序,其中包括 wxwidgets
  • 我使用 Linux 作为我的构建主机系统为多个目标配置(x86、arm、Linux、Windows)构建应用程序
  • 由于上述多个目标配置,我选择使用 CMake 的 ExternalProject_Add 函数从源代码构建这些第三方库。
  • 第三方库是在与我的应用程序的 CMAKE_BINARY_DIR 分开的位置“按需”构建的,这样我就可以为我的应用程序擦除构建树,而无需重建第三方库(需要很长时间)。
  • 第三方库的位置根据我构建它们的目标配置而有所不同(显然)。

我对 CMake 很陌生,我目前面临的问题是:我的应用程序中的源文件找不到 wx 包含文件,我需要设置正确的链接器标志才能将我的应用程序链接到 wxwidgets。

这似乎是由实用程序“wx-config”处理的,该实用程序在使用 --cppflags 或 --libs 标志运行时提供该信息作为输出。但是,我无法弄清楚如何捕获该输出并将其附加到我从 CMakeLists.txt 文件设置的包含目录和链接库中。

所以基本上我想要的是。

  1. 为当前目标配置构建 wxwidgets(如果它不存在)
  2. 运行 wx-config --cppflags 和 --libs 以找出当前目标配置的正确包含目录和链接器标志
  3. 在构建属于我自己的应用程序的目标时使用步骤 2 中的信息

到目前为止,我已经尝试过这样的事情:

# Set a target-configuration-specific location 
set(wxwidgetsTop ${MYPROJECT_EXTERNAL_DIR}/wxwidgets/wxwidgets_${MYPROJECT_CURRENT_TARGET_CFG})

# Build the project
ExternalProject_Add( wxWidgetsExternal
  PREFIX ${wxwidgetsTop}
  URL ${MYPROJECT_EXTERNAL_DIR}/tarballs/wxWidgets-3.0.2.tar.bz2
  SOURCE_DIR ${wxwidgetsTop}/src/wxwidgets
  CONFIGURE_COMMAND ${configure_cmdline}
  BUILD_COMMAND make -j${MYPROJECT_NCPU}
  INSTALL_COMMAND make install
  )

# Create a wxwidgets target to be used as a dependency from other code
add_library(wxWidgets IMPORTED STATIC GLOBAL)
add_dependencies(wxWidgets wxWidgetsExternal)

# (non-working) attempt to get the correct include dirs and linker
# flags for wxwidgets 
add_custom_command(TARGET wxWidgetsExternal
  POST_BUILD
  COMMAND ${INSTALL_DIR}/bin/wx-config ARGS --cppflags
  COMMENT "Running wx-config"
)
Run Code Online (Sandbox Code Playgroud)

但是上面没有提供一种在构建构成我的应用程序的目标时实际使用自定义命令的结果来附加 cppflags 和链接器选项的方法。

什么是实现我想要的好方法?

Syn*_*xis 6

我看到三种不同的方法:

方法一:使用find_package

使用 wxWidgets 作为项目的独立需求,并期望开发人员在构建项目之前安装它。在您的 CMakeLists.txt 中,您需要调用find_package(wxWidgets),如下所示:

    find_package(wxWidgets COMPONENTS net gl core base)
    if(wxWidgets_FOUND)
        include(${wxWidgets_USE_FILE})
        # and for each of your dependent executable/library targets:
        target_link_libraries(<YourTarget> ${wxWidgets_LIBRARIES})
    endif()
Run Code Online (Sandbox Code Playgroud)

这样做的优点是,如果您重建项目,则不会重建库,但是它需要您的用户(他们需要手动处理 wxWidgets 的安装)和您(您需要设置 include paths /compileDefinitions/. .. 用手)。

方法2:嵌入wxWidgets

第二个选项是将 wxWidgets 捆绑在您的存储库(svn external 或 git 子模块)中,并且通常(重新)编写该库的 CMakeLists.txt 以面向目标。然后,在最顶层的 CMakeLists.txt 中,您可以执行以下操作:

    # for example, if you just need core and net:
    target_link_librairies(my_app PUBLIC wxWidgetsCore wxWidgetsNet)
    # No need to manually setup include dirs, etc...
Run Code Online (Sandbox Code Playgroud)

要使 CMakeLists.txt 面向目标,您可以为目标而不是目录定义包含目录和其他编译属性。例子:

    # When defining wxWidgetsCore, for example
    add_library(wxWidgetsCore ...)
    target_include_directories(wxWidgetsCore PUBLIC someDir)
    target_compile_definitions(wxWidgetsCore PUBLIC -pedantic)
    target_link_libraries(wxWidgetsCore PUBLIC someLib)
Run Code Online (Sandbox Code Playgroud)

这种方法的缺点是重建项目将触发 wxWidgets 的重建。但是,可以通过不使用“重建”而是“仅清理我的应用程序,然后构建”来解决此问题。以下是有关如何实现这一目标的一些见解

方法 3:某种混合方法

方法 2 的一大缺点导致了第三种方法:不要将 wxWidgets 放入项目中,而是创建一个将“导入”库的 CMakeLists.txt。想法:你向用户询问 wxWidgets 的安装目录,然后这个脚本将为你的项目设置一切。首先,将 CMakeLists.txt 放在这里:

    /your-project-root
        /thirdparty
            /wxWidgets
                CMakeLists.txt
    /dir-where-wxwidgets-is-installed
        ...
Run Code Online (Sandbox Code Playgroud)

现在,您定义一个导入的目标:

    # When defining wxWidgetsCore, for example
    set(WX_INCLUDE_DIR ${USER_SPECIFIED_WX_ROOT}/include)
    add_library(wxWidgetsCore IMPORTED GLOBAL)
    set_property(TARGET wxWidgetsCore APPEND PROPERTY
        INTERFACE_INCLUDE_DIRECTORIES ${WX_INCLUDE_DIR})
Run Code Online (Sandbox Code Playgroud)

请参阅INTERFACE_INCLUDE_DIRECTORIESINTERFACE_LINK_LIBRARIES。您需要您的用户在他的系统中的某个地方构建 wxWidgets,但从您的角度来看,您只需这样做target_link_libraries(your_app PUBLIC wxWidgets...),就像方法 2 中那样。优点是这种方法可以与方法 2 透明地互换,并且您不需要放置整个依赖项在你的项目中。


Cra*_*ott 1

设置 cppflags 和链接器标志必须在 CMake 时完成,但是您尝试在构建时运行 wx-config 并且无论如何都不会捕获其输出,因此除了将内容add_custom_command()打印到构建工具之外,您没有做任何有用的事情输出。

理想情况下,您将使用FindwxWidgetsCMake 已经提供的模块。它需要已经构建了 wxWidgets(但请参阅下文)。查看它的 CMake 文档,看看这是否至少听起来像您尝试使用 wx-config 手动实现的目标。如果您可以FindwxWidgets为您完成这项工作,那将是一种更干净的方法。

在配置时构建一些内容以便稍后可以在 CMakeLists.txt 文件中使用它有点棘手。在构建ExternalProject_Add()时下载并构建东西,但是您需要在配置时提前构建 wxWidgets 。我最近写了一篇文章,介绍如何在配置时至少完成下载部分,您应该能够调整它以在配置时完成整个构建。该文章使用 Google Test 作为示例,可以在此处找到:

https://crascit.com/2015/07/25/cmake-gtest/

将 wxWidgets 构建放在您喜欢的任何地方,而不仅仅是在该CMAKE_BINARY_DIR区域中,这将是微不足道的。这将允许您为每个构建配置拥有不同的 wxWidgets 构建,并且能够独立于 wxWidgets 构建来清除应用程序的构建树。

希望这能为您指明正确的方向。