cmake项目中使用第三方库的正确方法 [英] Correct way to use third-party libraries in cmake project

查看:17
本文介绍了cmake项目中使用第三方库的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理使用一些第三方库的项目.我可以将它们作为 git submodule 克隆并放入我的项目中,并使用 add_subdirectory 在我的项目中使用它们.但是编译这些库需要很多时间,而且我无法在我的项目中管理 cmake 变量,并且 install() 命令使我的包包含许多我不知道的东西'不需要.

I'm working on project that use some third-party libraries. I can clone and put them into my project as a git submodule and use add_subdirectory to use them in my project. But it take much time to compile these libs, and I can not manage cmake variables in my projects, and install() command make my package contains many things that I don't need.

那么在我的项目中使用第三方库的正确方法是什么.我不能告诉客户端安装这些库作为我项目的依赖项.

So what is correct way to use third-party libraries in my project. I can not tell the client to install these libraries as dependencies of my project.

推荐答案

回答这个问题需要涉及几个方面,你会发现以下两个部分:

Answering this question requires to cover few aspects, you will find below two sections:

  • 配置文件包
  • ExternalProject CMake 模块

如果您正在寻找不在项目范围内构建的集成库,第一步是确保这些库都提供了一个配置文件包.

If you are looking into integrating libraries that are not built within the scope of your project, the first step is to make sure the libraries all provide a config-file package.

一个配置文件包通常包括FooConfig.cmakeFooConfigVersion.cmakeFooTargets.cmake 等文件.

A config-file package usually include files like FooConfig.cmake, FooConfigVersion.cmake and FooTargets.cmake.

一般来说,如果库 Foo 已经在使用 CMake 并且已经提供了一个配置文件包,那么使用 -DFoo_DIR:PATH=/path/to/build-or 配置你的项目-install-dir/ 允许您从自己的项目中调用 find_package(Foo REQUIRED).这将导入您可以链接到您自己的库或可执行文件的 CMake 目标.

Generally speaking, if the library Foo is already using CMake and already provide a config-file package, configuring your project with -DFoo_DIR:PATH=/path/to/build-or-install-dir/ allow you to call find_package(Foo REQUIRED) from your own project. This will import CMake targets that you can link against your own libraries or executables.

现在,如果库 Foo 尚未使用 CMake,则有以下选项:

Now if the library Foois not already using CMake, there are options:

  • 案例 1:

  • Case 1:

  • (a) 库 Foo 已经在使用 CMake
  • (b) 但提供配置文件包
  • 行动:我建议改进他们的构建系统
  • (a) library Foo is already using CMake
  • (b) but do NOT provide a config-file package
  • action: I suggest to improve their build system

情况 2:

  • (1) 库 Foo 使用 CMake
  • (2) 和 Foo 的维护者愿意过渡到 CMake(或者至少将 CMakeLists.txt 与他们当前的构建系统一起使用)
  • 行动:我建议改进他们的构建系统
  • (1) library Foo is not using CMake
  • (2) and maintainer of Foo are willing to transition to CMake (or at least have the CMakeLists.txt along side their current build system)
  • action: I suggest to improve their build system

情况 3:

  • (1) 库 Foo 使用 CMake
  • (2) 和 Foo 的维护者不想过渡到 CMake
  • (3) 但维护者愿意从他们当前的构建系统生成配置文件包
  • action:我建议帮助他们.例如,这是为 Qt5 所做的,它现在提供了一个配置文件包.
  • (1) library Foo is not using CMake
  • (2) and maintainer of Foo do not want to transition to CMake
  • (3) but maintainer are willing to generate config-file package from their current build system
  • action: I suggest to help them. This is for example what was done for Qt5, it now provides a config-file package.

案例 4:

  • (1) 库 Foo 使用 CMake

(2) 和 Foo 的维护者不想(或还没准备好)过渡到 CMake.

(2) and maintainer of Foo do not want (or are not ready) to transition to CMake.

(3) 并且当前的构建系统运行不佳,或者库难以用更广泛的编译器构建,或者不支持交叉编译

(3) and the current build system is not working well, or the library is difficult to build with a wider range of compiler, or does not support cross-compilation

action:创建一个名为 foo-cmake-buildsystem 的项目(最好在 GitHub 上),该项目将允许通过以下任一方式构建库

action: create a project (ideally on GitHub) named foo-cmake-buildsystem that will allow to build the library by either

  • 使用现有源代码树的路径配置项目
  • 让项目为您下载源代码
  • 例如,这是为 CPython 完成的.GitHub 上有一个名为 python-cmake-buildsystem 的项目

