There are already some good answers from Soeren and mascoj but I would like to give a more concrete recommendation.
When you already have a CMakeLists.txt for your executable and you like to add testing, I recommend adding a static dummy library. This library can have all the sources of the executable except the main method (it may be easiest to single out the main method in a separate file if you do not have that already). Using a static library will give you two benefits:
- The final executable will behave exactly as your current one, so there is no need to deal with distribution of a new, shared library
- You do not need to deal with exporting symbols or throwing exceptions across shared object boundaries
The changes to your CMakeLists.txt can be quite small. I will give an example here, assuming you use cmake 3.0 or newer. First, an example of CMakeLists.txt before adding the dummy library:
project(MyProject)
set(SOURCES src/First.cc src/Second.cc src/Third.cc)
add_executable(${PROJECT_NAME} ${SOURCES} src/Main.cc)
target_include_directories(${PROJECT_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR})
target_compile_options(${PROJECT_NAME}
$<$<CXX_COMPILER_ID:GNU>:-Wall;-pedantic)
target_compile_definitions(${PROJECT_NAME}
$<$<CONFIG:Debug>:DEBUG;_DEBUG>)
set_target_properties(${PROJECT_NAME}
PROPERTIES CXX_STANDARD 14)
target_link_libraries(${PROJECT_NAME}
Threads::Threads)
To add the dummy library and testing, you need to introduce a new target with a different name. I choose here to use ${PROJECT_NAME}_lib
because this will be very non-intrusive on the CMakeLists.txt. Here is the updated version. Notice the use of ${PROJECT_NAME}_lib
in place of ${PROJECT_NAME}
in almost all places. Most properties are now passed down to the executable by making them PUBLIC
. Only calls to set_target_properties()
are not transitive and must be duplicated for library and executable.
project(MyProject)
set(SOURCES src/First.cc src/Second.cc src/Third.cc)
add_library(${PROJECT_NAME}_lib STATIC ${SOURCES})
add_executable(${PROJECT_NAME} src/Main.cc)
target_include_directories(${PROJECT_NAME}_lib PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_BINARY_DIR})
target_compile_options(${PROJECT_NAME}_lib PUBLIC
$<$<CXX_COMPILER_ID:GNU>:-Wall;-pedantic)
target_compile_definitions(${PROJECT_NAME}_lib PUBLIC
$<$<CONFIG:Debug>:DEBUG;_DEBUG>)
set_target_properties(${PROJECT_NAME}_lib
PROPERTIES CXX_STANDARD 14)
set_target_properties(${PROJECT_NAME}
PROPERTIES CXX_STANDARD 14)
target_link_libraries(${PROJECT_NAME}
${PROJECT_NAME}_lib
Threads::Threads)
Now you can link your tests against ${PROJECT_NAME}_lib
with a different main method.