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

查看:126
本文介绍了在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),但维护者愿意从其当前的构建系统生成配置文件包
  • 操作:我建议帮助他们.例如,这是对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.
  • (3)并且当前的构建系统运行不正常,或者该库难以使用更广泛的编译器进行构建,或者不支持交叉编译
  • 操作:创建一个名为foo-cmake-buildsystem的项目(最好在GitHub上),该项目可以通过任一方式构建库

  • (1) library Foo is not using CMake
  • (2) and maintainer of Foo do not want (or are not ready) to transition to CMake.
  • (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: create a project (ideally on GitHub) named foo-cmake-buildsystem that will allow to build the library by either

  • 使用现有源树的路径配置项目
  • 让项目为您下载源文件
  • 例如,这是为CPython完成的. GitHub上有一个名为python-cmake-buildsystem的项目
  • configuring the project with the path to an existing source tree
  • having the project downloading the source for you
  • this is for example done for CPython. There is a project named python-cmake-buildsystem available on GitHub

案例5:

  • (1)出于任何原因,Foo的维护者不想过渡,或者无法维护替代的构建系统,或者系统上已经存在库
  • 操作:您可以创建一个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等)以拥有此类软件包 *(2)或需要为您的项目专门编译

      If the library Foo is: * (1) not available on the system: * or can't be installed using package manager * or working with the community maintaining packages (debian, conda-forge, chocolatey, ...) to have such package is not possible * (2) or need to be compiled specially for your project

      然后,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天全站免登陆