2

I have a project structure defined below with both src and test directories.

├── 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]

I'd like to configure cmake so that when the tests (unit testing) directory is built that it also compiles files in the ./src directory with the UNIT_TESTING define set and puts all build artifacts in the ./build/test/ directory.

This is so that I can track memory leaks by using wrapper functions for malloc free etc when UNIT_TESTING and the real memory allocation functions when building normally without unit test.

Does anyone know how to get me started?

m.s.
  • 16,063
  • 7
  • 53
  • 88
Adam
  • 532
  • 3
  • 11
  • 22

2 Answers2

1

First I'd recommend an out-of-source-build like this:

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

The top-level CMakeLists.txt in code would look like this:

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)

You then configure the project twice:

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

(2.) will build src and test with the additional #define while (1.) will only build src.

m.s.
  • 16,063
  • 7
  • 53
  • 88
  • Thanks for your answer. As you sure this would work? Surely (2) would still build unit testing source to ./build/src instead of the desired ./build/test/src? – Adam Jun 02 '15 at 12:00
  • (Sorry I submitted the comment before I fully typed it!) Surely (2) would still build unit testing source to ./build/src instead of the desired ./build/test/src? I wouldn't have both the production compilation and unit test compilation in the same build folder. Or is it good practice to build my production binaries in entirely different build directory to my unit tests? – Adam Jun 02 '15 at 12:10
  • @Adam you will have two fully separate builds. when you ran `make` in **build/src** it will build just `src`, and when you run `make` in **build/test** it will built `src` and `test`. all that happens inside of the respective build directory. and yes, I'd say it is good practice to separate production and test binaries. – m.s. Jun 02 '15 at 12:13
1

Taking m.s.'s answer a little further with How to build a program with 2 different values of a variable in CMake, you could even do this in one generated build environment.

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 will take care that the compiler outputs of TableLib and TestTableLib end up in different directories.

The only disadvantage would be that you will have two targets with the same source files (TableLib and TestTableLib). But you could group them in some IDEs with the FOLDER target property.

An alternative would be to just compile the files you need directly into the test. That is sometimes very handy if you have things mocked/stubbed and you don't want to or you can't link all the dependencies of the "code do be tested".

test/CMakeLists.txt (version with all sources included)

include_directories(../src)
add_definitions(-DUNIT_TESTING)
add_executable(TestTableExe test_table.c ../src/table.c ../src/table.h)
# add_test(NAME RunTableTest COMMAND ...)
Community
  • 1
  • 1
Florian
  • 39,996
  • 9
  • 133
  • 149