I am writing software for a platform that has both 64-bit and 32-bit cores and I want to write unit tests for both sets of software using googletest. I want to build the tests so that the tests for the 64-bit software are also built 64-bit and similarly 32-bit tests should be built 32-bit. This means that googletest has to be built separately 64 & 32-bit for both targets. I have been able to write CMakeLists that accomplish this when built separately, but when I create a main CMakeLists.txt file in the parent directory that includes all subdirectories the build fails because googletest is only built once and linking fails when because of architecture incompatibilities.
I am using vscode and I would like to be able to compile all tests for both architectures at once without having to manually change the cmake.sourceDirectory in vscode cmake extension and compile each target separately. I know I could just manually compile separate 32 & 64 bit libraries, add them to my project structure and configure CMake to link to those but I wouldn't want to add those libraries (and gtest headers) to my git-repository. I prefer using the CMake FetchContent feature to get and compile them on demand. Basically I would like two compile and build each target separately instead of first compiling all targets and then linking them which it seems to do now. Is this possible?
I am pretty much a noob with CMake so I feel like I'm just missing something obvious and there's some easy way of doing what I want.
Here's a simple example project that I've been playing around with trying to get this to work. My actual project has similar structure but has multiple 64-bit targets and one 32-bit target:
├─ CMakeLists.txt
├─ test32/
├─ CMakeLists.txt
├─ src/
├─ calc32.c
├─ calc32.h
├─ tests/
├─ tests32.cpp
├─ unit_tests_main.cpp
└─ test64/
├─ CMakeLists.txt
├─ src/
├─ calc64.c
├─ calc64.h
├─ tests/
├─ tests64.cpp
├─ unit_tests_main.cpp
The src-folders contain the application software that I'm trying to write tests for and the tests-folders contain the tests. The calc32 & 64 files just contain a single function that adds two integer parameters together and returns the result and the tests32 & 64 files each have a simple test that tests that the functions indeed return the result of the addition. Unit_tests_main.cpp-files have the gtest main function.
The root CMakeLists.txt:
cmake_minimum_required(VERSION 3.14)
project(tests)
add_subdirectory("test32")
add_subdirectory("test64")
The test32 CMakeLists.txt:
project(test32)
cmake_minimum_required(VERSION 3.14)
set(EXEC_NAME "calc32")
set(TEST_EXEC_NAME "calc32_tests")
set(TEST_DIR "./tests")
set(SRC_DIR "./src")
include(GoogleTest)
include(FetchContent)
enable_testing()
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.13.0
)
FetchContent_MakeAvailable(googletest)
add_executable(${TEST_EXEC_NAME}
${TEST_DIR}/unit_tests_main.cpp
)
# Trigger 32 bit build for both gtest & application
set_target_properties(gtest PROPERTIES COMPILE_OPTIONS "-m32" LINK_FLAGS "-m32")
set_target_properties(${TEST_EXEC_NAME} PROPERTIES COMPILE_OPTIONS "-m32" LINK_FLAGS "-m32")
# Add the files that contain your tests here
target_sources(${TEST_EXEC_NAME} PUBLIC
${TEST_DIR}/tests32.cpp
)
# Add the source files under test and their dependencies here
target_sources(${TEST_EXEC_NAME} PUBLIC
${SRC_DIR}/calc32.c
)
target_include_directories(${TEST_EXEC_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR};
${SRC_DIR};
)
target_link_libraries(
${TEST_EXEC_NAME}
gtest
)
gtest_discover_tests(${TEST_EXEC_NAME})
and finally the test64 CMakeLists.txt
project(test64)
cmake_minimum_required(VERSION 3.14)
set(EXEC_NAME "calc64")
set(TEST_EXEC_NAME "calc64_tests")
set(TEST_DIR "./tests")
set(SRC_DIR "./src")
include(GoogleTest)
include(FetchContent)
enable_testing()
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.13.0
)
FetchContent_MakeAvailable(googletest)
add_executable(${TEST_EXEC_NAME}
${TEST_DIR}/unit_tests_main.cpp
)
# Add the files that contain your tests here
target_sources(${TEST_EXEC_NAME} PUBLIC
${TEST_DIR}/tests64.cpp
)
# Add the source files under test and their dependencies here
target_sources(${TEST_EXEC_NAME} PUBLIC
${SRC_DIR}/calc64.c
)
target_include_directories(${TEST_EXEC_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR};
${SRC_DIR};
)
target_link_libraries(
${TEST_EXEC_NAME}
gtest
)
gtest_discover_tests(${TEST_EXEC_NAME})
As you can see they are pretty much identical except for the two extra set_target_properties-lines in the 32-bit CMakeLists.txt