配置 CMake 以在单元测试时重新编译源代码

Configuring CMake to re-compile source when unit testing

我在下面定义了一个包含 src 和 test 目录的项目结构。

├── CMakeLists.txt
├── src
│   ├── CMakeLists.txt
│   ├── table.c
│   └── table.h
├── test
│   ├── CMakeLists.txt
│   └── test_table.c
├── build
    ├── src    [src build]
    └── test   [src + test build with UNIT_TESTING defined]

我想配置 cmake,以便在构建测试(单元测试)目录时,它还使用 UNIT_TESTING 定义集编译 ./src 目录中的文件,并将所有构建工件放入./build/test/ 目录。

这样我就可以在 UNIT_TESTING 时使用 malloc free 等的包装函数跟踪内存泄漏,在没有单元测试的情况下正常构建时使用实际内存分配函数。

有人知道如何让我开始吗?

首先我推荐 out-of-source-build 这样的:

├── build
│   ├── src
│   └── test
└── code
    ├── CMakeLists.txt
    ├── src
    │   ├── CMakeLists.txt
    │   ├── table.c
    │   └── table.h
    └── test
        └── CMakeLists.txt
        └── test_table.c

code 中的顶级 CMakeLists.txt 如下所示:

project(example)
set(BUILD_TESTS FALSE CACHE BOOL "Build unit tests")
if(BUILD_TESTS)
    add_definitions(-DUNIT_TESTING)
    add_subdirectory(test)
endif()
add_subdirectory(src)

然后你配置项目两次:

  1. build/src: cmake ../../code
  2. build/test: cmake -DBUILD_TESTS:BOOL=TRUE ../../code

(2.) 将构建 srctest 以及额外的 #define 而 (1.) 将仅构建 src.

将 m.s. 的回答进一步 How to build a program with 2 different values of a variable in CMake,您甚至可以在一个生成的构建环境中执行此操作。

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(Example C)
add_subdirectory(src)
add_subdirectory(test)

src/CMakeLists.txt

set(inFiles table.c table.h)
add_library(TableLib ${inFiles})
add_library(TestTableLib ${inFiles})
set_property(TARGET TestTableLib APPEND PROPERTY COMPILE_DEFINITIONS "UNIT_TESTING")

test/CMakeLists.txt

add_executable(TestTableExe test_table.c)
add_dependencies(TestTableExe TestTableLib)
# add_test(NAME RunTableTest COMMAND ...)

CMake 会注意 TableLibTestTableLib 的编译器输出最终位于不同的目录中。

唯一的缺点是您将拥有两个具有相同源文件的目标(TableLibTestTableLib)。但是您可以将它们分组在某些具有 FOLDER 目标 属性.

的 IDE 中

另一种方法是将您需要的文件直接编译到测试中。如果你有 mocked/stubbed 而你不想或不能 link "code do be tested".

的所有依赖项,这有时会非常方便

test/CMakeLists.txt(包含所有来源的版本)

include_directories(../src)
add_definitions(-DUNIT_TESTING)
add_executable(TestTableExe test_table.c ../src/table.c ../src/table.h)
# add_test(NAME RunTableTest COMMAND ...)