CMake:unit testing的项目结构

我想构build我的项目,包括生产源(在src子文件夹)和testing(在test子文件夹)。 我正在使用CMake来build立这个。 作为一个最小的例子,我有以下文件:

的CMakeLists.txt:

 cmake_minimum_required (VERSION 2.8) project (TEST) add_subdirectory (src) add_subdirectory (test) 

SRC /的CMakeLists.txt:

 add_executable (demo main.cpp sqr.cpp) 

SRC / sqr.h

 #ifndef SQR_H #define SQR_H double sqr(double); #endif // SQR_H 

SRC / sqr.cpp

 #include "sqr.h" double sqr(double x) { return x*x; } 

src / main.cpp – 使用sqr,并不重要

testing/的CMakeLists.txt:

 find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED) include_directories (${TEST_SOURCE_DIR}/src) ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) add_executable (test test.cpp ${TEST_SOURCE_DIR}/src/sqr.cpp) target_link_libraries(test ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) enable_testing() add_test(MyTest test) 

testing/ TEST.CPP:

 #define BOOST_TEST_MODULE SqrTests #include <boost/test/unit_test.hpp> #include "sqr.h" BOOST_AUTO_TEST_CASE(FailTest) { BOOST_CHECK_EQUAL(5, sqr(2)); } BOOST_AUTO_TEST_CASE(PassTest) { BOOST_CHECK_EQUAL(4, sqr(2)); } 

几个问题:

  1. 这个结构是否有意义? 构build这些代码的最佳实践是什么? (我来自C#和Java,从某种意义上说它更容易)
  2. 我不喜欢我必须从test/CMakeLists.txt文件中的src文件夹中列出所有文件的事实。 如果这是一个图书馆项目,我只会链接图书馆。 有没有办法避免从其他项目列出所有的cpp文件?
  3. enable_testing()add_test(MyTest test)在做什么? 我没有看到任何效果。 我如何从CMake(或CTest)运行testing?
  4. 到目前为止,我只是跑了cmake . 在根文件夹中,但是这造成了随处可见的临时文件的混乱。 我怎样才能得到一个合理的结构编制结果?

对于问题1和2,我build议从不包含main.cpp的非testing文件(在本例中只是src / sqr.cpp和src / sqr.h)中创build一个库,然后避免列出(更重要的是重新编译)所有的来源两次。

对于问题3,这些命令会添加一个名为“MyTest”的testing,它会在没有任何参数的情况下调用可执行文件“test”。 但是,由于您已经添加了这些命令来testing/ CMakeLists.txt而不是您的顶级CMakeLists.txt,所以您只能从构build树的“test”子目录中调用testing(尝试cd test && ctest -N )。 如果您希望testing可以从顶级构build目录运行,您需要从顶级CMakeLists.txt调用add_test 。 这也意味着你必须使用更详细的add_testforms,因为你的testingexe文件没有在相同的CMakeLists.txt中定义

在你的情况下,因为你在根文件夹中运行cmake,所以你的构build树和你的源码树是一样的。 这被称为源内构build,并不理想,这导致了问题4。

生成构build树的首选方法是执行源代码构build,即在源代码树之外的某处创build一个目录,然后从那里执行cmake。 甚至在你的项目的根目录下创build一个“build”目录并执行cmake ..会提供一个干净的结构,不会干扰你的源代码树。

最后一点是避免调用可执行文件“test”(区分大小写)。 为什么,看到这个答案 。

为了实现这些变化,我会做以下几点:

的CMakeLists.txt:

 cmake_minimum_required (VERSION 2.8) project (TEST) add_subdirectory (src) add_subdirectory (test) enable_testing () add_test (NAME MyTest COMMAND Test) 

SRC /的CMakeLists.txt:

 add_library (Sqr sqr.cpp sqr.h) add_executable (demo main.cpp) target_link_libraries (demo Sqr) 

testing/的CMakeLists.txt:

 find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED) include_directories (${TEST_SOURCE_DIR}/src ${Boost_INCLUDE_DIRS} ) add_definitions (-DBOOST_TEST_DYN_LINK) add_executable (Test test.cpp) target_link_libraries (Test Sqr ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) 

我喜欢@Fraser的例子,但会在test / CMakeLists.txt中使用add_test命令,并在add_subdirectory(test)之前使用enable_testing。

这样,您可以在test / CMakeLists.txt中指定testing的同时,从顶层构build目录运行testing。

结果看起来像这样(我重用了@Fraser的例子):

的CMakeLists.txt

 cmake_minimum_required (VERSION 2.8) project (TEST) add_subdirectory (src) enable_testing () add_subdirectory (test) 

SRC /的CMakeLists.txt

 add_library (Sqr sqr.cpp sqr.h) add_executable (demo main.cpp) target_link_libraries (demo Sqr) 

testing/的CMakeLists.txt

 find_package (Boost COMPONENTS system filesystem unit_test_framework REQUIRED) include_directories (${TEST_SOURCE_DIR}/src ${Boost_INCLUDE_DIRS} ) add_definitions (-DBOOST_TEST_DYN_LINK) add_executable (Test test.cpp) target_link_libraries (Test Sqr ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) add_test (NAME MyTest COMMAND Test)