如何在不使用 CMake 但仅使用 make 的项目中合并使用 CMake 的仅标头库?

Posted

技术标签:

【中文标题】如何在不使用 CMake 但仅使用 make 的项目中合并使用 CMake 的仅标头库?【英文标题】:How to incorporate a header-only library that uses CMake in a project that does not use CMake but uses make only? 【发布时间】:2021-06-24 18:55:28 【问题描述】:

我正在寻找解决以下问题的最惯用的方法。我有一个项目 A 想要使用仅包含标头的库 B。项目 A 使用复杂的 Makefile 进行构建,其中库 B 依赖其客户端在构建步骤中使用 cmake 对其进行配置。

我不想将项目 A 转换为使用 Cmake(它具有许多其他依赖项的跨平台)。由于库 B 仅是标头,因此我无法单独构建它,然后在 A 的构建过程中单独链接到它。解决此问题的最惯用方法是什么(无需将项目 A 的整个构建项目更改为首先使用 CMake)?

【问题讨论】:

只有标头的库需要什么样的配置?通常您只需设置包含路径并开始使用它。如果确实需要配置创建一个新项目只是为了配置它,然后将它的路径添加到您的真实项目包含路径中。 有很多选择;你试过什么?您可以像使用Makefile 生成器运行cmake 并简单地递归到它一样简单,或者甚至只是将-I 添加到库B 的公共目录(假设库B 不需要将任何标头配置为一部分)的配置步骤)。如果依赖库 B 足够简单,您甚至可以删除整个构建系统并依赖标头的静态副本(仅标头可以工作) @Richard Critten:仅标头库可以选择要使用的精确数字类型 - 它可以使用自己的内部精确数字实现,或使用第三方精确数字实现。基于此,CMake 将在最终的头文件中定义宏。 @Human-Compiler 您的假设正是我不能简单包含它的原因 - 请参阅我上面的评论(头文件也在配置步骤中生成) 我很困惑,为什么作为 配置步骤 的一部分生成的标头会对我第一个使用 Makefile 生成器运行 cmake 的建议和包括 Makefile 层次结构?这会将库 B 的目标引入 Makefile 的生态系统,因此您可以从 Make 中获得适当的目标依赖性——这将允许您使用生成的源。这可以作为 Make 之前的预处理步骤完成,或者如果您愿意,甚至可以作为 Make 中的自定义目标(例如 cmake ...; cmake --build ...; cmake --build . --target install 【参考方案1】:

我正在寻找解决以下问题的最惯用的方法。我有一个项目 A 想要使用仅包含标头的库 B。项目 A 使用复杂的 Makefile 进行构建,其中库 B 依赖其客户端在构建步骤中使用 cmake 对其进行配置。

解决问题最惯用的方法是将项目分开。这意味着库 B 是库 A 的 external 依赖项,需要独立构建和安装。然后,项目 A 的构建系统只需要发现或被告知在哪里可以找到 B 标头。 B 是一个仅包含标头的库并没有真正考虑在内。

【讨论】:

我完全不同意这种习惯用法。事实上,在许多情况下使用这种方法可能很危险。考虑交叉编译和非目标构建的简单情况。如果您在 x86_64 系统上为某些 ARM 设备配置了头文件——您可能不希望将其安装在系统头文件中。大多数情况下,构建系统(即使它是 Makefile)更希望包装这样的构建,以便安装过程进入暂存区域,而不是让用户意外安装到系统 @Human-Compiler,这绝对是为主机或其他类似机器构建时的常用方法。或者无论如何,这就是我根据数十年经验得出的观点。此外,引入交叉编译实际上并没有对基础产生影响。它所做的是将选择安装库 B 的 where 更改为交叉目标,而不是构建主机的主系统。单项目交叉构建构建原生构建中不包含的依赖项绝不是正常的。 在处理多个 CMake 项目时,我会安装到本地前缀 even。通过add_subdirectoryFetchContent 或(甚至更糟)ExternalProject 争论行为不端的项目太脆弱,而且充满了“陷阱”。仅仅通过项目的预期消费方式(pkg-config、find_package等)通常是最可靠的选择。 @JohnBollinger 没有必要对整个“数十年的经验”俏皮话如此防御?。我只是想说,期望大型代码库的客户端记住安装到正确的目录往往会导致交叉编译时难以诊断的错误。基本上,除非由 某处的某个工具 管理——无论它是相同的构建系统(即 Makefile)还是协调它们的某个外部管理器(脚本或其他东西)——你冒着用户的风险-发生的错误。在这种情况下,人为因素很重要,因为它会浪费时间和金钱。

以上是关于如何在不使用 CMake 但仅使用 make 的项目中合并使用 CMake 的仅标头库?的主要内容,如果未能解决你的问题,请参考以下文章

Tool-CMake-make -j[cpu_num]

make如何指定cmake路径

在使用 cmake 构建时,如何让 make 变得冗长但只有“有意义”的行?

如何将 CMAKE_MAKE_PROGRAM 设置为忍者?

如何从 CMake 或 make 输出编译依赖项?

CMAKE - 调试/交叉构建?