如何指定头文件引入的库依赖

2024-03-23

假设在 CMake 项目中,我有一个内置到库中的源代码

// a.cpp
void f() { /* some code*/ }

我有一个标题

// b.h
void f();
struct X { void g() { f(); } };

我还有另一个文件:

// main.cpp
#include "b.h"
int main() { X x; x.g(); }

CMakeLists.txt 包含:

add_library(A a.cpp)
add_executable(main main.cpp)
target_link_libraries(main A)

现在看看 CMakeLists.txt 的最后一行:我需要显式指定 A 作为 main 的依赖项。基本上,我需要为包含 b.h. 的每个源指定此类依赖项。因为包含可以是间接的,并且可以通过包含链一路向下。例如,a.cp​​p 调用 c.h 的类内联函数,c.h 又调用 d.h 中的函数等,最后调用库 A 中的函数。如果 b.h 被很多文件包含,则手动查找所有此类依赖关系是不可行的大型项目。

所以我的问题是,是否有办法指定,对于每个直接或间接包含标头的源文件,它需要链接到某个库?

Thanks.


为了澄清一件事:你的 a.cpp 被编译成一个 lib“A”。这意味着 A 的任何用户都需要指定target_link_libraries与A。没有办法解决它。如果您有 10 个使用 A 的小应用程序,则需要指定target_link_libraries十次。

我的回答涉及你问题的第二个问题,我认为这是更重要的一个:

如何摆脱包含链?

通过在 b.h 中包含 a.h 并在 b.h 中使用它的方法,您将添加“隐式”依赖项。正如您所注意到的,b.h 的任何用户也需要 a.h。一般来说,有两种方法。

好的方法:

这与CMake无关,而是关于封装。您的库的用户(包括您自己)不需要担心其内部实现。这意味着:a.h 中不要包含 b.h。

相反,请将包含内容移至 .cpp 文件。这样,你就打破了链条。例如。就像是

// b.h
void f();
struct X
{ 
    void g();
};

// b.cpp
#include b.h
#include a.h
void X::g( )
{
    f();
}

这样,a.h 的使用就“包含”在 cpp 文件中,任何使用您库的人只需要包含 b.h 并链接到 b.lib。

另一种选择:

现在,在某些情况下,你必须接受这种“依赖”,或者这是一个有意识的选择。例如。当您无法控制 A 或当您有意识地决定创建一个根据 A 内部的类/结构定义的库时。

在这种情况下,我建议您编写一段 CMake 代码,它会准备好链下所有必需的包含目录。例如。在“YourLibConfig.cmake”中定义变量“YOURLIB_INCLUDES”和“YOURLIB_LIBRARIES”,并记录库的任何用户都应导入“YourLibConfig.cmake”。这是几个基于 cmake 的项目所采用的方法。例如。 OpenCV 安装一个OpenCVConfig.cmake文件,VTK 安装一个VTKConfig.cmake并准备一个UseVTK.cmake file

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何指定头文件引入的库依赖 的相关文章

