conan-io / conan

Conan - The open-source C and C++ package manager
https://conan.io
MIT License
7.96k stars 952 forks source link

[question] How do I test for operating system with Conan 2 API? #16445

Closed PauloCarvalhoRJ closed 3 weeks ago

PauloCarvalhoRJ commented 3 weeks ago

How do I test for operating system with Conan 2 API?

Hello,

So, I'm migrating lots of Conan 1.x recipes to Conan 2 and I have lots of code like this:

from conans.tools import os_info
...
 executable_name = executable_name + ("" if os_info.is_linux else ".exe")

I couldn't find a replacement in Conan 2 documentation here: https://docs.conan.io/2/reference nor the migration guide mentions anything directly like it: https://docs.conan.io/1/conan_v2.html . So, how do I query the operating system with Conan 2 API? I, however, found, by chance, a similar test here: https://docs.conan.io/1/migrating_to_2.0/recipes.html#settings . So, will something like this

     if self.settings.os == "Linux":
        ...

be exactly the same as:

     if os_info.is_linux:
        ...

? I ask this because I need self.settings.os to return "Linux" for all Linux distros and not "CentOS", "Fedora", "RedHat", "Debian", ... .

thank you,

PC

memsharded commented 3 weeks ago

Hi @PauloCarvalhoRJ

Thanks for your question.

if self.settings.os == "Linux":

Yes, this will return True for all Linux OSs, because this is the os=Linux that is defined in the profile file or in command line argument. This is irrespective of the current OS Conan is running, the Conan recipes must be as independent of the current system as possible. If in some case the current "build" settings are necessary, coming from the "build" profile (--profile:build or --settings:build), then recipes might access it too, but this is rarely needed and typically only for some packages like packages wrapping a compiler or a build tool.

Note also that no conditionals can be used in the source() method, as it should be independent of the inputs.

PauloCarvalhoRJ commented 3 weeks ago

Hello, @memsharded ,

Thanks for the answer. In the ideal world, I totally agree that a recipe should be OS-invariant. However, unfortunately, this is often not the case, especially when you are tasked with building legacy software which are even sensitive to Linux distro. By the way, following your rationale, can recipe code like

from conans.tools import OSInfo
...
info = OSInfo()
if info.is_linux and info.linux_distro in ("debian", "ubuntu"):
   ...

be replaced with

     if self.settings.distro in ("debian", "ubuntu"):
        ...

, provided I have distro=debian (or ubuntu) in the profile file set in the --profile:<profile_name> option?

thanks again,

PC

memsharded commented 3 weeks ago

Thanks for the answer. In the ideal world, I totally agree that a recipe should be OS-invariant

Not a recipe. Recipes have lots of things that are not invariant. It is only the source() method of the recipe that should be invariant.

if self.settings.distro in ("debian", "ubuntu"):

yes, definitely, a recipe can use this, as long as it defines the distro custom setting as first level setting. But this will typically not be the most recommended approach. The most correct approach in most cases is to add distro as a subsetting of os Linux setting, so the above would be more like:

if self.settings.os == "Linux" and str(self.settings.os.distro) in ("ubuntu", ...)

Note the str() to be able to do the in operator.

This can be perfectly use in many methods of the recipe, just not in the source() one.

PauloCarvalhoRJ commented 3 weeks ago

Thank you for the informative answers. That helped me a lot.

memsharded commented 3 weeks ago

Happy to help!