Conan: Provide an utility to compare cppstd values

Created on 10 Apr 2019  路  7Comments  路  Source: conan-io/conan

How to easily compare if 'gnu17' is is less than '20' in configure()? Could you please provide a common tool to compare that?

low good first issue medium review

Most helpful comment

I agree that is the use case all of us had in mind.
I propose this interface:

def configure(self):
    ... dependending on options, settings...
    tools.check_min_cppstd(self, cppstd=17, gnu_extensions=False)
    ...

The tool will check that the current cppstd (because declared or because it is the default of the compiler) if at least the specified number.

  • If gnu_extensions==True then it is required also that the gnu extensions are enabled.
  • If gnu_extensions==False then a valid input will be gnuXXX or XXX.
    - The gnu_extensions won't have any effect on Windows.
  • If you specify tools.check_min_cppstd(self, cppstd=14, gnu_extensions=True) an input of compiler.cppstd==14, compiler.cppstd==17 or compiler.cppstd==20 will raise, it is needed gnu14 or gnu17 or gnu20.

EDIT:

Add also tools.valid_min_cppstd() that will do the same but returning a boolean instead of raising.

EDIT:

The gnu_extensions=True won't check the OSS. It is tricky to do it automatically since you can cross build to Arduino or any other embeeded where it could makes sense but it is not linux.

All 7 comments

I like it.

We have discussed in https://github.com/conan-io/conan/pull/5440 that this is a bit more problematic than it seems:

  • Having it as a helper CppStd(self.settings.compiler.cppstd)> "14" seems very not ergonomic
  • Built-in comparison ``self.settings.compiler.cppstd) < "17" requires too hardcoded knowledge and fragile behavior (what if user defined settings like c++1y that cannot compare as integers)

A proposal could be to use the order in which the settings are defined in settings.yml. This will take some time and will try to make it for the next 1.21, not this one. Issues to take into account:

  • To make sure the right side is being promoted and validated to the type of the left side. self.settings.compiler.cppstd < "foo" should raise because "foo" is not a valid cppstd declared in the settings.yml.
  • gnu11 and 11 are not the same std
  • Make sure that only lists are valid comparisons (the rests are dictionaries, I don't think it makes sense to consider their order).
  • This is a generic mechanism to compare settings. Will be valid for any list in settings.yml

IMO the use-case is more about requiring a minimum standard than comparing them, so...

What about using a declarative approach closer to the CMake one?

def configure(self):
    ... dependending on options, settings...
    tools.CppStdRequired(self, cppstd=17, extensions=True|False)
    ...

The implementation could take advantage of the utilities we already have to parse self.settings.compiler.cppstd and identify the _number_ and the _gnu-extension-enabled_... . and also, very important, the _default-standard_ from the given compiler-version .

If it fails, raise a ConanInvalidConfiguration, if we don't know how to parse it, print a warning and do nothing.

Note for readers that by itself it's not a sufficient metric since the standard support is a very granular thing.
The tools.CppStdRequired would be quite handy when checking for the current compiler, maybe even allowing for feature-required like functionality based on that.

I agree that is the use case all of us had in mind.
I propose this interface:

def configure(self):
    ... dependending on options, settings...
    tools.check_min_cppstd(self, cppstd=17, gnu_extensions=False)
    ...

The tool will check that the current cppstd (because declared or because it is the default of the compiler) if at least the specified number.

  • If gnu_extensions==True then it is required also that the gnu extensions are enabled.
  • If gnu_extensions==False then a valid input will be gnuXXX or XXX.
    - The gnu_extensions won't have any effect on Windows.
  • If you specify tools.check_min_cppstd(self, cppstd=14, gnu_extensions=True) an input of compiler.cppstd==14, compiler.cppstd==17 or compiler.cppstd==20 will raise, it is needed gnu14 or gnu17 or gnu20.

EDIT:

Add also tools.valid_min_cppstd() that will do the same but returning a boolean instead of raising.

EDIT:

The gnu_extensions=True won't check the OSS. It is tricky to do it automatically since you can cross build to Arduino or any other embeeded where it could makes sense but it is not linux.

Add also tools.valid_min_cppstd() that will do the same but returning a boolean instead of raising.

I liked it!

Was this page helpful?
0 / 5 - 0 ratings