我应该为外部库提供 CMakeLists.txt 还是提供 find_packages?
Should I supply external libraries with a CMakeLists.txt or supply find_packages instead?
我正在做一个需要一些外部库的项目。因为是跨平台的,所以我用的是cmake。
分发此类项目的首选方式是什么?我应该为外部库(例如 zlib)提供它们自己的 CMakeLists.txt
还是应该通过简单地提供 find_packages()
?
来表示依赖关系
前者应有尽有。而后者让开发人员决定如何提供依赖项(例如 vcpkg)
虽然没有普遍首选方法,但我绝对相信您应该坚持find_package
。像这样声明你的依赖关系:
find_package(Pkg [version] REQUIRED [components])
仅当您知道 Pkg
本身提供 first-party CMake 包配置文件时,才包含 [version]
和 [components]
。如果您正在编写和分发库,您将在 MyProjConfig.cmake
文件中包含等效的 find_dependency
调用。
如果某些依赖项没有标准的 CMake 查找模块或提供自己的 CMake 包配置文件,您应该在 ./cmake
中编写自己的并在根 CMakeLists.txt
中添加 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
],在任何 find_package
调用之前。您也将安装您的查找模块,并在您的配置文件中的模块路径中添加相同的内容。
在查找模块中,您可以使用任何您想要的方法为您的依赖项创建一些导入的目标。使用 PkgConfig
是一个很好的方法。
通过 find_package
立即与许多依赖项提供程序一起工作:vcpkg、cmake_paths
Conan 生成器、Linux 发行版系统包,等等。
这样做的主要替代方法是供应代码,这意味着直接将您的依赖项包含在您的构建中,无论是通过 copy/paste 到您的源代码树、git 子模块,还是通过 build-time 从网上下载 (FetchContent
).
用于构建这些的机制几乎总是 add_subdirectory
最后,它将您的依赖项的 CMake 构建引入您的。
也许最大的问题是大多数项目的 CMake 代码完全没有准备好以这种方式使用。它可能会破坏您的缓存变量,将无效标志注入您的目标,覆盖您生成的 headers,等等。集成是一场噩梦。
此外,从软件分发的角度来看,这样做会将您的代码绑定到特定版本的依赖项,并从可能想要打包您的代码的其他人手中夺走控制权。例如,Debian 包不允许捆绑它们的依赖项...如果 libA
依赖于 libB
,那么每个包都会得到自己的包。使用 find_package
,维护者将适当的依赖项注入到您的构建中是微不足道的。如果没有,它通常涉及 difficult-to-maintain 补丁。
我正在做一个需要一些外部库的项目。因为是跨平台的,所以我用的是cmake。
分发此类项目的首选方式是什么?我应该为外部库(例如 zlib)提供它们自己的 CMakeLists.txt
还是应该通过简单地提供 find_packages()
?
前者应有尽有。而后者让开发人员决定如何提供依赖项(例如 vcpkg)
虽然没有普遍首选方法,但我绝对相信您应该坚持find_package
。像这样声明你的依赖关系:
find_package(Pkg [version] REQUIRED [components])
仅当您知道 Pkg
本身提供 first-party CMake 包配置文件时,才包含 [version]
和 [components]
。如果您正在编写和分发库,您将在 MyProjConfig.cmake
文件中包含等效的 find_dependency
调用。
如果某些依赖项没有标准的 CMake 查找模块或提供自己的 CMake 包配置文件,您应该在 ./cmake
中编写自己的并在根 CMakeLists.txt
中添加 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
],在任何 find_package
调用之前。您也将安装您的查找模块,并在您的配置文件中的模块路径中添加相同的内容。
在查找模块中,您可以使用任何您想要的方法为您的依赖项创建一些导入的目标。使用 PkgConfig
是一个很好的方法。
通过 find_package
立即与许多依赖项提供程序一起工作:vcpkg、cmake_paths
Conan 生成器、Linux 发行版系统包,等等。
这样做的主要替代方法是供应代码,这意味着直接将您的依赖项包含在您的构建中,无论是通过 copy/paste 到您的源代码树、git 子模块,还是通过 build-time 从网上下载 (FetchContent
).
用于构建这些的机制几乎总是 add_subdirectory
最后,它将您的依赖项的 CMake 构建引入您的。
也许最大的问题是大多数项目的 CMake 代码完全没有准备好以这种方式使用。它可能会破坏您的缓存变量,将无效标志注入您的目标,覆盖您生成的 headers,等等。集成是一场噩梦。
此外,从软件分发的角度来看,这样做会将您的代码绑定到特定版本的依赖项,并从可能想要打包您的代码的其他人手中夺走控制权。例如,Debian 包不允许捆绑它们的依赖项...如果 libA
依赖于 libB
,那么每个包都会得到自己的包。使用 find_package
,维护者将适当的依赖项注入到您的构建中是微不足道的。如果没有,它通常涉及 difficult-to-maintain 补丁。