如何删除依赖项目中相同依赖源的重复项

Posted

技术标签:

【中文标题】如何删除依赖项目中相同依赖源的重复项【英文标题】:How remove duplicate of the same dependiencies sources in dependent projects 【发布时间】:2017-03-05 18:43:38 【问题描述】:

我有两个 cmake 项目。其中一个使用 googletest,第二个也使用它。更重要的是,我在第二个项目中使用了第一个项目。

我在 github 上有第二个项目,googletest 也在 github 上。所以我想在使用

构建我的第一个项目时下载它们

ExternalProject_Add

命令。


这是简化的文件夹结构:

ProjectA
| build/
| include/
| src/
| modules/
| | ProjectB/
| | | CMakeLists.txt
| | googletest/
| | | CMakeLists.txt
| CMakeLists.txt

ProjectB 的简化结构:

ProjectB/
| build/
| include/
| src/
| modules/
| | googletest/
| | | CMakeLists.txt
| CMakeLists.txt

现在我有一个重要的问题:可以一次下载 googletest 代码吗?现在我下载了两次,一次是ProjectA,第二次是ProjectB

我可以添加简化的CMakeLists.txt 代码,但我认为这里不需要。

【问题讨论】:

【参考方案1】:

您可以将 googletest 视为第三个外部项目,然后将其位置作为 CMake 缓存变量传递到您的两个项目中。这将确保您只需要下载一次 googletest,但它可能不如将 googletest 直接构建为项目的一部分方便。您可以创建第四个***项目以将三个项目(googletest、projectA 和 projectB)中的每一个组合在一起,这样您就可以确保在需要配置 projectA 或 projectB 之前构建 googletest。 googletest 的 ExternalProject 会将 gtest 和 gmock 目标安装到其安装区域。然后将该目录传递到 projectA 和 projectB 的 ExternalProjects 中,作为查找 google 测试的位置。为此,您可以在 projectA 和 projectB 中使用 FindGTest 模块,让您的***项目为 projectA 和 projectB 设置 GTEST_ROOT 缓存变量。这可能是最简单的选择。

另一种选择是下载并构建 googletest 作为 projectA 的一部分(请参阅here 了解我建议这样做的方法),然后让 projectB 重新使用 googletest 源或更好的构建目标来自项目A。如果您愿意,您可以将 projectA 带入 projectB,就像上面的链接将 googletest 带入 projectA 一样。我们在工作中使用这样的安排将许多不同的项目组合在一起,每个项目都可以独立构建或作为其他项目的一部分。这种方法的一个优点是,如果您使用像 Visual Studio、Xcode 或 Qt Creator 这样的 IDE,您可以在源列表中查看所有项目的源,并且 IDE 的问题检测、重构工具等往往具有整体构建的更完整视图。它还倾向于最小化必须在项目之间手动传递的信息,因为 CMake 在一个构建中看到整套源和目标,因此无需显式处理特定于平台的库名称、不同的构建输出目录结构等。

如果您想将 projectA 保留为 projectB 的 ExternalProject,那么您仍然可以重新使用 projectA 中的 googletest 源,但您必须非常小心地设置目标间依赖关系,以确保 projectA 在任何需要的东西之前构建googletest 来源。您可能最终还必须手动计算下载内容并在 projectA 中构建的位置,如果您的项目构建在多个平台上,这可能会很痛苦。听起来这最接近您要如何做的事情,但我可能会建议尝试上述两种方法之一。

还有其他选择,例如使用像 hunter 这样的包管理器,但这可能与问题的原始焦点有点偏离。

【讨论】:

感谢您的回答!我今天去看看。 感谢您的复杂回答。我检查了您的博客文章和 Git 存储库,并且可能在我的问题中使用了这种方法。【参考方案2】:

如果你不想两次下载 Google C++ 测试框架,你可以简单地使用 cmake 的正确 find 模块,让它从你的环境中找到你需要的东西。

FindGTest

上面链接的示例用法:

enable_testing()
find_package(GTest REQUIRED)
add_executable(foo foo.cc)
target_link_libraries(foo GTest::GTest GTest::Main)
add_test(AllTestsInFoo foo)

话虽如此,它们是具有自己模块的不同项目。最好明确说明它们。 您仍然可以在ProjectB 中放置一个自定义cmake 查找模块,该模块在ProjectA 中查找gtest。无论如何,这是一个脆弱的解决方案,因为一旦 ProjectA 中的依赖项发生变化,它就会中断。


cmets中的问题:

gtest 看起来确实不错,但是我想知道我是否有与 gtest 不同的项目(例如 ProjectC),那我该怎么办?我正在寻找更通用的解决方案。

如果我无法通过适当的查找模块(以及需要的版本)在我的系统中查找依赖项,我通常更愿意明确说明它们。因此,我将所需的依赖项添加到每个项目中,即使这意味着重新编译它们两次。 一个可以回答 whys 的问题:如果ProjectA 依赖于给定模块的标签 xProjectB 需要标签 y 怎么办?工作?如果这两个标签破坏了彼此的 API(不幸的是,有时会发生这种情况),除非您明确说明每个项目的依赖关系,否则您将遇到麻烦。

【讨论】:

那么,如果您认为拥有两个独立的 google 测试源副本会更好? @BartekPL 不,我认为您可以安全地使用FindGTest 模块。为什么不呢? gtest 看起来确实不错,但是我想知道我是否有与 gtest 不同的项目(例如 ProjectC),那我该怎么办?我正在寻找更通用的解决方案 :) 你有什么想法吗? @BartekPL 让我整合一下答案。 @BartekPL 别担心。我是来帮忙的,不是为了名声。随意接受此答案或符合您要求的答案。 ;-)

以上是关于如何删除依赖项目中相同依赖源的重复项的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Eclipse 中从我的 Android 项目中删除依赖项

如何正确删除 Maven 项目中的依赖项

如何从 Eclipse 中的 Maven 项目中删除未使用的依赖项? [复制]

如何在 Xcode 11 中删除 Swift 包依赖项?

如何在 Gradle 中查找/删除未使用的依赖项

如何列出 React 项目中未使用的节点模块/依赖项?