CMake:或者在 Debug/Release 中安装一个导出文件?

CMake: Install an export file in Debug/Release alternatively?

以下面的例子为例:

...
add_library(Foo ...)
install(TARGETS Foo EXPORT FooTargets
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
...
)

install(EXPORT FooTargets
 FILE lib/cmake/Foo
...
)

运行这个跟

$ mkdir build; cd build
$ cmake -DCMAKE_BUILD_TYPE=Release .. (or in Debug)
$ cmake --build .
$ cmake --install . --prefix my/custom/prefix

这将创建文件:

my/custom/prefix/lib/cmake/Foo/FooTargets.cmake
my/custom/prefix/lib/cmake/Foo/FooTargets-release.cmake (Or debug, respectively)
my/custom/prefix/lib/libFoo.a

根据我从 FooTargets.cmake 文件中设法理解的内容,它包含所有 FooTargets-*.cmake 文件和 includes() 所有文件。

反过来,FooTargets-release.cmake 文件引用了 libFoo.a 文件。

在关于 install 命令的文档中,它说您可以将 CONFIGURATIONS 选项添加到 install TARGETS 命令,因此如果我们更改上面的内容:

install(TARGETS Foo EXPORT FooTargets
   CONFIGURATIONS Debug
   LIBRARY DESTINATION lib/Debug
   ARCHIVE DESTINATION lib/Debug

这将在 my/custom/path/lib/Debug/libFoo.a 中安装 libFoo.a 文件。现在假设我希望将 Release 库安装在 lib/Release 中,将 Debug 库安装在 lib/Debug 中,并且当下游项目使用我的包时,它将拥有正确的库,具体取决于它配置 - 即 - 调试构建将 link 针对调试库,与发布相同。

我认为我能做的是:

install(TARGETS Foo EXPORT FooTargets
   CONFIGURATIONS Debug
   LIBRARY DESTINATION lib/Debug
   ARCHIVE DESTINATION lib/Debug
)

install(TARGETS Foo EXPORT FooTargets 
  CONFIGURATIONS Release
  LIBRARY DESTINATION lib/Release
  ARCHIVE DESTINATION lib/Release
)

install(EXPORT FooTargets 
  DESTINATION lib/cmake/Foo
  ...
)

而在Debug中构建时,会生成FooTargets-debug.cmake,指向lib/Debug/libFoo.a,而在Release中构建时,FooTargets-release.cmake ] 将生成,指向 lib/Release/libFoo.a。然后 FooTargets.cmake 将检查正在构建的消费项目使用什么配置,并包含正确的配置。

当我尝试执行上述操作时,我得到:

-- Configuring done
CMake Error: install(EXPORT "FooTargets" ...) includes target "Foo" more than once in the export set.
-- Generating done
CMake Generate step failed.  Build files cannot be regenerated correctly.

这应该怎么做?

编辑

我以一种不太直接的方式发现,当我这样构建消费项目时:

$ cmake -DCMAKE_BUILD_TYPE=Debug ..

像这样:

$ cmake -DCMAKE_BUILD_TYPE=Release ..

我link只反对相关图书馆。基本上,它的工作原理是 FooTargets.cmake 文件包含在 FooConfig.cmake 文件中,该文件由 find_package 调用。 FooTargets.cmake 文件是定义导入目标的文件:

add_library(Foo IMPORTED)

此文件然后调用所有 FooTargets-*.cmake,将相关库添加到某个名为 _IMPORT_CHECK_FILES_FOR_FOO 的列表中。 该文件还做的是:

set_property(TARGET Foo::Foo APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)

显然有一些 属性 IMPORTED_CONFIGURATIONS 保存导入的配置。

我想在路上的某个地方,find_package 获取此列表并根据 CMAKE_BUILD_TYPE 变量对其进行过滤,这样 link 只有相关的库。

我仍然不明白的是,如何在(Foo 的)Release 构建时创建 FooTargets-release.cmake,指向 lib/Release/Foo.a,对于调试构建。

看来 CMake 已经完成了一半,除非我严重遗漏了什么。

似乎 per-CONFIGURATIONS 安装不容易适应 EXPORT 语义。

但是,在简单的情况下,per-configuration 的特定可以通过在 DESTINATION 中使用 generator expressions 来实现:

install(TARGETS Foo EXPORT FooTargets
   LIBRARY DESTINATION lib/$<CONFIG>
   ARCHIVE DESTINATION lib/$<CONFIG>
)

install(EXPORT FooTargets 
  DESTINATION lib/cmake/Foo
  ...
)

上面的代码会将库安装到 lib/Debug 进行调试配置,并安装到 lib/Release 进行发布配置。