project-root
├── build
├── cmake
├── main
│ ├── CMakeLists.txt
│ └── main.cpp
├── src
│ ├── app
│ │ ├── inc
│ │ │ └── app
│ │ │ ├── appLib.hpp
│ │ │ └── appMain.hpp
│ │ ├── src
│ │ │ ├── appLib.cpp
│ │ │ └── appMain.cpp
│ │ └── test
│ │ └── CMakeLists.txt
│ │ └── test_appLib.cpp
│ ├── common
│ │ ├── inc
│ │ │ └── common
│ │ │ └── utility.hpp
│ │ └── test
│ └── core
│ ├── inc
│ │ └── core
│ │ └── coreLib.hpp
│ ├── src
│ │ └── coreLib.cpp
│ ├── test
│ │ ├── CMakeLists.txt
│ │ └── test_coreLib.cpp
│ └── CMakeLists.txt
├── testRunner
│ ├── build
│ └── CMakeLists.txt
├── ThirdParty
└── CMakeLists.txt
I'm trying to integrate unit tests to my project, so I decided to use project structure shown above. My point is to keep test and app binaries separated, and keeping test codes close to production code, aligning with Craig Scott's recommended approach.
I'm using Catch2
as a unit test library, and it's cloned under ThirdParty
dir. I can build my application binary from root/build
, and tests from testRunner/build
. But the problem is there is several binaries for each test directory. I want to make a single test binary for all test codes. I have to use single add_executable
command in a higher level, but how to do that while using Catch2::Catch2WithMain
?
root/CMakeLists.txt:
cmake_minimum_required (VERSION 3.5)
# set the build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE)
if(CMAKE_BUILD_TYPE MATCHES Debug)
message("Debug build.")
elseif(CMAKE_BUILD_TYPE MATCHES Release)
message("Release build.")
endif()
set(application_name "cmake-project-template")
set(CMAKE_CXX_STANDARD 17)
set(application_version "1.0.2")
set(PROJECT_VER ${application_version})
cmake_policy(SET CMP0048 NEW)
cmake_policy(SET CMP0079 NEW)
project (${application_name} LANGUAGES C CXX)
# set search path for CMake modules
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
find_package(PCAP REQUIRED)
find_package(MysqlConnectorCpp REQUIRED)
add_subdirectory(ThirdParty)
add_subdirectory(src)
add_subdirectory(main)
testRunner/CMakeLists.txt:
cmake_minimum_required (VERSION 3.5)
set(application_name "TEST-cmake-project-template")
set(CMAKE_CXX_STANDARD 17)
set(application_version "1.0.2")
set(PROJECT_VER ${application_version})
cmake_policy(SET CMP0048 NEW)
cmake_policy(SET CMP0079 NEW)
project (${application_name} LANGUAGES C CXX)
# set search path for CMake modules
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/../cmake/Modules)
find_package(PCAP REQUIRED)
find_package(MysqlConnectorCpp REQUIRED)
# Include Catch2 from ThirdParty
add_subdirectory(${CMAKE_SOURCE_DIR}/../ThirdParty/Catch2 build/Cathc2)
add_subdirectory(../ThirdParty build)
# enable testing
enable_testing()
# Add your test directories
add_subdirectory(../src/app/test app_test)
add_subdirectory(../src/core/test core_test)
add_subdirectory(../src src_test)
main/CMakeLists.txt:
set(source
main.cpp
)
add_library(main ${source})
target_link_libraries(main PUBLIC app core)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} app core)
src/CMakeLists.txt:
add_subdirectory(app)
add_subdirectory(common)
add_subdirectory(core)
src/core/CMakeLists.txt:
set(source
src/coreLib.cpp
)
add_library(core ${source})
target_include_directories(core PUBLIC inc)
target_include_directories(core PRIVATE inc/core)
target_include_directories(core PUBLIC ${MYSQLCONNECTORCPP_INCLUDE_DIR})
target_link_libraries(core PUBLIC
common
${MYSQLCONNECTORCPP_LIBRARY} )
src/core/test/CMakeLists.txt:
add_executable(test_core test_coreLib.cpp)
target_include_directories(test_core PRIVATE ../inc)
target_include_directories(test_core PRIVATE ../inc/core)
# Link with the core library target
target_link_libraries(test_core PRIVATE core Catch2::Catch2WithMain)
add_test(
NAME test_coreLib
COMMAND test_coreLib
)
src/app/test/CMakeLists.txt:
add_executable(test_app test_appLib.cpp)
target_include_directories(test_app PRIVATE ../inc)
target_include_directories(test_app PRIVATE ../inc/core)
# Link with the app library target
target_link_libraries(test_app PRIVATE app Catch2::Catch2WithMain)
add_test(
NAME test_app
COMMAND test_app
)
src/core/test/test_coreLib.cpp:
#include <catch2/catch_test_macros.hpp>
#include "core/coreLib.hpp"
TEST_CASE("coreLibFoo1", "[coreLib]")
{
coreLibClass x;
x.coreLibfoo1();
}