随机推荐

  • C++ 中的临界区和返回值

    在尝试从头开始创建线程安全容器类时 我遇到了从访问方法返回值的问题 例如在 Windows 中 myNode getSomeData EnterCriticalSection myCritSec myNode retobj fill ret
  • 打印具有特定数量的零的浮点数

    我知道如何控制小数位数 但是具体如何控制零的数量呢 例如 104 06250000 gt 104 0625 119 00000 gt 119 0 72 000000 gt 72 0 使用十进制模块怎么样 来自文档 http docs pyt
  • 如何将文本环绕在图像或可组合项周围?

    如何将文本环绕在图像或可组合项周围 类似的东西流文本视图 https github com deano2390 FlowTextView在 Jetpack Compose 中 我想知道是否有可能留下一定的空闲空间 这样如果文本太长 它就会断
  • 如何将卡片放入条子应用栏中

    我做了一个 sliverappbar 我想在这个 sliverappbar 上放一张卡片 如何将卡片放在 sliverappbar 上 并且该卡片会随 sliverappbar 一起折叠 该卡应一半在应用栏中 一半在 正文 中 Custom
  • 通过示例查询 Spring Data - In Clause?

    根据 Spring 文档 我只能为 QBE 编写精确匹配 我只需要精确匹配 但在一组值之间 查询的 IN 子句 e g Person p new Person p setId need to match among set of ids E
  • 访问 iframe 中的表单

    我正在尝试访问表单及其元素 该表单位于 iframe 内 访问该表单的 javascript 代码位于主文档内 我不确定我还应该在这个问题中添加什么内容 所以如果我需要添加其他内容 请告诉我 表单和主页在同一域中 Thanks var if
  • 查询失败,错误代码为 13 并显示错误消息“未授权在 [db] 上执行命令 { find:

    我正在使用以下 蒙戈3 2 7 春季 4 3 1 发布 我创建了以下具有以下权限的用户 gt use admin switched to db admin gt db getUser UserAdminNew id admin UserAd
  • 角度跟踪依据和排序依据

    开始使用 Angular 并进行演示 在模型中 事件项包括名为starts at 的开始时间和标题 我有一个使用 ng repeat event in events track by index 的标签 并尝试添加 orderBy even
  • 如何在 VB.Net 中声明 lambda 事件处理程序?

    我相信以下 VB Net 代码与前面的 C 代码等效 然而 VB Net 测试失败 事件处理 Lambda 从未被调用 到底是怎么回事 VB Net 版本 失败
  • 在后台运行 Chrome 扩展程序

    我目前正在创建我的第一个 Chrome 扩展程序 到目前为止一切顺利 这只是我运行多个计时器的一个小测试 但显然 当我打开和关闭扩展程序时 我的所有计时器都会重置 因此 为了保持所有计时器运行 当我关闭扩展程序并使它们在后台页面中运行时 我
  • MapView 自定义 Pin 图问题

    我已经更改了 MapView 引脚图像 但遇到了这个问题 其中一些点不会更改引脚图像 而其中一些会发生变化 问题会出在哪里呢 我添加了一个例子 My Code MKAnnotationView mapView MKMapView mV vi
  • 如何在 ES6 中获取 Set 的第一个元素(EcmaScript 2015)

    在ES6中 我们如何快速获取元素呢 in Set 的 MDN 语法 https developer mozilla org en docs Web JavaScript Reference Global Objects Set 我没有找到答
  • CSS中这个符号是什么意思?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 这是什么 这是关于 CSS 语法时不时出现的问题的集合 这也是一个社区 Wiki 所以邀
  • Django 表单向导和 recaptcha

    我使用以下命令进行了验证码集成Django 片段 http www djangosnippets org snippets 1653 settings py RECAPTCHA PUBLIC KEY
  • 创建物化视图时如何指示某列不可为空?

    我正在使用以下查询创建物化视图 CREATE MATERIALIZED VIEW article view AS SELECT id alternative headline article author id created at des
  • 有没有更好的方法在字符串列表上使用 strip() ? - 蟒蛇[重复]

    这个问题在这里已经有答案了 现在我一直在尝试对字符串列表执行 strip 我这样做了 i 0 for j in alist alist i j strip i 1 有更好的方法吗 你可能不应该使用list作为变量名 因为它是一种类型 不管
  • 内连接与 IN

    SELECT C FROM StockToCategory STC INNER JOIN Category C ON STC CategoryID C CategoryID WHERE STC StockID StockID VS SELE
  • Rx 中的历史调度程序

    我有以下代码 我尝试重播序列 但 PostWorkItem 总是为 null 我不明白为什么 下面的代码给出了堆栈溢出错误 Task
  • 锁内锁

    我想知道这种构造是否会导致错误 lock sync something lock sync something lock sync something 我已经运行了这段代码 看起来不错 但也许在某些情况下可能会引发错误 lock是一个包装器
  • 如何指定头文件引入的库依赖

    假设在 CMake 项目中 我有一个内置到库中的源代码 a cpp void f some code 我有一个标题 b h void f struct X void g f 我还有另一个文件 main cpp include b h int