我的项目CMakeLists是否应在构建目录和包注册表生成目标导出文件?
1. 未经同意将构建包加入注册表是否合理?
绝对不合理。CMake包注册表是全局系统级的记录,主动开启CMAKE_EXPORT_PACKAGE_REGISTRY并执行export(PACKAGE MyLib)会直接修改用户的全局配置,很可能干扰其他项目的find_package行为——比如用户同时构建你的库的多个版本时,注册表会优先返回最后构建的版本,导致依赖项目意外链接到非预期版本。永远不要在库的CMakeLists.txt中主动设置CMAKE_EXPORT_PACKAGE_REGISTRY,这个选项的控制权完全应该交给用户自己。
2. 为何要和默认已安装搜索机制并行?
构建目录导出目标是为了开发阶段的高效迭代:用户在修改你的库代码时,不需要每次都执行安装操作,就能让依赖项目直接调用构建目录里的最新编译产物。而已安装版本是面向最终用户或稳定依赖场景的,两者覆盖了从开发调试到正式部署的全流程需求,并行存在是为了给不同使用场景提供便利。
3. 是否不应让CMake将目标导出到注册表?
是的,除非用户明确提出需求。库维护者不该主动触发注册表导出,这属于侵入性操作。如果用户需要通过注册表使用构建目录的包,他们可以自行在构建时添加-DCMAKE_EXPORT_PACKAGE_REGISTRY=ON参数,或者在本地CMake配置中设置,选择权必须在用户手中。
4. 不导出到注册表,目标导出文件还有用吗?
当然有用,而且这是更安全灵活的使用方式:
- 用户可以通过指定
CMAKE_PREFIX_PATH让find_package定位到构建目录的导出文件,比如:cmake -S MyApp -B MyApp/build -DCMAKE_PREFIX_PATH=/path/to/MyLib/build - 也可以在依赖项目的CMakeLists.txt中直接引入导出文件:
include(/path/to/MyLib/build/MyLibTargets.cmake)
这两种方式都不会修改全局配置,完全避免了版本冲突风险。
5. 是否应该仅在安装时生成目标导出文件?
不是,应该同时支持构建目录导出和安装导出:
- 安装导出(
install(TARGETS ... EXPORT ...))是必须的,为最终用户提供标准的安装后使用路径; - 构建目录导出(
export(TARGETS ... FILE ...))是给开发者的便利,让他们能在不安装的情况下快速测试依赖。
你只需要在CMakeLists.txt中添加export(TARGETS ...)命令即可,不要触碰注册表相关设置。用户如果需要使用构建目录的包,自行通过CMAKE_PREFIX_PATH或手动引入导出文件实现,这样既满足了开发需求,又不会对用户系统造成意外干扰。
内容的提问来源于stack exchange,提问作者einpoklum

