Cmake, Conan, and GTest Example
A minimal example of a project that uses cmake, conan, and gtest. I make use of the very handy cmake-conan wrapper. This setup also works seamlessly in CLion
Source Code: https://github.com/jroddev/basic-conan-cmake-gtest-project
This sample project is what I would consider a minimal example of a project that uses cmake, conan, and gtest. I make use of the very handy cmake-conan wrapper. This setup also works seamlessly in CLion (using cmake directly, not the conan plugin).
.
|_ cmake
| |_ conan.cmake
|_ app
| |_ include
| |_ src
| |_ test
| | |_ CMakeList.txt
| |_ CmakeList.txt
|_ CmakeList.txt
|_ conanfile.txt
First thing you'll probably notice is there are quite a few cmake files.
- ./CMakeList.txt: top-level cmake file, includes the others
- ./cmake/conan.cmake: Setup cmake-conan wrapper
- ./app/CMakeList.txt: Handles building of the app module
- ./app/test/CMakeList.txt: Sets up test executable and adds it to CTest
cmake-conan allows you to configure conan directly in cmake instead of requiring a conanfile.txt. However in order to get this working I would have needed to move code out of conan.cmake and into the root CMakeList.txt. Because I wanted to keep the cmake-conan details hidden I decided to move all the cmake code into the conan.cmake file and to have a conanfile.txt at the root.
Top Level CMakeList.txt
cmake_minimum_required(VERSION 3.22)
project(conan_project)
set(CMAKE_CXX_STANDARD 20)
include(cmake/conan.cmake)
option(RUN_TESTS "Build the tests" ON)
if(RUN_TESTS)
enable_testing()
find_package(GTest)
endif()
add_subdirectory(app)
The job of this file is some basic boiler plate and then to include other cmake files. At the end I include the 'app' module using add_subdirectory.
CMake Conan Helper File
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.16.1/conan.cmake"
"${CMAKE_BINARY_DIR}/conan.cmake"
EXPECTED_HASH SHA256=396e16d0f5eabdc6a14afddbcfff62a54a7ee75c6da23f32f7a31bc85db23484
TLS_VERIFY ON)
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
conan_cmake_autodetect(settings)
conan_cmake_run(CONANFILE ${CMAKE_CURRENT_SOURCE_DIR}/conanfile.txt
BASIC_SETUP CMAKE_TARGETS
BUILD missing
REMOTE conancenter
SETTINGS ${settings}
)
Most of this is copy and pasted from the cmake-conan README.md. One modification I made was to opt for a conanfile.txt file at the project root directory.
Conanfile
[requires]
gtest/1.10.0
spdlog/1.9.2
[generators]
cmake_find_package
App Module
add_executable(conan_project src/main.cpp)
find_package(spdlog)
target_include_directories(conan_project PRIVATE
include
${spdlog_INCLUDE_DIR}
)
target_link_libraries(conan_project spdlog::spdlog)
set(app_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
if(RUN_TESTS)
add_subdirectory(test)
endif()
This is the file most likely to grow with the project. I find, include, and link the spdlog library. I found spdlog_INCLUDE_DIR and spdlog::spdlog by looking in the cmake generated Findspdlog.cmake file. The cmake-conan wrapper will create a Find<dep>.cmake file for each dependency. You can use these files to see what variables are set and what targets are exported.
App Test Module
add_executable(conan_project_tests main.cpp)
target_include_directories(conan_project_tests PRIVATE ${app_SOURCE_DIR}/include)
target_link_libraries(conan_project_tests GTest::gtest_main)
add_test(NAME conan_project_tests
COMMAND conan_project_tests)
set_tests_properties(${conan_project_tests} PROPERTIES TIMEOUT 10)
This file creates, compiles and links the test executable. add_test is used to register this test suite with CTest.
Build and Test
If you're using cmake you can just run the executable and tests from the IDE.
If you're building from the commandline the the .github/workflows/cmake.yml pipeline has a working example. Here is a cleaned, simpler version:
# configure
cmake -B build -DCMAKE_BUILD_TYPE=Release
# build
cmake --build ./build/ --config Release
# run
./build/bin/conan_project
# test
ctest --test-dir build/