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

时间:2017-03-05 18:43:38

标签: c++ git build cmake

我有两个cmake项目。其中一个使用googletest,其中第二个也使用它。还有,我在第二个项目中使用了第一个项目。

我在github上有第二个项目,googletest也在github上。因此,当我使用

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

ExternalProject_Add

命令。

这是简化的文件夹结构:

.itemImage img {
    max-width: 100%;
}

ProjectA | build/ | include/ | src/ | modules/ | | ProjectB/ | | | CMakeLists.txt | | googletest/ | | | CMakeLists.txt | CMakeLists.txt 的简化结构:

ProjectB

现在我有一个重要的问题:可以下载googletest代码一次吗?现在我下载两次,一次ProjectB/ | build/ | include/ | src/ | modules/ | | googletest/ | | | CMakeLists.txt | CMakeLists.txt ,第二次ProjectA

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

2 个答案:

答案 0 :(得分:1)

如果您不想两次下载Google C ++测试框架,只需使用正确的cmake查找模块,让它从您的环境中找到您需要的内容。

请参阅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查找模块,该模块在gtest内查找ProjectA。无论如何,它是一个脆弱的解决方案,因为它会在ProjectA中的依赖关系发生变化时立即中断。

评论中的问题:

  

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

如果我无法通过正确的查找模块(以及需要时的版本)查找系统中的依赖项,我通常更愿意明确它们。因此,我将所需的依赖项添加到每个项目中,即使它意味着重新编译它们两次 一个可以回答为什么的问题:如果ProjectA取决于给定模块的标记 x ProjectB需要标记 y < / em>上班?如果这两个标签打破了彼此的API(不幸的是有时它会发生),除非你明确了解每个项目的依赖关系,否则你将遇到麻烦。

答案 1 :(得分: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源代码,或者更好的是,从projectA构建目标。您可以将projectA带入projectB,就像上面的链接将googletest带入projectA一样。我们在工作中使用这样的安排来汇集许多不同的项目,每个项目可以单独构建或作为其他项目的一部分构建。这种方法的一个优点是,如果您使用的是像Visual Studio,Xcode或Qt Creator这样的IDE,您可以看到源列表中所有项目的来源以及IDE的问题检测,重构工具等往往会有更完整的整体构建视图。它还倾向于最小化必须在项目之间手动传递的信息,因为CMake在一个构建中看到整个源和目标集,因此不需要显式处理特定于平台的库名,不同的构建输出目录结构等等。

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

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