Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validate docs #1947

Merged
merged 1 commit into from Dec 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions mastering/conditional.rst
Expand Up @@ -83,6 +83,11 @@ There are two approaches for this situation:
if self.settings.os == "Windows":
del self.options.fPIC

.. note::

For managing invalid configurations, please check the new experimental ``validate()`` method (:ref:`method_validate`).


- **Constrain settings inside a recipe**:

This approach constrains the settings inside a recipe to a subset of them, and it is normally used in recipes that are never supposed to
Expand Down
104 changes: 102 additions & 2 deletions reference/conanfile/methods.rst
Expand Up @@ -286,9 +286,9 @@ The :ref:`cpp_info_attributes_reference` attribute has the following properties
package may have: libraries, executables... Read more about this feature at :ref:`package_information_components`.
- **requires**: **[Experimental]** List of components from the requirements this package (and its consumers) should link with. It will
be used by generators that add support for components features (:ref:`package_information_components`).


If your recipe has requirements, you can access to the information stored in the ``cpp_info`` of your requirements

If your recipe has requirements, you can access to the information stored in the ``cpp_info`` of your requirements
using the ``deps_cpp_info`` object:

.. code-block:: python
Expand Down Expand Up @@ -519,6 +519,106 @@ it is an example of a recipe for a library that doesn't support Windows operatin

This exception will be propagated and Conan application will finish with a :ref:`special return code <invalid_configuration_return_code>`.

.. note::

For managing invalid configurations, please check the new experimental ``validate()`` method (:ref:`method_validate`).


.. _method_validate:

validate()
----------

.. warning::

This is an **experimental** feature subject to breaking changes in future releases.

The ``validate()`` method can be used to mark a binary as "impossible" or invalid for a given configuration. For example,
if a given library does not build or work at all in Windows it can be defined as:

.. code-block:: python

from conans import ConanFile
from conans.errors import ConanInvalidConfiguration

class Pkg(ConanFile):
settings = "os"

def validate(self):
if self.settings.os == "Windows":
raise ConanInvalidConfiguration("Windows not supported")

If you try to use, consume or build such a package, it will raise an error, returning exit code :ref:`exit code <invalid_configuration_return_code>`:

.. code-block:: bash

$ conan create . pkg/0.1@ -s os=Windows
...
Packages
pkg/0.1:INVALID - Invalid
...
> ERROR: There are invalid packages (packages that cannot exist for this configuration):
> pkg/0.1: Invalid ID: Windows not supported

A major difference with ``configure()`` is that this information can be queried with the ``conan info`` command, for example this
is possible without getting an error:

.. code-block:: bash

$ conan export . test/0.1@user/testing
...
> test/0.1@user/testing: Exported revision: ...

$ conan info test/0.1@user/testing
>test/0.1@user/testing
ID: INVALID
BuildID: None
Remote: None
...

Another important difference with the ``configure()`` method, is that ``validate()`` is evaluated after the graph has been computed and
the information has been propagated downstream. So the values used in ``validate()`` are guaranteed to be final real values,
while values at ``configure()`` time are not. This might be important, for example when checking values of options of dependencies:

.. code-block:: python

from conans import ConanFile
from conans.errors import ConanInvalidConfiguration

class Pkg(ConanFile):
requires = "dep/0.1"

def validate(self):
if self.options["dep"].myoption == 2:
raise ConanInvalidConfiguration("Option 2 of 'dep' not supported")


If a package uses ``compatible_packages`` feature, it should not add to those compatible packages configurations that will not be valid,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this section, I think it is more important to show how a compatible package (a valid one) will be used to substitute an invalid package. Something with the compiler.cppstd is very evident: the package is invalid (will fail with conan create) if using C++11, but a conan install will use a compatible one that was built using C++14,17,20.

These comments about what packages to add to self.compatible_packages belong to the documentation of the compatible_packages feature.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is also a valid use case, in which you can fallback to release artifacts in Linux if you don't have the debug one, which usually works in non-windows platforms. I am not sure if I understand the issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not an issue, I think that the other use case is much more interesting regarding validate + compatible-packages. Falling back to Release builds I think it is more related to compatible-packages than validate, and this is the documentation for the validate function. One example is enough, the other is better IMO.

for example:

.. code-block:: python

from conans import ConanFile
from conans.errors import ConanInvalidConfiguration

class Pkg(ConanFile):
settings = "os", "build_type"

def validate(self):
if self.settings.os == "Windows":
raise ConanInvalidConfiguration("Windows not supported")

def package_id(self):
if self.settings.build_type == "Debug" and self.settings.os != "Windows":
compatible_pkg = self.info.clone()
compatible_pkg.settings.build_type = "Release"
self.compatible_packages.append(compatible_pkg)

Note the ``self.settings.os != "Windows"`` in the ``package_id()``. If this is not provided, the ``validate()`` might still work and
raise an error, but in the best case it will be wasted resources (compatible packages do more API calls to check them), so it is
strongly recommended to properly define the ``package_id()`` method to no include incompatible configurations.


.. _method_requirements:

requirements()
Expand Down