案例 5:

  • (1) 出于任何原因,Foo 的维护者不想转换,或者无法维护替代构建系统,或者系统上已有库
  • action:您可以创建一个 FindFoo.cmake 来创建导入的目标.
    • 此类文件可以特定于您的项目,也可以直接贡献给 CMake
    • 例如FindOpenSSL.cmakeFindGit.cmake、...
    • (1) for any reason the maintainer of Foo do not want to transition, or maintaining an alternative build system is not possible, or library is already available on the system
    • action: You could create a FindFoo.cmake that would create imported targets.
      • such file could be specific to your project or could be contributed to CMake directly
      • this is for example the case of FindOpenSSL.cmake, FindGit.cmake, ...

      要了解有关配置文件包的更多信息,请参阅 https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html

      To learn more about config-file package, see https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html

      如果库 Foo 是:

      • (1) 在系统上不可用:
        • 或无法使用包管理器安装
        • 或者与维护软件包(debian、conda-forge、chocolatey 等)的社区合作来拥有这样的软件包是不可能的

        然后,ExternalProject CMake 模块将允许您从您自己的项目中下载、配置、构建...这些项目.

        Then, the ExternalProject CMake module will allow you to download, configure, build ... these projects from within your own project.

        实现这一目标的方法很少.

        There are few approaches to make this happen.

        这是一个运行良好的系统:您可以设置一个 2 级构建系统,我们称之为:SuperBuild.

        Here is one that has been working well: You could setup a 2-level build system that we call: SuperBuild.

        为了支持 SuperBuild 方法,您的 CMakeLists.txt 可以具有以下结构:

        To support the SuperBuild approach, your CMakeLists.txt could have the following structure:

        project(AwesomeProject)
        
        [...]
        
        option(Awesome_ENABLE_EXTRA "Enable more awesome stuff" OFF)
        
        option(AwesomeProject_SUPERBUILD "Build ${PROJECT_NAME} and the projects it depends on." ON)
        
        [...]
        
        if(AwesomeProject_SUPERBUILD)
          include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake")
          return()
        endif()
        
        find_package(Foo REQUIRED)
        
        add_library(AwesomeLib ....)
        target_library_libraries(AwesomeLib PUBLIC Foo)
        
        [...]
        

        然后,在文件 SuperBuild.cmake 中,您将大致有以下两个调用:

        Then, in the file SuperBuild.cmake you would roughly have these two calls:

        ExternalProject_Add(Foo
          GIT_REPOSITORY "git://github.com/Foo/Foo"
          GIT_TAG "123456"
          SOURCE_DIR ${CMAKE_BINARY_DIR}/Foo
          BINARY_DIR ${CMAKE_BINARY_DIR}/Foo-build
          CMAKE_CACHE_ARGS
            -DFOO_ENABLE_BAR:BOOL=1
          INSTALL_COMMAND ""
          )
        
        
        ExternalProject_Add(AwesomeProject
          SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
          BINARY_DIR ${CMAKE_BINARY_DIR}/AwesomeProject-build
          DOWNLOAD_COMMAND ""
          UPDATE_COMMAND ""
          CMAKE_CACHE_ARGS
            -Foo_DIR:PATH=${CMAKE_BINARY_DIR}/Foo-build
            -DAwesome_ENABLE_EXTRA:BOOL=${Awesome_ENABLE_EXTRA}
          INSTALL_COMMAND ""
          )
        

        这意味着您现在可以在子目录 AwesomeProject-build 中找到通常的构建树.

        This means that you usual build tree will now be found in the subdirectory AwesomeProject-build.

        注意Foo-buildAwesomeProject-build是两个独立的构建树,它们之间的链接是上面讨论的配置文件包.

        Note that Foo-build and AwesomeProject-build are two independent build tree, the link between them is the config-file package discussed above.

        这可以通过使用 -Foo_DIR:PATH=${CMAKE_BINARY_DIR}/Foo-build 配置 AwesomeProject 子项目来实现和调用 find_package(Foo REQUIRED).

        This is made possible by configuring AwesomeProject sub project with -Foo_DIR:PATH=${CMAKE_BINARY_DIR}/Foo-build and the calling find_package(Foo REQUIRED).

        如果您使用 VisualStudio 之类的工具,您可以打开任何这些子目录中的解决方案文件.

        If you use tools like VisualStudio you can open the solution file found in any of these sub-directory.

        要了解有关外部项目的更多信息:https://cmake.org/cmake/help/latest/module/ExternalProject.html

        To learn more about external project: https://cmake.org/cmake/help/latest/module/ExternalProject.html

        还有更多细节,但我希望这能让您更好地了解什么是可能的.

        There are many more details, but I hope this will allow you to get a better understanding of what is possible.

        这篇关于cmake项目中使用第三方库的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