diff --git a/knowledge/faq.rst b/knowledge/faq.rst index c702fc93c3ad..57d2741226d3 100644 --- a/knowledge/faq.rst +++ b/knowledge/faq.rst @@ -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. diff --git a/reference/binary_model/extending.rst b/reference/binary_model/extending.rst index 789faece74a8..0bf634a1cceb 100644 --- a/reference/binary_model/extending.rst +++ b/reference/binary_model/extending.rst @@ -57,6 +57,7 @@ They are also the recommended default to represent when a library is shared, sta - :ref:`documentation for options` - :ref:`documentation for default_options`. + - :ref:`Defining options for dependencies in recipes does not have strong guarantees` Settings vs options vs conf diff --git a/reference/conanfile/attributes/binary_model.inc b/reference/conanfile/attributes/binary_model.inc index 9c5fe83bb721..bdcfd937ed8d 100644 --- a/reference/conanfile/attributes/binary_model.inc +++ b/reference/conanfile/attributes/binary_model.inc @@ -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 ": 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`. 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 diff --git a/reference/conanfile/methods/requirements.rst b/reference/conanfile/methods/requirements.rst index ceb20630ac53..bbcbd1a3cde3 100644 --- a/reference/conanfile/methods/requirements.rst +++ b/reference/conanfile/methods/requirements.rst @@ -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`. The recommended way + to define options values is in profile files. + .. _reference_conanfile_package_type_trait_inferring: diff --git a/tutorial/versioning/conflicts.rst b/tutorial/versioning/conflicts.rst index 709dd6b3f2c2..68bc3b7646b2 100644 --- a/tutorial/versioning/conflicts.rst +++ b/tutorial/versioning/conflicts.rst @@ -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`. 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: