[new] Compatible packages regarding C++ standard #73
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This example tries to show how to handle
validate
andcompatible_packages
features together.This is a tiny scenario, but typically dependency graphs will be much bigger and information about libraries won't be as accessible as here.
Disclaimer.- This is a very opinionated dramatization using just two recipes, but it is based on a real story where I played the main character 😅
Alternative 1: recipes 'app' and 'library'
'library' recipe
In order to build your
app
you know you needlibrary/1.0
and it is available as a Conan package (maybe in ConanCenter, maybe in your own servers) and you need to build it from sources:If your compiler doesn't activate C++11 by default, we get a nice error:
and with a little knowledge of Conan we know how to fix it:
Opps! (We need a better error message here) Again a nice message that tells us we need C++14 to build the library. Easy to fix!
We have our binary available now.
'app' recipe
Now we want to use that library in our
app
. We forgot about the previous steps, maybe ourapp
is upgrading fromlibrary/0.1
tolibrary/1.0
, maybe different teams take care of the library and the application:Conan shows a nice message telling us that using
library/1.0
requires at least C++11.app
requires plain C++ but the new requirement needs C++11 to be used (API uses C++11 features):It's been easy, we have our application, all the binaries have been generated with the proper profile and can be identified. The binary we are using for
library/1.0
belongs tocompiler.cppstd=14
and the binary forapp/1.0
is being built using a profile withcompiler.cppstd=11
. This can be important metadata associated with the binaries.More importantly, this is quite straightforward from the POV of the user.
Alternative 2: recipes 'app' and 'hidden'
'hidden' recipe
The recipe for
hidden
package contains the typical linesCMAKE_CXX_STANDARD
in theCMakeLists.txt
file of the project, they are hidden to the consumer of the library. So we, Conan users, run the commands and we are able to compilehidden
at the first shot:This works because our compiler support C++14, otherwise, we would get the typical CMake error at build time. We know the error (not a template metaprogramming one, LOL).
Here we are already getting into troubles, we have generated a binary that uses C++14 but it is associated with the default profile that is using (at least my
apple-clang
) C++98... but other calls like:will succeed too, they will use C++14 even though I'm requesting C++11. This can be a problem from the ABI perspective in some scenarios.
Metadata associated with these binaries will be wrong.
'app' recipe (using hidden requirement)
We now go to the other team of developers, they retrieve the binary for
hidden/1.0
, the default profile works and they know the default for their compiler is C++98, theirapp
doesn't use modern features, they can integrate this library. Let's go!I get build errors! As an
app
developer I'm confused, this profile was suitable for thehidden/1.0@
package, but now it fails to build with of C++11 errors... is it my error? Am I missing something?At least this is a small recipe, I can have a look at the errors, at the sources and at the recipe and I realize that I need C++11 because the API contains some
auto
declarations. Good, let's build the lib:WTF! I had a binary, now I need to build from sources the package
hidden/1.0
because the new profile withcompiler.cppstd=11
computes a new package ID... even more, it tells me that I need C++14, not only C++11. Ok, at least it is easy to fix:Oh! Of course, let's use
--build=missing
:conan install app/1.0@ --build=missing -o app:use_hidden=True -s compiler.cppstd=14 ... OK!
...but I built my
app
using C++14, and I wanted it just with C++11, one more compilation:And I'm finally there.
Why do I really prefer the first approach, where the C++ standard is managed by Conan and it doesn't appear in
CMakeLists.txt
at all:Information is closer to the user, information is available when building the graph, not via an error from the build-system. This can be very important if the graph becomes big and complex, Conan can report the error after building the graph, no need to start building things to realize we need to change the
compiler.cppstd
value and start building again.Metadata Binaries can be associated with the profile used to create them.
compiler.cppstd
we know the binary uses whatever the default is for that compiler.This can be very important when using experimental features from future C++ standards that are not stable yet.
Better experience regarding ConanCenter packages. The binary available for
hidden/1.0@
is not usable at all, we need a profile withcompiler.cppstd=11
to be able to consume that package and this extra item in the profile modifies the packageID and it forces us to build from sources!!Advantages of the second approach:
CMakeLists.txt
file to remove theset(CXX_STANDARD XX)
declaration because I know it is everywhere.IMHO, libraries will keep doing (2), but our recipes in ConanCenter (as soon as we start iterating configuration with explicit
compiler.cppstd
values) should remove those lines fromCMakeLists.txt
files.