替换全局变量并转而使用目标属性控制诸如在主应用程序CMakeLists.txt文件中的包含库中构建测试之类的最佳方法是什么?
背景
我们有一个c ++应用程序A,该应用程序除其他外使用内部库:lib B和lib C,它们作为A:s存储库中的git子模块包含在内。所有存储库(a,B和C)都使用Gtest作为单元测试框架共享一个公共结构的内部结构。这导致所有项目都具有“ unit_tests”目标和“ gtest”目标。
因此,当使用add_subfolder()在A:s CMakeLists.txt中包含lib B和lib C时,会发生冲突,因为CMake要求目标名称唯一,并且在其中总共有3个“ unit_tests”目标这三个仓库。还有其他测试目标,但是到目前为止它们是独一无二的。将测试目标重命名为b_unit_tests和a_unit_test可以解决此问题,但感觉不对,我们还需要将gtest目标重命名为a_gtest,b_gtest ...
当前,我们已经通过在A:s CMakeLists.txt中将全局CMake变量B_BUILD_TESTS,C_BUILD_TESTS设置为false并使用add_submodule(unit_tests)控制B和Cs CMakeLists.txt文件中的测试包含度来解决此问题。这并不是一个真正的问题,因为我们不想在构建应用程序A时为库B和C生成并运行单元测试。这样做通常会浪费时间。
在观看了Daniel Pfeifers ccpnow的谈话并以声明性方式阅读了其他有关使用CMake的博客文章之后,我开始着眼于现代CMake做法来重写CMake系统。因此,现在为每个包含的库设置全局标志的使用感觉就像是我想避免的反模式。理想情况下,我认为最好通过在包含的目标上设置属性来最好地控制测试。像下面这样。
add_subdirectory(B)
set_target_properties(B PROPERTIES BUILD_TESTS false)
target_link_libraries(A PRIVATE B)
理想情况下,它仍将包括bs测试目标,只是使它们不依赖于b:s主要目标。但是,如果不使用b_前缀重命名所有bs目标,这似乎很难做到。从技术上讲,b_unit_tests仍然是与b不同的目标,尽管从A的上下文来看,您会认为它是目标B的一部分。
不幸的是,我无法使以上内容正常工作,因为CMake似乎已经为目标提供了一组预定义的属性,并且似乎不完全支持添加新属性。有define_property和set_property,但据我所知,您不能使用它们来定义目标的属性。
强烈建议如何以更现代的方式重写CMakeLists.txt并清楚地分离和配置而不求助于全局变量。
对于现代CMake来说,库应该导出其路径和源,并且在导出过程中可以添加名称空间。虽然我真的不知道这是否也适用于作为子模块包含并与应用程序一起构建的库?这是我应该使用libs A和
的路线吗答案 0 :(得分:0)
为什么不只是重命名测试目标,以免它们彼此冲突?您还可以使用单个BUILD_TESTS
变量对其进行统治,并默认将其设置为ON
或OFF
,具体取决于库的构建方式-作为独立项目还是作为其他项目的一部分。