Replies: 2 comments
-
Thank you for writing this well written and comprehensive guide, I'm sure it'll be useful to other Conan users. Dealing with build systems in C++ can be frustrating at times. This is the first time I hear about CMake's dependency providers, sounds like a very welcome addition. |
Beta Was this translation helpful? Give feedback.
-
I have not built freetype on windows, but I can talk some about this. Freetype hand harfbuzz had provided cmakelists.txt: https://github.com/freetype/freetype/blob/master/CMakeLists.txt and https://github.com/harfbuzz/harfbuzz/blob/main/CMakeLists.txt. So you can just add these projects as git submodule, then modify rmlui's CMakeLists.txt, remove find_package(freetype), but just link and include target freetype. Like this: This is rlottie above, but I think freetype is same. |
Beta Was this translation helpful? Give feedback.
-
After struggling for several days on how to do this, I finally found a way to do it and thought it might be useful for anyone else having the same issues as I did.
Explanation
In order to use unreleased versions of RmlUi (git) or use versions of RmlUi that haven't been distributed yet in vcpkg or Conan one has to go through the process of building RmlUi from source. While this might seem easy at first, having to download a compiled binary and paste it inside the source tree of a dependency, even if it's ignored by Git, is rather inconvenient. There's no guarantee you'll be able to find a Freetype distribution that matches your requirements (linkage, compiler and ABIs, version, compile options...), specially on Windows where most distributions are only compiled using MSVC, not to mention the fact that you still have to "install" them and how cumbersome it is in Windows.
For this reason, I followed the official Conan documentation to download Freetype 2.10.4 for Windows, just to find out that the instructions in Conan Center make you use a toolchain file to populate variables instead of using an initial cache script (argument
-C <initial-cache-script>
when configuring/generating the project). And there's a problem with that logic:Using toolchain files like this goes against the nature of CMake toolchain files being intended to be used in cross-compilation scenarios, and it's also the reason why I don't like using vcpkg no matter how straightforward it might seem to use. In fact, the method described in Conan Center, which uses the CMake toolchain file, doesn't even work and makes the build process of RmlUi fail due to missing headers.
Making things worse, due to Conan being in the process of revamping their integration with CMake for their 2.0 release by declaring the older integration methods obsolete and replacing them with new (and as of today, unstable) ones, their documentation about the CMake integration is all over the place and fragmented between their Getting Started guide, the Conan Center instructions and the more in-depth articles from their documentation.
About the newer Conan generators:
CMake
is intended to be used only inside a Conan package recipe and not by integrators/users of said packagesCMakeToolchain
goes against the nature of CMake toolchain files, and as of today it doesn't even work for this caseCMakeDeps
utilizes CMake package config files instead ofFind<package>.cmake
modules, which should be the idealHowever, while using
CMakeDeps
allows for a successful project configuration and build, the final linking step fails with MSVC errorLNK2019
due unresolved external symbols related to Brotli and PNG. Why? Because RmlUi usesfind_package(Freetype ...)
to find Freetype, which fallbacks to the CMake-providedFindFreetype.cmake
module, which somehow enters in conflict with the Freetype distribution from Conan and ends up breaking symbol linking and/or includes for Freetype.Because of all of this, and by the means of the official documentation, there's no way to make this work. But reality seems to tell otherwise.
How to actually do it (for CMake superprojects)
The goal for this, or at least the one I had when trying to find a way to do it, is to set up CMake in a way that no user intervention neither any kind of dedicated "bootstrap" or "development environment configuration" scripts are needed. Just installing Conan and generating the project or loading the root source folder in an IDE with CMake integration is all that's needed for everything to be properly set up.
For the sake of respecting the CMake binary directory workflow, all Conan-generated files will go inside the CMake binary directory that you generate. This allows you to keep multiple binary directories with different configurations (target platform, architecture, toolchain, compile flags...) living under your source tree without having problems of one build suddenly trying to link against an incompatible Conan package binary.
To share configuration settings between people (ex. to set
CONAN_PROFILE
, compilers, flags...) it is strongly advised to use CMake Presets.For this explanation, a minimal reference project will be used with the following structure:
In the file structure,
rmlui
is folder containing a copy of the RmlUi source code, whilemain.cpp
contains the following:The solution for this issue and how to build RmlUi using Conan's Freetype depends on the version of Conan and the version of CMake:
CMake
<= 3.23
Conan
< 2.0
In CMake 3.23 and lower, calls to
find_package()
will default to module mode. If the ConanCMakeDeps
generator is used to point CMake to the packages, the RmlUi project will still ignore some of the settings from the Conan configuration files, go with the CMake ones and therefore break the symbol references just like it was told above. To solve this, we need to force CMake to ignore its own find modules and stick to what Conan specifies by making Conan create alternative find modules that supersede the default ones:conanfile.txt
CMakeLists.txt
To configure and build:
Check the contents of the default Conan build profile for your platform using:
Which in Windows with Visual Studio 2022 installed should result in:
Decide whether or not the default profile meets your requirements:
-DCONAN_PROFILE=<absoulte_or_relative_to_the_cmake_binary_dir_path_to_profile>
to CMake when configuring/generating the project for Conan to use your new profile file.Configure the CMake project or load it in an IDE with CMake integration and compile it
Conan
>= 2.0
In Conan 2.0, due to the deprecation of the
cmake_find_package
andcmake_find_package_multi
it won't be possible to integrate Freetype from Conan into the CMake project using them (or at least it won't be the "right" way to do it anymore) and I don't know if using theCMakeToolchain
andCMakeDeps
will end up working with RmlUi anyway.Something that might help is
CMAKE_FIND_PACKAGE_REDIRECTS_DIR
from CMake 3.24, which will allow to redirect all calls offind_package()
use a config file if present in this directory before anything else, even if the call forfind_package()
enforces module mode.The CLI of Conan 2.0 will also enforce build profiles for both host and build, which will make the
I'll update this when I get to try the stable versions of both CMake 3.24 and Conan 2.0.
CMake
>= 3.24
CMake 3.24 introduces Dependency Providers, which should allow package managers like Conan and vcpkg to integrate more tightly with CMake. Due to the release of CMake 3.24 being way closer in time than the release of Conan 2.0, we might seem heavy overhauls to the integration between CMake and Conan before the release of Conan 2.0.
If you use CMake 3.24 with Conan < 2.0, the method for CMake 3.23 and Conan < 2.0 should work just fine.
However for the case of Conan >= 2.0 it's still uncertain whether it will work or not. But thanks to the addition of the
CMAKE_FIND_PACKAGE_REDIRECTS_DIR
variable, it might be possible to completely forget about CMake find modules and just work with the CMake config files generated by Conan using theCMakeDeps
generator.I'll update this when I get to try the stable versions of both CMake 3.24 and Conan 2.0.
How to actually do it (for superprojects using other build systems)
In order for RmlUi to detect Freetype, the same information from Conan needs to be passed to CMake. Regardless of the integration your build system might have with CMake, your build system needs to run the equivalent to these CLI commands:
Keep in mind the changes in Conan profiles after the release of Conan 2.0 to adapt your commands to the new CLI specification.
Beta Was this translation helpful? Give feedback.
All reactions