让我们考虑一下Debian或Ubuntu发行版,在那里人们可以安装一些库程序包,比如说libfoobar个,以及相应的libfoobar-dev个库程序包.第一个包含共享库对象.后者通常包含头文件、静态库变量和cmake导出的目标(比方说,FoobarTargets.cmake),这使得cMake类似find_package的东西可以完美地工作.为此,FoobarTargets.cmake必须包含两个目标:静态目标和共享变量目标.

另一方面,我读了很多文章,指出我(作为libfoobar的作者)应该避免在CMakeLists.txt中声明add_library(foobar SHARED ....)add_library(foobar_static STATIC ...),而是支持使用BUILD_SHARED_LIBS=ONBUILD_SHARED_LIBS=OFF构建和安装库.但是这种方法只能将库的一个变体导出到FoobarTargets.cmake中,因为后面的构建将覆盖第一个.

因此,问题是:如何以正确的方式做到这一点?因此,包维护人员将不需要补丁程序库CMakeLists.txt来从一侧正确地导出这两个变体.并坚持CMake的真实方式,删除仅在静态/共享方面与另一边不同的重复目标?

推荐答案

我写了an entire blog post篇关于这方面的文章.一个有效的例子是available on GitHub.

基本思想是,您需要以这样一种方式编写您的FoobarConfig.cmake文件:它以一种有原则的、用户可控的方式加载FoobarSharedTargets.cmakeFoobarStaticTargets.cmake中的一个,同时也容忍只存在一个或另一个.我主张以下战略:

  1. 如果find_package调用恰好列出了所需组件中的staticshared之一,则加载相应的目标集.
  2. 如果定义了变量Foobar_SHARED_LIBS,则加载相应的目标集.
  3. 否则,为了与FetchContent用户保持一致,请使用设置BUILD_SHARED_LIBS.

在所有情况下,您的用户都将链接到Foobar::Foobar.

最终,您无法在同一个子目录中同时导入静态和共享内容,同时还提供一致的构建树(FetchContent)和安装树(Find-Package)接口.但这并不是什么大不了的事,因为消费者通常只想要其中的一个,而且将两个都链接到一个目标是完全非法的.

Linux相关问答推荐

GNC C:关于主要出发点混乱的 idea ?

如何确定Linux上的最大静态TLS(线程本地存储)块大小?

如何告诉链接器不要在链接的共享库中查找某些符号?

如何在充满 csv 的目录中获得不同的值计数

使用 AWK 过滤 Linux 输出

8 个半小时范围的 Crontab 表达式

如何删除文件中不需要的字符(使用 shell 脚本)

linux shell获取多文件交集

Linux C程序:如何找到函数所属的库

在 64 位 Linux 操作系统上编译 32 位程序导致致命错误

如何计算列的平均值

如何将输出从 grep 传送到 cp?

yum 可以告诉我哪些存储库提供了特定的包吗?

如何在没有 IDE 的情况下构建和部署三星 SmartTV 应用程序(例如:在 Linux 上)

列出当前目录和所有子目录中特定大小的文件

并行运行 shell 脚本

Linux 配置/制作,--prefix?

在 bash 中将输出作为 cp 的参数传递

linux中netstat和ss的区别?

`cd //` 中的双斜杠 // 在 Linux 中是什么意思?