How Do I Get CMake To Find Boost When Using Conan?

Taylor Built Solutions Logo

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.

Short Update — I had some problems with cmake_findboost_modular creating the necessary shortcuts to properly link the Boost::program_options library on Windows with Visual Studio 2019. After talking to Jerry Wiltse, who is one of the maintainers on cmake_findboost_modular, I decided just to link with Conan’s default target for all of Boost. While this isn’t ideal it works and I will, at some point, take a further look into how Conan generates it’s link targets and see if I can help in this regard. Given that this is a side project at the moment this may take a while for me to get to. Anyway, Conan is still great and I highly recommend it.

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 the Barbarian or 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()
Code language: PHP (php)

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:

  1. Conan did actually make the pathing to its packages available.
  2. How to get that pathing into CMakeLists.txt
  3. 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:

Read The Freaking Manual

Leave a Reply

Your email address will not be published. Required fields are marked *