diff --git a/reference/conanfile/methods/build.rst b/reference/conanfile/methods/build.rst index b93df91daabe..c54a850c19c1 100644 --- a/reference/conanfile/methods/build.rst +++ b/reference/conanfile/methods/build.rst @@ -3,7 +3,7 @@ build() ======= -The ``build()`` method is used to define the build from source of the package. In practice this means calling some build system, which could be done explictly or using any of the build helpers provided by Conan: +The ``build()`` method is used to define the build from source of the package. In practice this means calling some build system, which could be done explicitly or using any of the build helpers provided by Conan: .. code-block:: python @@ -27,17 +27,16 @@ The ``build()`` method is used to define the build from source of the package. I For more information about the existing built-in build system integrations, visit :ref:`conan_tools`. The ``build()`` method should be as simple as possible, just wrapping the command line invocations -that a developer would do in the simplest possible way. The ``generate()`` method is the responsible -for preparing the build, creating toolchain file, CMake presets, or whatever other files are necessary -so developers can easily call the build system by hand easily. This way the integration with IDEs and -the developer experience is much better. The result is that the ``build()`` method should be relatively -simple in practice. +that a developer would do in the simplest possible way. The ``generate()`` method is the one responsible +for preparing the build, creating toolchain files, CMake presets, or any other files which are necessary +so developers could easily call the build system by hand. This allows for much better integrations with IDEs and +improves the developer experience. The result is that in practice the ``build()`` method should be relatively simple. The ``build()`` method is the right place to build and run unit tests, before packaging, and raising errors if those tests fail, interrupting the process, and not even packaging the final binaries. -The built-in helpers will skip the unit tests if ``tools.build:skip_test`` configuration is defined, for custom integrations, it is expected that the method checks this ``conf`` value in order to skip building and running tests, which can be useful for some CI scenarios. +The built-in helpers will skip the unit tests if the ``tools.build:skip_test`` configuration is defined. For custom integrations, it is expected that the method checks this ``conf`` value in order to skip building and running tests, which can be useful for some CI scenarios. -The ``build()`` method runs once per different configuration, so if there are some source operations like applying patches that are done conditionally to different configurations, they could be also applied in the -``build()`` method, before the actual build. It is important that in this case the ``no_copy_source`` attribute cannot be set to ``True``. +The ``build()`` method runs once per unique configuration, so if there are some source operations like applying patches that are done conditionally to different configurations, they could be also applied in the +``build()`` method, before the actual build. It is important to note that in this case the ``no_copy_source`` attribute cannot be set to ``True``. @@ -45,4 +44,4 @@ The ``build()`` method runs once per different configuration, so if there are so **Best practices** - - The ``build()`` should be as simple as possible, the heavy lifting of preparing the build should happen in the ``generate()`` method, in order to achieve a good developer experience that can easily build locally with just ``conan install .``, plus directly calling the build system or opening their IDE. \ No newline at end of file + - The ``build()`` method should be as simple as possible, the heavy lifting of preparing the build should happen in the ``generate()`` method in order to achieve a good developer experience that can easily build locally with just ``conan install .``, plus directly calling the build system or opening their IDE. \ No newline at end of file diff --git a/reference/conanfile/methods/build_id.rst b/reference/conanfile/methods/build_id.rst index af02c9abf594..6b103bf2a0db 100644 --- a/reference/conanfile/methods/build_id.rst +++ b/reference/conanfile/methods/build_id.rst @@ -4,15 +4,15 @@ build_id() ========== The ``build_id()`` method allows to re-use the same build to create different binary packages in the cache, -potentially saving build time as it can avoid some unnecessary re-builds. It is an optimization method. +potentially saving build time as it can avoid some unnecessary re-builds. It is therefore an optimization method. In the general case, there is one build folder for each binary package, with the exact same ``package_id`` of the package. However this behavior can be changed, there are a couple of scenarios that this might be useful: -- The package build scripts generates several different configurations at once (like both debug and release artifacts) in the same run, without the possibility of building each configuration separately. +- The package build scripts generate several different configurations at once (like both debug and release artifacts) in the same run, without the possibility of building each configuration separately. - The package build scripts generate one binary configuration, but different artifacts that can be packaged separately. For example if there are some test executables, you might want to create two packages: one just containing the library for general usage, and another one also containing the tests (for compliance, later reproducibility, debugging, etc). -In the first case, we could write for example: +In the first case, we could for example write: .. code-block:: python @@ -34,7 +34,7 @@ Other information like custom package options can also be changed: self.info_build.options.myoption = 'MyValue' # any value possible self.info_build.options.fullsource = 'Always' -If the ``build_id()`` method does not modify the ``info_build`` data, and produce a different one than +If the ``build_id()`` method does not modify the ``info_build`` data, and it still produces a different id than the ``package_id``, then the standard behavior will be applied. Consider the following: .. code-block:: python @@ -45,7 +45,7 @@ the ``package_id``, then the standard behavior will be applied. Consider the fol if self.settings.os == "Windows": self.info_build.settings.build_type = "Any" -This will only produce a ``build_id`` different if the package is for Windows, running ``build()`` just +This will only produce a different ``build_id`` if the package is for Windows, thus running ``build()`` just once for all ``build_type`` values. The behavior in any other OS will be the standard one, as if the ``build_id()`` method was not defined, running one different ``build()`` for each ``build_type``. @@ -55,4 +55,4 @@ one different ``build()`` for each ``build_type``. **Best practices** - Conan strong recommendation is to use one package binary with its own ``package_id`` for each different configuration. The ``build_id()`` goal is to deal with legacy build scripts that cannot easily be changed to do the build of one configuration each time. + Conan strongly recommends to use one package binary with its own ``package_id`` for each different configuration. The goal of the ``build_id()`` method is to deal with legacy build scripts that cannot easily be changed to do the build of one configuration each time. diff --git a/reference/conanfile/methods/build_requirements.rst b/reference/conanfile/methods/build_requirements.rst index f39354b7695f..dba33accc200 100644 --- a/reference/conanfile/methods/build_requirements.rst +++ b/reference/conanfile/methods/build_requirements.rst @@ -3,7 +3,7 @@ build_requirements() ==================== -The ``build_requirements()`` method is functionally equivalent to the ``requirements()`` one, it is executed just after it. It is not strictly necessary, in theory everything that is inside this method, could be done in the end of the ``requirements()`` one. Still, the ``build_requirements()`` is good for having a dedicated place to define ``tool_requires`` and ``test_requires``: +The ``build_requirements()`` method is functionally equivalent to the ``requirements()`` one, it is executed just after it. It is not strictly necessary, in theory everything that is inside this method, could be done in the end of the ``requirements()`` one. Still, ``build_requirements()`` is good for having a dedicated place to define ``tool_requires`` and ``test_requires``: .. code-block:: python @@ -14,7 +14,7 @@ The ``build_requirements()`` method is functionally equivalent to the ``requirem For simple cases the attribute syntax can be enough, like ``tool_requires = "cmake/3.23.5"`` and ``test_requires = "gtest/1.13.0"``. The method form can be necessary for conditional or parameterized requirements. -The ``tool_requires`` and ``test_requires`` are just a specialized instance of ``requires`` with some predefined trait values. See the :ref:`requires() reference` for more information. +The ``tool_requires`` and ``test_requires`` methods are just a specialized instance of ``requires`` with some predefined trait values. See the :ref:`requires() reference` for more information about traits. tool_requires ------------- @@ -22,7 +22,7 @@ tool_requires The ``tool_requires`` is equivalent to ``requires()`` with the following traits: - ``build=True``. This dependency is in the "build" context, being necessary at build time, but not at application runtime, and will receive the "build" profile and configuration. -- ``visible=False``. The dependency to a tool requirement is not propagated downstream. For example, one package can ``tool_requires("cmake/3.23.5")``, but that doesn't mean that consumer packages also use ``cmake``, they could even use a different build system, or a different version, without causing conflicts. +- ``visible=False``. The dependency to a tool requirement is not propagated downstream. For example, one package can call ``tool_requires("cmake/3.23.5")``, but that doesn't mean that the consumer packages also use ``cmake``, they could even use a different build system, or a different version, without causing conflicts. - ``run=True``. This dependency has some executables or runtime that needs to be ran at build time. - ``headers=False`` A tool requirement does not have headers. - ``libs=False``: A tool requirement does not have libraries to be linked by the consumer (if it had libraries they would be in the "build" context and could be incompatible with the "host" context of the consumer package). @@ -33,7 +33,7 @@ test_requires The ``test_requires`` is equivalent to ``requires()`` with the following traits: - ``test=True``. This dependency is a "test" dependency, existing in the "host" context, but not aiming to be part of the final product. -- ``visible=False``. The dependency to a test requirement is not propagated downstream. For example, one package can ``self.test_requires("gtest/1.13.0")``, but that doesn't mean that consumer packages also use ``gtest``, they could even use a different test framework, or the same ``gtest`` with a different version, without causing conflicts. +- ``visible=False``. The dependency to a test requirement is not propagated downstream. For example, one package can call ``self.test_requires("gtest/1.13.0")``, but that doesn't mean that the consumer packages also use ``gtest``, they could even use a different test framework, or the same ``gtest`` with a different version, without causing conflicts. It is possible to further modify individual traits of ``tool_requires()`` and ``test_requires()`` if necessary, for example: @@ -48,5 +48,5 @@ It is possible to further modify individual traits of ``tool_requires()`` and `` **Best practices** - - ``tool_requires`` are exclusively for build time **tools**, not for libraries that would be included and linked into the consumer package. For libraries with some special characteristics, using a ``requires()`` with custom trait values. - - The ``self.test_requires()`` and ``self.tool_requires`` should exclusively be used in this ``build_requirements()`` method, with the only possible exception of the ``requirements()`` method. Using them in any other method is forbidden. To access dependencies information when necessary in some methods, the ``self.dependencies`` should be used. + - ``tool_requires`` are exclusively for build time **tools**, not for libraries that would be included and linked into the consumer package. For libraries with some special characteristics, use a ``requires()`` with custom trait values. + - The ``self.test_requires()`` and ``self.tool_requires()`` methods should exclusively be used in the ``build_requirements()`` method, with the only possible exception being the ``requirements()`` method. Using them in any other method is forbidden. To access information about dependencies when necessary in some methods, the :ref:`self.dependencies` attribute should be used. diff --git a/reference/conanfile/methods/compatibility.rst b/reference/conanfile/methods/compatibility.rst index 3662001c5300..97115c2685dd 100644 --- a/reference/conanfile/methods/compatibility.rst +++ b/reference/conanfile/methods/compatibility.rst @@ -14,13 +14,13 @@ level. In general, the global compatibility plugin should be good for most cases require the recipe method for exceptional cases. This method can be used in a *conanfile.py* to define packages that are compatible between -each other. If there are no binaries available for the requested settings and options -this mechanism will retrieve the compatible package's binaries if they exist. The method +each other. If there are no binaries available for the requested settings and options, +this mechanism will retrieve the compatible package's binaries if they exist. This method should return a list of compatible configurations. For example, if we want that binaries -built with gcc versions 4.8, 4.7 and 4.6 are considered compatible with the ones compiled -with 4.9 we could declare the ``compatibility()`` like this: +built with gcc versions 4.8, 4.7 and 4.6 to be considered compatible with the ones compiled +with 4.9 we could declare a ``compatibility()`` method like this: .. code-block:: python diff --git a/reference/conanfile/methods/config_options.rst b/reference/conanfile/methods/config_options.rst index 58705ae1b6c5..a0408eb05636 100644 --- a/reference/conanfile/methods/config_options.rst +++ b/reference/conanfile/methods/config_options.rst @@ -5,7 +5,7 @@ config_options() The ``config_options()`` method is used to configure or constraint the available options in a package, **before** they are given a value. A typical use case is to remove an option in a given platform. For example, -the ``fPIC`` flag doesn't exist in Windows, so it should be done: +the ``fPIC`` flag doesn't exist in Windows, so it should be removed in this method like so: .. code-block:: python @@ -13,4 +13,4 @@ the ``fPIC`` flag doesn't exist in Windows, so it should be done: if self.settings.os == "Windows": del self.options.fPIC -The ``config_options()`` executes before ``configure()`` method, and before the actual assignment of ``options`` values, but settings are already defined. +The ``config_options()`` method executes before the ``configure()`` method, and before the actual assignment of the ``options`` values, but after settings are already defined. diff --git a/reference/conanfile/methods/configure.rst b/reference/conanfile/methods/configure.rst index d44872e4d8ac..d10554c5a00b 100644 --- a/reference/conanfile/methods/configure.rst +++ b/reference/conanfile/methods/configure.rst @@ -3,13 +3,13 @@ configure() =========== -The ``configure()`` method should be used for configuration of settings and options in the recipe +The ``configure()`` method should be used for the configuration of settings and options in the recipe for later use in the different methods like ``generate()``, ``build()`` or ``package()``. This -method executes while building the dependency graph and expanding the packages dependencies, that means +method executes while building the dependency graph and expanding the packages dependencies, which means that when this method executes the dependencies are still not there, they do not exist, and it is not possible to access ``self.dependencies``. -For example, for a C (not C++) library, the ``compiler.libcxx`` and ``compiler.cppstd`` shouldn't +For example, for a C (not C++) library, the ``compiler.libcxx`` and ``compiler.cppstd`` settings shouldn't even exist during the ``build()``. It is not only that they are not part of the ``package_id``, but they shouldn't be used in the build process at all. They will be defined in the profile, because other packages in the graph can be C++ packages and need them, but it is the responsibility of this @@ -43,7 +43,7 @@ so it should be removed: del self.options.fPIC -Recipes can suggest dependencies option values as ``default_options = {"*:shared": True}``, but +Recipes can suggest values for their dependencies options as ``default_options = {"*:shared": True}``, but it is not possible to do that conditionally. For this purpose, it is also possible to use the ``configure()`` method: @@ -58,5 +58,5 @@ it is not possible to do that conditionally. For this purpose, it is also possib **Best practices** - - Recall it is **not** possible to define ``settings`` or ``conf`` values in recipes, they are read only. - - The definition of ``options`` values is only a "suggestion", but not always defining the value, depending on the graph computation, priorities, etc., the final value of ``options`` can be different. + - Recall that it is **not** possible to define ``settings`` or ``conf`` values in recipes, they are read only. + - The definition of ``options`` values is only a "suggestion", depending on the graph computation, priorities, etc., the final value of ``options`` can be different than the one set by the recipe. diff --git a/reference/conanfile/methods/export.rst b/reference/conanfile/methods/export.rst index 42cd1d148501..7072cb569e58 100644 --- a/reference/conanfile/methods/export.rst +++ b/reference/conanfile/methods/export.rst @@ -4,8 +4,8 @@ export() ======== Equivalent to the ``exports`` attribute, but in method form. This method will be called at ``export`` time, -which happens in ``conan export`` and ``conan create`` commands, and it is intended to allow copying files from the -user folder to the Conan cache folders, those files becoming part of the recipe. These sources will +which happens in the ``conan export`` and ``conan create`` commands, and it is intended to allow copying files from the +user folder to the Conan cache folders, thus making files becoming part of the recipe. These sources will be uploaded to the servers together with the recipe, but are typically not downloaded unless the package is being built from source. @@ -25,13 +25,13 @@ as the destination folder for using ``copy()`` or your custom copy. copy(self, "LICENSE.md", self.recipe_folder, self.export_folder) -There are 2 files that are always exported to the cache, without being explicitly defined in the recipe: the ``conanfile.py`` recipe, and the ``conandata.yml`` file if it exists. The ``conandata.yml`` file is automatically loaded whenever the ``conanfile.py`` is loaded, becoming the ``self.conan_data`` attribute, so it is intrinsic part of the recipe, so it is part of the "exported" recipe files, not of the "exported" source files. +There are 2 files that are always exported to the cache, without being explicitly defined in the recipe: the ``conanfile.py`` recipe, and the ``conandata.yml`` file if it exists. The ``conandata.yml`` file is automatically loaded whenever the ``conanfile.py`` is loaded, becoming the ``self.conan_data`` attribute, so it is a intrinsic part of the recipe, so it is part of the "exported" recipe files, not of the "exported" source files. .. note:: **Best practices** - - The recipe files must be configuration independent. Those files are common for all configurations, then, it is not possible to do conditional ``export()`` to different settings, options, or platforms. Do not try to do any kind of conditional export. If necessary export all the files necessary for all configurations at once. - - The exported files must be small. Exporting with the recipe big files will make much slower the resolution of dependencies. - - Only files that are necessary for the evaluation of the ``conanfile.py`` recipe must be exported with this method. Files necessary for building from sources should be exported with ``exports_sources`` attribute or ``export_source()`` method. + - The recipe files must be configuration independent. Those files are common for all configurations, thus it is not possible to do conditional ``export()`` to different settings, options, or platforms. Do not try to do any kind of conditional export. If necessary export all the files necessary for all configurations at once. + - The exported files must be small. Exporting big files with the recipe will make the resolution of dependencies much slower the resolution. + - Only files that are necessary for the evaluation of the ``conanfile.py`` recipe must be exported with this method. Files necessary for building from sources should be exported with the ``exports_sources`` attribute or the :ref:`export_source()` method. diff --git a/reference/conanfile/methods/export_sources.rst b/reference/conanfile/methods/export_sources.rst index d2a9884dfef9..5f4118d83483 100644 --- a/reference/conanfile/methods/export_sources.rst +++ b/reference/conanfile/methods/export_sources.rst @@ -40,7 +40,7 @@ The method might be able to read files in the recipe folder and do something wit The ``export_conandata_patches()`` is a high-level helper function that does the export of the patches defined -in the ``conandata.yml`` file, that could be later applied in ``apply_conandata_patches()`` in the ``source()`` method. +in the ``conandata.yml`` file, which could be later applied with ``apply_conandata_patches()`` in the ``source()`` method. .. code-block:: python @@ -57,6 +57,6 @@ in the ``conandata.yml`` file, that could be later applied in ``apply_conandata_ **Best practices** The recipe sources must be configuration independent. Those sources are common for all configurations, - then, it is not possible to do conditional ``export_sources()`` to different settings, options, or + thus it is not possible to do conditional ``export_sources()`` to different settings, options, or platforms. Do not try to do any kind of conditional export. If necessary export all the files necessary for all configurations at once. diff --git a/reference/conanfile/methods/generate.rst b/reference/conanfile/methods/generate.rst index d7d8c385deb6..06340446944e 100644 --- a/reference/conanfile/methods/generate.rst +++ b/reference/conanfile/methods/generate.rst @@ -21,10 +21,10 @@ The purpose of ``generate()`` is to prepare the build, generating the necessary The idea is that the ``generate()`` method implements all the necessary logic, making both the user manual builds after a :command:`conan install` -very straightforward, and also the ``build()`` method logic simpler. The build produced by a user in their local flow should result +very straightforward, and also the ``build()`` method logic simpler. The build produced by a user in their local flow should result in exactly the same one as the build done in the cache with a ``conan create`` without effort. -Generation of files happen in the ``generators_folder`` as defined by the current layout. +Generation of files happens in the ``generators_folder`` as defined by the current layout. In many cases, the ``generate()`` method might not be necessary, and declaring the ``generators`` attribute could be enough: @@ -74,7 +74,7 @@ multiple recipes: mygen.generate() -In case it is necessary to collect or copy some file from the dependencies, it is also possible to do it in the ``generate()`` method, accessing ``self.dependencies``. +In case it is necessary to collect or copy some files from the dependencies, it is also possible to do it in the ``generate()`` method, accessing ``self.dependencies``. Listing the different include directories, lib directories from a dependency "mydep" would be possible like this: .. code:: python diff --git a/reference/conanfile/methods/init.rst b/reference/conanfile/methods/init.rst index 981705b2f980..aa958d805132 100644 --- a/reference/conanfile/methods/init.rst +++ b/reference/conanfile/methods/init.rst @@ -45,7 +45,7 @@ The final ``Pkg`` conanfile will have both ``os`` and ``arch`` as settings, and This method can also be useful if you need to unconditionally initialize class attributes like ``license`` or ``description`` or any other from datafiles other than -`conandata.yml`. For example, you have a `json` file containing the information about the +`conandata.yml`. For example, you can have a `json` file containing the information about the ``license``, ``description`` and ``author`` for the library: @@ -79,6 +79,6 @@ Then, you can load that information from the ``init()`` method: **Best practices** - - Try to keep your ``python_requires`` as simple as possible, and do not reuse attributes from them (the main need for the ``init()`` method), trying to avoid the complexity of this ``init()`` method. In general inheritance can have more issues than composition (or "use composition over inheritance" general programming good practice), so try to avoid it if possible. - - Do not abuse ``init()`` for other purposes other than listed here, neither use the Python private ``ConanFile.__init__`` constructor. + - Try to keep your ``python_requires`` as simple as possible, and do not reuse attributes from them (the main need for the ``init()`` method), trying to avoid the complexity of this ``init()`` method. In general inheritance can have more issues than composition (or in other words "use composition over inheritance" as a general programming good practice), so try to avoid it if possible. + - Do not abuse ``init()`` for other purposes other than listed here, nor use the Python private ``ConanFile.__init__`` constructor. - The ``init()`` method executes at recipe load time. It cannot contain conditionals on settings, options, conf, or use any dependencies information other than the above ``python_requires``. diff --git a/reference/conanfile/methods/package.rst b/reference/conanfile/methods/package.rst index bb27f564af01..bab50005e294 100644 --- a/reference/conanfile/methods/package.rst +++ b/reference/conanfile/methods/package.rst @@ -32,7 +32,7 @@ The second way is to use the ``install`` functionality of some build systems, pr Also, it is possible to combine both approaches, doing ``cmake.install()`` and also adding some ``copy()`` calls, for example to make sure some "License.txt" file is packaged that was not taken into account by the CMakeLists.txt script. -It is also possible, to use conditionals in the ``package()`` method, +It is also possible to use conditionals in the ``package()`` method, because different platforms might have different artifacts in different locations: .. code-block:: python @@ -44,9 +44,9 @@ because different platforms might have different artifacts in different location else: copy(self, "*.lib", src=os.path.join(self.build_folder, "build", "libs"), ...) -Though in most situations it might not be necessary, because pattern based copy will not likely find wrong artifacts like ``*.dll`` in a non-Windows build. +Though in most situations it might not be necessary, because pattern based copy will likely not find wrong artifacts like ``*.dll`` in a non-Windows build. -The ``package()`` method is also the one called when packaging precompiled binaries with ``conan export-pkg``. In this case the ``self.source_folder`` and ``self.build_folder`` refer to user space folders, as defined by the ``layout()`` and the only folder in the Conan cache will be ``self.package_folder``. +The ``package()`` method is also the one called when packaging precompiled binaries with ``conan export-pkg``. In this case the ``self.source_folder`` and ``self.build_folder`` refer to user space folders, as defined by the ``layout()`` method and the only folder in the Conan cache will be ``self.package_folder``. .. note:: diff --git a/reference/conanfile/methods/package_id.rst b/reference/conanfile/methods/package_id.rst index 1a97f351c6d8..79b0386f7201 100644 --- a/reference/conanfile/methods/package_id.rst +++ b/reference/conanfile/methods/package_id.rst @@ -4,19 +4,19 @@ package_id() ============ Conan computes a unique ``package_id`` reference for each configuration, including ``settings``, ``options`` and ``dependencies`` versions. -This ``package_id()`` method allows some customizations and changes over the computed ``package_id``, in general with the goal of relax some of the global binary compatibility assumptions. +This ``package_id()`` method allows some customizations and changes over the computed ``package_id``, in general with the goal to relax some of the global binary compatibility assumptions. -The general rule is that every different value of ``settings``, ``options`` create a different ``package_id``. This rule can be relaxed or expanded following different approaches: +The general rule is that every different value of ``settings`` and ``options`` creates a different ``package_id``. This rule can be relaxed or expanded following different approaches: -- A given package recipe can decide in its ``package_id()`` that the final binary is independent of some settings, for example if it is a header-only library, that used input settings to build some tests, it might completely clear all configuration, so the resulting ``package_id`` is always the same irrespective of the inputs. Likewise a C library might want to remove the effect of ``compiler.cppstd`` and/or ``compiler.libcxx`` from its binary ``package_id``, because as a C library, its binary will be independent. -- A given package recipe can implement some partial erasure of information, for example to obtain the same ``package_id`` for a range of compiler versions. This type of binary compatibility it is in general better addressed with the global ``compatibility`` plugin, or with the ``compatibility()`` method if the global plugin is not enough. +- A given package recipe can decide in its ``package_id()`` that the final binary is independent of some settings, for example if it is a header-only library, that uses input settings to build some tests, it might completely clear all configuration, so the resulting ``package_id`` is always the same irrespective of the inputs. Likewise a C library might want to remove the effect of ``compiler.cppstd`` and/or ``compiler.libcxx`` from its binary ``package_id``, because as a C library, its binary will be independent. +- A given package recipe can implement some partial erasure of information, for example to obtain the same ``package_id`` for a range of compiler versions. This type of binary compatibility is in general better addressed with the global ``compatibility`` plugin, or with the ``compatibility()`` method if the global plugin is not enough. - A package recipe can decide to inject extra variability in its computed ``package_id``, adding ``conf`` items or "target" settings. Information erasure ------------------- -This is a ``package_id`` relaxing strategy. Let's check the first case: a header-only library, that has input ``settings``, because it still want to use them for some unit-tests in its ``build()`` method. In order to have exactly one final binary for all configurations, because the final artifact should be identical in all cases, just the header files, it would be necessary to do: +This is a ``package_id`` relaxing strategy. Let's check the first case: a header-only library, that has input ``settings``, because it still wants to use them for some unit-tests in its ``build()`` method. In order to have exactly one final binary for all configurations, because the final artifact should be identical in all cases (just the header files), it would be necessary to do: .. code-block:: python @@ -28,17 +28,17 @@ This is a ``package_id`` relaxing strategy. Let's check the first case: a header cmake.test() # running unit tests for the current configuration def package_id(self): - # Completely clear all the ``package_id`` information ("info" object) + # Completely clear all the settings from the ``package_id`` information ("info" object) # All resulting ``package_id`` will be the same, irrespective of configuration self.info.settings.clear() .. warning:: - The modifications of the information happens always over the ``self.info`` object, not on ``self.settings`` or ``self.options`` + The modifications of the information always happen over the ``self.info`` object, not on ``self.settings`` or ``self.options`` -If a package is just a C library, but it couldn't remove the ``compiler.cppstd`` and ``compiler.libcxx`` in the ``configure()`` method (the recommended approach for most cases, to guarantee those flags are not used in the build), because there are C++ unit tests to the C library, then, those could be removed with (as the tests are not packaged and the final binary will be independent of C++): +If a package is just a C library, but it couldn't remove the ``compiler.cppstd`` and ``compiler.libcxx`` in the ``configure()`` method (the recommended approach for most cases, to guarantee those flags are not used in the build), because there are C++ unit tests to the C library, then as the tests are not packaged and the final binary will be independent of C++, those could be removed with: .. code-block:: python @@ -65,7 +65,7 @@ If a package is building an executable to be used as a tool, and only 1 executab del self.info.settings.compiler del self.info.settings.build_type -Note that this doesn't mean that the ``compiler`` and ``build_type`` should be removed for every application executable. For other things that tools, but final products to release, the most common situation is that maintaining the different builds for the different compilers, compiler versons, build types, etc. is the best approach. +Note that this doesn't mean that the ``compiler`` and ``build_type`` should be removed for every application executable. For other things that are not tools, but final products to release, the most common situation is that maintaining the different builds for the different compilers, compiler versions, build types, etc. is the best approach. It also means that we are erasing some information. We will not have the information of the compiler and build type that was used for the binary that we are using (it will not be in the ``conan list`` output, and it will not be in the server metadata either). If we compile a new binary with a different compiler or build type, it will create a new package revision under the same ``package_id``. @@ -92,7 +92,7 @@ Adding information ------------------ There is some information not added by default to the ``package_id``. -If we are creating a package for a tool, to be used as a ``tool_require``, and it happens that such package binary will be different for each "target" configuration, like it is the case for some cross-compiler, if the compiler itself might be different for the different architectures that it is targeting, it will be necessary to add the ``settings_target`` to the ``package_id`` with: +If we are creating a package for a tool, to be used as a ``tool_require``, and it happens that such package binary will be different for each "target" configuration, like it is the case for some cross-compilers, if the compiler itself might be different for the different architectures that it is targeting, it will be necessary to add the ``settings_target`` to the ``package_id`` with: .. code-block:: python @@ -100,7 +100,7 @@ If we are creating a package for a tool, to be used as a ``tool_require``, and i self.info.settings_target = self.settings_target -The ``conf`` items do not affect by default the ``package_id``. It is possible to explicitly make them part of it at the recipe level with: +The ``conf`` items do not affect the ``package_id`` by default. It is possible to explicitly make them part of it at the recipe level with: .. code-block:: python diff --git a/reference/conanfile/methods/package_info.rst b/reference/conanfile/methods/package_info.rst index 006854676f6d..1fb8a0b67e1d 100644 --- a/reference/conanfile/methods/package_info.rst +++ b/reference/conanfile/methods/package_info.rst @@ -4,7 +4,7 @@ package_info() ============== The ``package_info()`` method is the one responsible of defining the information to the consumers of the package, so those consumers can easily and automatically consume this package. -The ``generate()`` method of the consumers is the place where the information defined in the ``package_info()`` will be mapped to the specific build system of the consumer. Then, if we want a package to be consumed by different build systems (like it happens with ConanCenter recipes for the community), it is very important that this information is complete. This might require +The ``generate()`` method of the consumers is the place where the information defined in the ``package_info()`` will be mapped to the specific build system of the consumer. Then, if we want a package to be consumed by different build systems (like it happens with ConanCenter recipes for the community), it is very important that this information is complete. .. important:: @@ -57,14 +57,14 @@ Directories: initialized to ``['include']``, and it is rarely changed. - **libdirs**: List of relative paths (starting from the package root) of directories in which to find library object binaries (\*.lib, \*.a, \*.so, \*.dylib). By default it is initialized to ``['lib']``, and it is rarely changed. -- **bindirs**: List of relative paths (starting from the package root) of directories in which to find library runtime binaries (like exectuables +- **bindirs**: List of relative paths (starting from the package root) of directories in which to find library runtime binaries (like executable Windows .dlls). By default it is initialized to ``['bin']``, and it is rarely changed. - **resdirs**: List of relative paths (starting from the package root) of directories in which to find resource files (images, xml, etc). By default it is empty. - **srcdirs**: List of relative paths (starting from the package root) of directories in which to find sources (like .c, .cpp). By default it is empty. It might be used to store sources (for later debugging of packages, or to reuse those sources building them in other packages too). -- **builddirs**: List of relative paths (starting from package root) of directories that can contain build scripts that could be used by the consumers. EMpty by default. +- **builddirs**: List of relative paths (starting from package root) of directories that can contain build scripts that could be used by the consumers. Empty by default. - **frameworkdirs**: List of relative paths (starting from the package root), of directories containing OSX frameworks. Flags: @@ -75,14 +75,14 @@ Flags: Rarely used. Properties: -- **set_property()** allows to define some built-in and user general properties to be propagated with the ``cpp_info`` model for consumers. They might contain build-system specific information. Some built-in properties are ``cmake_file_name``, ``cmake_target_name``, ``pkg_config_name``, that can define specific behavior for ``CMakeDeps`` or ``PkgConfigDeps`` generators. For more information about these, read the specific build system integration. +- **set_property()** allows to define some built-in and user general properties to be propagated with the ``cpp_info`` model for consumers. They might contain build-system specific information. Some built-in properties are ``cmake_file_name``, ``cmake_target_name``, ``pkg_config_name``, that can define specific behavior for ``CMakeDeps`` or ``PkgConfigDeps`` generators. For more information about these, read the specific build system integration documentation. Structure: - **components**: Dictionary with names as keys and a component object as value to model the different components a package may have: libraries, executables... - **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 . + be used by generators that add support for components features. It is common that different configurations will produce different ``package_info``, for example, the library names might change in different OSs, @@ -113,7 +113,7 @@ TBD buildenv_info, runenv_info -------------------------- -The ``buildenv_info`` and ``runenv_info`` are ``Environment`` objects that allow to define information for the consumers in form of environment variables. +The ``buildenv_info`` and ``runenv_info`` attributes are ``Environment`` objects that allow to define information for the consumers in the form of environment variables. They can use any of the ``Environment`` methods to define such information: .. code-block:: python @@ -148,7 +148,7 @@ Conan ``VirtualBuildEnv`` generator will be used by default in consumers, collec conf_info --------- -``tool_requires`` packages in the "build" context can transmit some ``conf`` configuration to its immediate consumers, with the ``conf_info``. For example, one Conan +``tool_requires`` packages in the "build" context can transmit some ``conf`` configuration to its immediate consumers, with the ``conf_info`` attribute. For example, one Conan package packaging the AndroidNDK could do: .. code-block:: python @@ -163,8 +163,8 @@ package packaging the AndroidNDK could do: **Best practices** - - The ``package_info()`` is not strictly necessary if you have other means to propagate information for consumers. For example, if your package creates ``xxx-config.cmake`` files at build time, and they are put in the final package, it might not be necessary to define ``package_info()`` at all, and in the consumer side the ``CMakeDeps`` would not be necessary either, as ``CMakeToolchain`` is able to inject the paths to locate the ``xxx-config.cmake`` files inside the packages. This approach can be good for private usage of Conan, albeit some limitations of CMake, like not being able to manage multi-configuration projects (like Visual Studio switching Debug/Release in the IDE, that ``CMakeDeps`` can provide), limitations in some cross-build scenarios using packages that are both libraries and build tools (like ``protobuf``, that also ``CMakeDeps`` can handle). + - The ``package_info()`` method is not strictly necessary if you have other means of propagating information for consumers. For example, if your package creates ``xxx-config.cmake`` files at build time, and they are put in the final package, it might not be necessary to define ``package_info()`` at all, and in the consumer side the ``CMakeDeps`` would not be necessary either, as ``CMakeToolchain`` is able to inject the paths to locate the ``xxx-config.cmake`` files inside the packages. This approach can be good for private usage of Conan, albeit some limitations of CMake, like not being able to manage multi-configuration projects (like Visual Studio switching Debug/Release in the IDE, that ``CMakeDeps`` can provide), limitations in some cross-build scenarios using packages that are both libraries and build tools (like ``protobuf``, that also ``CMakeDeps`` can handle). - Providing a ``package_info()`` is very necessary if consumers can use different build systems, like in ConanCenter. In this case, it is necessary a bit of repetition, and coding the ``package_info()`` might feel duplicating the package ``xxx-config.cmake``, but automatically extracting the info from CMake is not feasible at this moment. - - If you plan to use editables or the local development flow, need to check the ``layout()`` and defining the information for ``self.cpp.build`` and ``self.cpp.source`` + - If you plan to use editables or the local development flow, there's a need to check the ``layout()`` and define the information for ``self.cpp.build`` and ``self.cpp.source``. - It is not necessary to add ``bindirs`` to the ``PATH`` environment variable, this will be automatically done by the consumer ``VirtualBuildEnv`` and ``VirtualRunEnv`` generators. - - The **paths** defined in ``package_info()`` shouldn't be converted in ``package_info()`` to any specific format (like the one required by Windows subsystems). Instead, it is the responsibility of the consumer to translate these paths to the adequate format. + - The **paths** defined in ``package_info()`` shouldn't be converted to any specific format (like the one required by Windows subsystems). Instead, it is the responsibility of the consumer to translate these paths to the adequate format. diff --git a/reference/conanfile/methods/requirements.rst b/reference/conanfile/methods/requirements.rst index e9c4af6acea6..40ff35eb0f4e 100644 --- a/reference/conanfile/methods/requirements.rst +++ b/reference/conanfile/methods/requirements.rst @@ -8,7 +8,7 @@ Requirement traits Traits are properties of a requires clause. They determine how various parts of a dependency are treated and propagated by Conan. Values for traits are usually computed by -Conan based on dependency's :ref:`reference_conanfile_attributes_package_type`, but can +Conan based on the dependency's :ref:`reference_conanfile_attributes_package_type`, but can also be specified manually. A good introduction to traits is provided in the `Advanced Dependencies Model in Conan 2.0 diff --git a/reference/conanfile/methods/validate_build.rst b/reference/conanfile/methods/validate_build.rst index 7ca8dad6b2ba..18913dd50952 100644 --- a/reference/conanfile/methods/validate_build.rst +++ b/reference/conanfile/methods/validate_build.rst @@ -4,7 +4,7 @@ validate_build() ================ -The ``validate_build()`` method is used to verify if a package binary can be **built** with the current configuration. It is different than the ``validate()`` method, that raises when the package cannot be **used** with the current configuration. +The ``validate_build()`` method is used to verify if a package binary can be **built** with the current configuration. It is different than the ``validate()`` method which raises when the package cannot be **used** with the current configuration. The ``validate_build()`` method can check the ``self.settings`` and ``self.options`` values to raise ``ConanInvalidaConfiguration`` if necessary.