How to use conan with CMake to generate multi-config Visual Studio Solution Files?
What is your question?
Hello,
We have a sizeable C/C++ code base that uses CMake to generate multi-config solution files for Windows, as well as single config make file for Linux. Our company is split pretty evenly between Linux and Windows developers.
We would like to use Conan for package management and integration with GitLab. I've worked through the examples, and I'm stuck on one issue. How do I use Conan with CMake to generate a multi-configuration Visual Studio solution file that allows me to select any of the configurations and compile?
Here is the problem I noticed. I worked through the tutorial's Build a simple CMake project using Conan demo.
Following the instructions, I created a Visual Studio solution file that would compile when using the command line cmake --build . --config Release or the Visual Studio IDE set to Release.
I noticed the VS IDE still had the selector for Debug and RelWithDebInfo, so I tried compiling Debug, and it failed saying it couldn't find zlib.h file. I used the VS IDE and quickly saw that the extra include paths and link libraries for Debug weren't set.
This makes sense, because I only configured Release, but I cannot find any documentation that explains how to get it to work with both Release and Debug at the same time.
I found the tutorial page "Building for multiple configurations: Release, Debug, Static and Shared", but this page explains how to change configuration, essentially meaning a separate solution file per configuration.
How can I use conan to to install the desired dependencies: Release and Debug and then run cmake to use the installed Release and Debug dependencies?
Have you read the CONTRIBUTING guide?
- [X] I've read the CONTRIBUTING guide
I continued to play around with this and I found that the following steps appear to do what I want:
conan install . --output-folder=build --build=missing --settings=build_type=Release
conan install . --output-folder=build --build=missing --settings=build_type=Debug
conan install . --output-folder=build --build=missing --settings=build_type=RelWithDebInfo
cd build
cmake .. -G "Visual Studio 15 2017" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
However, I don't see this actually documentation that approves or sanctions this, but I recall wording in the introduction that I interpreted to say, "if it's not documented, it can be broken at any time by a new release."
Hi @RochaStratovan
Your steps are completely correct. We try to describe about configurations in https://docs.conan.io/2/tutorial/consuming_packages/different_configurations.html, but it is true that it is not that explicit this for Visual Studio multi-configuration projects
In other parts like https://docs.conan.io/2/examples/tools/cmake/cmake_toolchain/build_project_cmake_presets.html#examples-tools-cmake-toolchain-build-project-presets it describes
We can call conan install to install both Release and Debug configurations. Conan will generate a conan_toolchain.cmake at the corresponding generators folder:
$ conan install . $ conan install . -s build_type=Debug
To install both configurations first
I am moving this ticket to the docs repo to try to improve this, thanks for the feedback!
@memsharded should conan tell cmake to only generate the configurations that have been conan installed? E.g., by setting CMAKE_CONFIGURATION_TYPES or similar in the toolchain file.
I was stumped for a while trying the get the debug configuration to build when only Release had been conan installed (I didn't realise release was the conan default).
I'm also curious to know why conan install doesn't overwrite the previous build type, I couldn't see any file in build that looks like it keeps infomation relating to the previous installed configurations.
This I've tried, does it make sense? Should something like this be added by default?
def generate(self):
tc = CMakeToolchain(self)
# This stops extra configurations from being generated
# See https://github.com/conan-io/docs/issues/3517
if tc.is_multi_configuration:
configuration_types = set([self.settings.get_safe("build_type")])
preset_path = Path(self.generators_folder) / "CMakePresets.json"
if preset_path.exists():
preset = json.loads(preset_path.read_text())
# Conan generated presets should have only 1 configurePreset, no more
cache_variables = preset["configurePresets"][0]["cacheVariables"]
if existing := cache_variables.get("CMAKE_CONFIGURATION_TYPES"):
configuration_types.update(existing.split(";"))
tc.cache_variables["CMAKE_CONFIGURATION_TYPES"] = ";".join(
sorted(configuration_types)
)
tc.generate()
And to answer my question as to why is doesn't overwrite the previous build type, it looks like actually reads in the previous toolchain file and updates individual variables.
Hi @parched
Thanks for the feedback.
The
$ conan install .
$ conan install . -s build_type=Debug
Are mostly to install the different dependencies binaries, but is not that connected to the way they are consumed.
You might have only Debug type in the consumer, and want to use sometimes the Release dependencies and other the Debug dependencies (this might be possible only in Linux, but not Windows)
The build type of the consumer can be explicitly defined with:
$ conan install . -s build_type=Release -s "&:build_type=Debug"
$ conan install . -s build_type=Debug
Also, modern CMake > 3.27 doesnt need explicit mapping of Configuration types, so users are free to pick what they want.
The new CMakeConfigDeps generator in https://docs.conan.io/2/incubating.html does a step further and allows this automatic CMake mapping of configuration types for crossed configurations (consumer in Debug, dependencies in Release).
The recommendation would be then to not modify CMAKE_CONFIGURATION_TYPES, and Conan doesn't have plans to do it either. In the current version, explicit installation of build_types for dependencies and the current consumer is recommended, in the future the new CMakeConfigDeps generator will further simplify this.