After a lot of hard work and research, I've managed to make multiple cmake targets to separate running my program from running tests on the code. But I don't like what I've made because I see redundancy in the CMakeList.txt
files.
Currently I have to add every new source file to both targets so that the source target can build using that file and the test target can build since they need to test that file. I can't throw the entire source target into the test target because then the test target would contain two main files.
My only idea of how to fix the redundancy is to put all of the files in the source target without the main.cpp
file into some group, and then attach that group to both targets. That way the source target contains just the main.cpp
file and the source file group, and the test target contains all its tests and the source file group. So the file group would basically be all of the overlap between the two targets. I just don't know how to do that.
Research
Here's the other stack overflow questions I found that helped me get to where I am:
- what does target option mean in cmake
- how to use cmake with catch2
- cmake one build directory for multiple projects
Code
Here is my test project I made to experiment with catch2 and cmake that currently works for both build targets "tests" and "catch2Test":
/catch2Test // <-- project folder
|---- /include
| |---- /catch2
| |---- catch.hpp
|---- /src
| |---- /myMath
| | |---- factorial.cpp
| | |---- factorial.h
| |---- main.cpp
| |---- CMakeLists.txt
|---- /test
| |---- test_main.cpp
| |---- test_factorial.cpp
| |---- CMakeLists.txt
|---- CMakeLists.txt
/include/catch2/catch.hpp
is the library header file for catch2
/src/myMath/
contains the header file and code file for the factorial implementation, same as used in the catch2 tutorial. This is also where the implementation for the factorial tests come from.
/src/main.cpp
is a simple main file that includes factorial.h to do factorial math and then prints it to cout.
Here's explicit code for the remaining files that actually matter:
/test/test_main.cpp
#define CATCH_CONFIG_MAIN
#include "../include/catch2/catch.hpp"
/test/test_factorial.cpp
#include "../include/catch2/catch.hpp"
#include "../src/myMath/factorial.h"
TEST_CASE("Factorials are computed", "[factorial]")
{
REQUIRE(factorial(0) == 1);
REQUIRE(factorial(1) == 1);
REQUIRE(factorial(2) == 2);
REQUIRE(factorial(3) == 6);
REQUIRE(factorial(10) == 3628800);
}
/CmakeLists.txt
cmake_minimum_required(VERSION 3.13)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(src)
add_subdirectory(test)
/test/CMakeLists.txt
add_executable(tests
../src/myMath/factorial.cpp ../src/myMath/factorial.h
../include/catch2/catch.hpp
test_main.cpp
test_factorial.cpp
)
/src/CMakeLists.txt
add_executable(catch2Test
main.cpp
myMath/factorial.cpp myMath/factorial.h
)
Running
When I run the catch2Test target, I get desired results:
Hello, World!
Factorial 0! = 1
Factorial 1! = 1
Factorial 2! = 2
Factorial 3! = 6
Factorial 6! = 720
Factorial 10! = 3628800
Process finished with exit code 0
And when I run the tests target, I also get desired results:
===============================================================================
All tests passed (5 assertions in 1 test case)
Process finished with exit code 0
It all works, I just don't like my current solution.
How can I make my targets more easily extendable?
Also, side question: what's the more appropriate way to include a header library? I assume it's not supposed to be in the add_executable()
like I did in /test/CMakeLists.txt
as ../include/catch2/catch.hpp
...