'Avoid repeating config between Conan profile and CMake
I have been learning Conan for a personal project, and I have a question that I haven't been able to answer from looking at the docs and examples.
There seems to be an awkward lack of interaction between Conan's "profiles" and CMake. What I mean is: There are a number of different build parameters that must be manually kept in sync - running CMake with different parameters than the ones that were chosen during conan install will result in build errors.
To give a more concrete example, here are two of my configs and how I would use them to build:
$ cat ~/.conan/profiles/gcc_debug
[settings]
os=Linux
os_build=Linux
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=10
compiler.libcxx=libstdc++11
build_type=Debug
[options]
[build_requires]
[env]
$ export CC=/usr/bin/gcc
$ export CXX=/usr/bin/g++
$ conan install ../src --profile gcc_debug
$ cmake ../src -GNinja -DCMAKE_BUILD_TYPE=Debug
$ cmake --build .
$ cat ~/.conan/profiles/clang_cl_release
[settings]
os=Windows
os_build=Windows
arch=x86_64
arch_build=x86_64
compiler=Visual Studio
compiler.version=16
compiler.toolset=ClangCL
build_type=Release
[options]
[build_requires]
[env]
$ conan install ../src --profile clang_cl_release
$ cmake ../src -G"Visual Studio 16 2019" -TClangCL
$ cmake --build . --config=Release
In the first example, I have to repeat gcc and Debug.
In the second one, I have to repeat Visual Studio, 16, ClangCL, and Release.
Having to repeat myself so many times feels smelly, especially when these options are spread out across multiple long-running commands, and forgetting one just option can result in non-obvious error messages. It also seems weird to me that Conan doesn't just enforce (override) the appropriate CMake vars when you call cmake_basic_setup(); it already knows what values it expects, and blows up if they don't match.
What is the recommended way to handle this?
Solution 1:[1]
Normally you would use Conan to setup all your external libraries and then use them from CMake. You can however do the other way around: Let CMake call Conan to install the external dependencies.
Example code from How to launch conan install from cmake:
cmake_minimum_required(VERSION 2.8)
project(myproject CXX)
# 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://raw.githubusercontent.com/conan-io/cmake-conan/master/conan.cmake"
"${CMAKE_BINARY_DIR}/conan.cmake")
endif()
include(${CMAKE_BINARY_DIR}/conan.cmake)
conan_cmake_run(REQUIRES Catch2/2.6.0@catchorg/stable
BASIC_SETUP)
add_executable(main main.cpp)
target_link_libraries(main ${CONAN_LIBS})
Solution 2:[2]
See recommended conan usage: https://github.com/conan-io/cmake-conan
set(CONAN_PROFILE_NAME ${CMAKE_SYSTEM_NAME}-${CMAKE_GENERATOR})
execute_process(COMMAND ${CONAN_CMD} profile new ${CONAN_PROFILE_NAME} --detect ERROR_QUIET)
conan_cmake_autodetect(settings)
# REPEAT THIS FOR EACH OF YOUR REMOTES
conan_cmake_configure(REQUIRES zlib/1.2.0 GENERATORS cmake_find_package)
conan_cmake_install(PATH_OR_REFERENCE .
BUILD missing
REMOTE conancenter
PROFILE ${CONAN_PROFILE_NAME}
SETTINGS ${settings})
find_package(zlib)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mats L |
| Solution 2 | Sergei Krivonos |
