Skip to content

Commit

Permalink
options conflicts (#3643)
Browse files Browse the repository at this point in the history
  • Loading branch information
memsharded authored Mar 20, 2024
1 parent dde1e3d commit 530b0e7
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 0 deletions.
50 changes: 50 additions & 0 deletions knowledge/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,53 @@ Conan will not normalize or change in any way the source files, it is not its re
crlf = false
Other approach would be to change the ``.gitconfig`` to change it globally. Modern editors (even Notepad) in Windows can perfectly work with files with ``LF``, it is no longer necessary to change the line endings.


.. _faq_different_options_values:


Defining options for dependencies in conanfile.py recipes doesn't work
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Conan expands the dependency graph depth-first, this is important to be able to implement many of the very special C/C++ propagation
logic (headers, static and shared libraries, applications, tool-requires, test-requires, conflicts, overrides, etc.).

This means that when a ``conanfile.py`` declares something like:

.. code-block:: python
class MyPkg(ConanFile):
name = "mypkg"
version = "0.1"
default_options = {"zlib/*:shared": True}
# Or
def requirements(self):
self.requires("zlib/1.3", options={"shared": True})
it cannot be always honored, and the ``zlib`` dependency might end with different ``shared=False`` option value.
This in-recipe options values definition for dependencies only works if:

- There are no other packages depending on ``zlib`` in the graph
- There are other packages depending on ``zlib`` in the graph, but ``mypkg/0.1`` is the first require (the first branch
in the dependency graph) that is required. That means that ``requires = "mypkg/0.1", "zlib/1.3"`` will work and will have
``zlib`` as shared, but ``requires = "zlib/1.3", "mypkg/0.1"`` will expand first ``zlib`` with its default, which is
``shared=False`` and when the ``mypkg/0.1`` is computed it will be too late to change ``zlib`` to be ``shared=True``.

In case there are some recipe that won't work at all with some option of the dependency, the recommendation is to define
a ``validate()`` method in the recipe to guarantee that it will raise an error if for some reason the upstream dependency
doesn't have the right options values.

Conan might be able to show some (not guaranteed to be exhaustive) of these issues in the output of the Conan commands,
please read it carefully.


.. code-block::
Options conflicts
liba/0.1:myoption=1 (current value)
libc/0.1->myoption=2
It is recommended to define options values in profiles, not in recipes
In general, it is more recommended to define options values in profile files, not in recipes.
Recipe defined options always have precedence over options defined in profiles.
1 change: 1 addition & 0 deletions reference/binary_model/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ They are also the recommended default to represent when a library is shared, sta

- :ref:`documentation for options<conan_conanfile_properties_options>`
- :ref:`documentation for default_options<conan_conanfile_properties_default_options>`.
- :ref:`Defining options for dependencies in recipes does not have strong guarantees<faq_different_options_values>`


Settings vs options vs conf
Expand Down
6 changes: 6 additions & 0 deletions reference/conanfile/attributes/binary_model.inc
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ This attribute should be defined as a python dictionary.
You can also assign default values for options of your requirements using "<reference_pattern>: option_name", being
a valid ``reference_pattern`` a ``name/version`` or any pattern with ``*`` like the example above.
.. warning::
Defining options values in recipes does not have strong guarantees, please check
:ref:`this FAQ about options values for dependencies<faq_different_options_values>`. The recommended way
to define options values is in profile files.
You can also set the options conditionally to a final value with ``configure()`` instead of using ``default_options``:
.. code-block:: python
Expand Down
16 changes: 16 additions & 0 deletions reference/conanfile/methods/requirements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,22 @@ direct
If the dependency is a direct one, that is, it has explicitly been declared by the current
recipe, or if it is a transitive one.

options
~~~~~~~

It is possible to define options values for dependencies as a trait:

.. code-block:: python
self.requires("mydep/0.1", options={"dep_option": "value"})
.. warning::

Defining options values in recipes does not have strong guarantees, please check
:ref:`this FAQ about options values for dependencies<faq_different_options_values>`. The recommended way
to define options values is in profile files.


.. _reference_conanfile_package_type_trait_inferring:

Expand Down
7 changes: 7 additions & 0 deletions tutorial/versioning/conflicts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,13 @@ define that it should be a static library (not really necessary, because that is
# Not strictly necessary because this is already the matrix default
default_options = {"matrix*:shared": False}
.. warning::

Defining options values in recipes does not have strong guarantees, please check
:ref:`this FAQ about options values for dependencies<faq_different_options_values>`. The recommended way
to define options values is in profile files.

And also ``intro`` recipe would do the same, but instead define that it wants a shared library, and adds a
``validate()`` method, because for some reason the ``intro`` package can only be built against shared libraries
and otherwise crashes:
Expand Down

0 comments on commit 530b0e7

Please sign in to comment.