2017-03-05 101 views
1

我有两个cmake项目。其中一个使用googletest,第二个也使用它。更重要的是,我在第二个项目中使用了第一个项目。如何删除从属项目中相同的依赖项源的重复

我在github上有第二个项目,googletest也在github上。所以,我想下载它们,当我用

ExternalProject_Add

命令建立我的第一个项目。


这simpified文件夹结构:

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。 Externaltestject for googletest会将gtest和gmock目标安装到其安装区域。然后将该目录传递给projectA的和projectB的ExternalProjects作为查找Google测试的位置。您可以使用项目A和项目B中的FindGTest模块进行此操作,让顶级项目为projectA和projectB设置GTEST_ROOT缓存变量。这可能是最简单的选择。

另一个选择是下载并构建googletest作为了projectA(见here的方法,我建议这样做)的一部分,然后让项目B重新使用googletest源或者更好的是,从内置目标了projectA。如果需要,您可以像上面的链接将googletest带入projectA一样将projectA引入projectB。我们在工作中使用这样一种安排来汇集多个不同的项目,每个项目都可以独立构建或作为其他项目的一部分构建。这种方法的一个优点是,如果您使用Visual Studio,Xcode或Qt Creator之类的IDE,您可以查看源列表中所有项目的来源,并且IDE的问题检测,重构工具等往往具有更全面地了解整体构建。它也倾向于最小化必须在项目之间手动传递的信息,因为CMake在一个构建中看到了整套源和目标,因此不需要明确处理平台特定的库名称,不同的构建输出目录结构等

如果你想保持projectA作为projectB的ExternalProject,那么你仍然可以重复使用ProjectA中的googletest源代码,但你必须非常仔细地设置目标间依赖关系,以确保构建projectA在需要googletest资源的任何事情之前。你可能最终也不得不手动确定下载到projectA中的内容,如果你的项目建立在多个平台上,这可能会很痛苦。这听起来像是最接近你所要求的,但我可能会建议尝试上述两种方法之一。

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

+0

谢谢你的回答!我今天会检查一下。 – BartekPL

+0

感谢您的复杂答案。我检查了你的博客文章和Git回购,并且我在我的问题中使用了这种方法。 – BartekPL

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


问题的意见:

这似乎是GTEST确实不错,但我不知道如果我有不同的项目比GTEST(如项目C),那么我该怎么办?我寻找更通用的解决方案。

如果我无法通过正确的查找模块(以及需要的版本)在我的系统中查找依赖项,我通常更愿意对它们进行明确的说明。因此,我将所需的依赖项添加到每个项目中,即使它意味着重新编译它们两次。
可以回答个为什么一个问题:如果ProjectA取决于标签X给定模块和ProjectB需要标签Ÿ工作?如果两个标签破坏对方的API(不幸的是有时会发生),那么除非您明确了解每个项目的依赖关系,否则您将遇到麻烦。

+0

那么,如果您认为拥有两个独立的Google测试资源副本会更好? – BartekPL

+0

@BartekPL不,我想你可以安全地使用FindGTest模块。为什么不? – skypjack

+0

gtest似乎真的很好,但我不知道我是否有与gtest(例如ProjectC)不同的项目,那么我该怎么做?我寻找更多的解决方案:)你有什么想法吗? – BartekPL

相关问题