This was originally posted on my blog and is being re-posted here for reach. Please share it and let me know if you liked it or have any questions!
Recently I was watching Jason Turner’s series on creating an RPG game with C++20. In this he mentions the use of a C++ starter project that uses CMake and Conan to setup good practices from the start of the project (here’s the video walking through the creation of the project). I recently started a project using CMake to create the build files on different OS’s and had some trouble with it. Given that I thought I’d update my CMake setup for the project to the starter project that Jason used. While doing that, however, I ran into trouble getting CMake to find the version of Boost that Conan installed. Here’s what I did to resolve that.
TL;DR — Read the manual, of course. Also use cmake_findboost_modular to pull just sub-modules of Boost.
What is Conan?
And why am I giving a summary of what it is when this is a post about a solution to a specific problem? Because defining what Conan is and what it does will help clarify the problem. It did for me. I’d just jumped into using Jason’s starting project as a template without fully understanding the tools in use and I had to learn about them to find the solution.
So Conan: The … Package Manager?
Conan is a package manager that allows for the installation and management of C and C++ dependencies. It is a stand-alone app that can be run by itself. It also happens to have great integration with CMake. This integration with CMake is what the starter project makes use of and, thus, what I am making use of.
Goal: Get a Specific Library Within Boost
When I created the EveSDEImporter project and determined that I wanted to handle command line arguments I decided to use Boost’s Program Options library. There are many ways & libraries for handling command line parameters but, given that I hadn’t played with Boost at all and it is a large and popular set of C++ functionality, I thought I’d go with program options to get some experience with Boost. That being said, it took me more time than I would’ve liked to download the Boost source, build it, and figure out how to get the program options library linked into the EveSDEImporter executable with CMake. Given that Conan is a package manager it was my hope to use it to get Boost and make it easy to include in the project.
How do you tell Conan to download Boost?
The Conan.cmake file that is part of the C++ starter project creates a macro that does the Conan setup. My Conan.cmake is almost identical to the starter projects’ with the exception that I replaced docopt with Boost. Note that this isn’t a judgement on docopt. I’d just been using Boost so I decided to continue with it.
macro(run_conan)
# Download automatically, you can also just copy the conan.cmake file
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
file(DOWNLOAD "https://github.com/conan-io/cmake-conan/raw/v0.15/conan.cmake" "${CMAKE_BINARY_DIR}/conan.cmake")
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
conan_add_remote(
NAME
bincrafters
URL
https://api.bintray.com/conan/bincrafters/public-conan)
conan_cmake_run(
REQUIRES
${CONAN_EXTRA_REQUIRES}
catch2/2.11.0
cmake_findboost_modular/1.69.0@bincrafters/stable # MINE
boost/1.73.0 # MINE
fmt/6.2.0
spdlog/1.5.0
OPTIONS
${CONAN_EXTRA_OPTIONS}
BASIC_SETUP
CMAKE_TARGETS # individual targets to link to
BUILD
missing)
endmacro()
One of the issues I had with CMake on Windows was that CMake’s find_package() was finding an older version of Boost that I had around. As I was looking around for how to tell find_package() to get the correct version I stumbled across cmake_findboost_modular. You’ll see this in my Conan.cmake and it immediately resolved the issue with finding the correct version of Boost. I’ll note that I didn’t have this problem on OS X but I have confirmed that adding cmake_findboost_modular did not cause problems there.
How do I tell CMake to use Boost::program_options? Like normal-ish
There are several things that need to happen to get CMake to tell the build system it creates to link Boost::program_options to the executable being built. The first way thing that we need to do when we are using Conan to manage packages is to tell CMake to load the info that Conan creates that contains all of the paths to where Conan downloaded packages (among other things). In the CMakeLists.txt for the executable that needs a Boost package this can be done with the following:
# Include Conan info
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
Once we have all the information from Conan we can use it to tell CMake where to find Boost and to go actually find it:
# Dependencies -- Boost
Set(Boost_INSTALL_DIR ${CONAN_BOOST_ROOT})
find_package(Boost 1.73.0 COMPONENTS program_options REQUIRED)
After this has been included we can do the normal step of including Boost::program_options as one of the target_link_libraries:
# Main executable
add_executable(intro main.cpp)
target_link_libraries(
intro
PRIVATE project_options
project_warnings
SDEParser
Boost::program_options
CONAN_PKG::fmt
CONAN_PKG::spdlog)
Once this has been entered into the CMakeLists.txt for the project that needs a Boost library CMake can be run to build the build system.
Conclusion
CMake is a complex system that has a TON of options to help you build your build system in a way that will work across operating systems and build tools. It wasn’t until I sat down and actually read the manual for Conan that I realized that:
- Conan did actually make the pathing to its packages available.
- How to get that pathing into CMakeLists.txt
- That, past specifying where the packages are, including a package in target_link_libraries is just like doing it without Conan
I hope that this helps you if you’re struggling with how to get Conan to find Boost and use packages. And, as always, I need to remind myself of this:
Top comments (2)
As an FYI you should not need to use cmake_findboost_modular any longer. If you use the camke generator from Conan it will create the conanbuildinfo.cmake which you can then include as shown above. Here is a good starting point for conan/CMake integration docs.conan.io/en/1.36/integrations...
Thanks! I know I'm a while coming back to dev.to so this is a late response. I'll check it out