Skip to content

Commit b8cb01c

Browse files
authored
Intel compiler docs and new compatible packages approach (conan-io#1479)
* Intel compiler docs and new compatible packages approach * Review
1 parent a10166c commit b8cb01c

File tree

6 files changed

+168
-15
lines changed

6 files changed

+168
-15
lines changed

creating_packages/define_abi_compatibility.rst

+111-6
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,12 @@ in the range ``(v >= "4.5" and v < "5.0")`` will have exactly the same package I
169169
used to build it. It worked like an information erasure, once the binary is built, it is not possible to know which
170170
gcc was used to build it.
171171

172-
Using ``CompatiblePackage``, it is possible to define compatible binaries that have different package IDs. With
173-
this ``CompatiblePackage`` feature, it is possible to have a different binary for each ``gcc`` version, so the
172+
But it is possible to define compatible binaries that have different package IDs. For instance, it
173+
is possible to have a different binary for each ``gcc`` version, so the
174174
``gcc 4.8`` package will be a different one with a different package ID than the ``gcc 4.9`` one, and still define
175175
that you can use the ``gcc 4.8`` package when building with ``gcc 4.9``.
176176

177-
With ``CompatiblePackage`` we can define an ordered list of compatible packages, that will be checked in order if
177+
We can define an ordered list of compatible packages, that will be checked in order if
178178
the package ID that our profile defines is not available. Let's see it with an example:
179179

180180
Lets say that we are building with a profile of ``gcc 4.9``. But for a given package we want to
@@ -191,14 +191,15 @@ That can be defined as:
191191
def package_id(self):
192192
if self.settings.compiler == "gcc" and self.settings.compiler.version == "4.9":
193193
for version in ("4.8", "4.7"):
194-
compatible_pkg = CompatiblePackage(self)
194+
compatible_pkg = self.info.clone()
195195
compatible_pkg.settings.compiler.version = version
196196
self.compatible_packages.append(compatible_pkg)
197197
198198
Note that if the input configuration is ``gcc 4.8``, it will not try to fallback to binaries of ``gcc 4.7`` as the
199199
condition is not met.
200200

201-
The ``CompatiblePackage()`` copies the values of ``settings``, ``options`` and ``requires`` from the current instance of the recipe so they can be modified to model the compatibility.
201+
The ``self.info.clone()`` method copies the values of ``settings``, ``options`` and ``requires`` from the current instance of
202+
the recipe so they can be modified to model the compatibility.
202203

203204
It is the responsibility of the developer to guarantee that such binaries are indeed compatible. For example in:
204205

@@ -211,7 +212,7 @@ It is the responsibility of the developer to guarantee that such binaries are in
211212
default_options = {"optimized": 1}
212213
def package_id(self):
213214
for optimized in range(int(self.options.optimized), 0, -1):
214-
compatible_pkg = CompatiblePackage(self)
215+
compatible_pkg = self.info.clone()
215216
compatible_pkg.options.optimized = optimized
216217
self.compatible_packages.append(compatible_pkg)
217218
@@ -226,6 +227,88 @@ the ``optimized`` option to conditionally require different dependencies, that w
226227
step is processed after the whole dependency graph has been built, so it is not possible to define how dependencies are resolved
227228
based on this compatibility model, it only applies to use-cases where the binaries can be *interchanged*.
228229

230+
Check the :ref:`Compatible Compilers<compatible_compilers>` section to see another example of how to take benefit of compatible packages.
231+
232+
233+
.. _compatible_compilers:
234+
235+
Compatible Compilers
236+
--------------------
237+
238+
Some compilers make use of a base compiler to operate, for example, the ``intel`` compiler uses
239+
the ``Visual Studio`` compiler in Windows environments and ``gcc`` in Linux environments.
240+
241+
The ``intel`` compiler is declared this way in the :ref:`settings.yml<settings_yml>`:
242+
243+
.. code-block:: yaml
244+
245+
intel:
246+
version: ["11", "12", "13", "14", "15", "16", "17", "18", "19"]
247+
base:
248+
gcc:
249+
<<: *gcc
250+
threads: [None]
251+
exception: [None]
252+
Visual Studio:
253+
<<: *visual_studio
254+
255+
Remember, you can :ref:`extend Conan<extending>` to support other compilers.
256+
257+
258+
You can use the ``package_id()`` method to define the compatibility between the packages generated by the ``base`` compiler and the ``parent`` one.
259+
You can use the following helpers together with the :ref:`compatible packages<compatible_packages>` feature to:
260+
261+
- Consume native ``Visual Studio`` packages when the input compiler in the profile is ``intel`` (if no ``intel`` package is available).
262+
- The opposite, consume an ``intel`` compiler package when a consumer profile specifies ``Visual Studio`` as the input compiler (if no
263+
``Visual Studio`` package is available).
264+
265+
- ``base_compatible()``: This function will transform the settings used to calculate the package ID into the "base" compiler.
266+
267+
.. code-block:: python
268+
269+
def package_id(self):
270+
271+
if self.settings.compiler == "intel":
272+
p = self.info.clone()
273+
p.base_compatible()
274+
self.compatible_packages.append(p)
275+
276+
Using the above ``package_id()`` method, if a consumer specifies a profile with a intel profile (**-s compiler=="intel"**) and there is no binary available, it will resolve to a
277+
Visual Studio package ID corresponding to the base compiler.
278+
279+
280+
- ``parent_compatible(compiler="compiler", version="version")``: This function transforms the settings of a compiler into the settings of a
281+
parent one using the specified one as the base compiler. As the details of the "parent" compatible cannot be guessed, you have to provide them as **keyword args** to the
282+
function. The "compiler" argument is mandatory, the rest of keyword arguments will be used to initialize the ``info.settings.compiler.XXX`` objects
283+
to calculate the correct package ID.
284+
285+
.. code-block:: python
286+
287+
def package_id(self):
288+
289+
if self.settings.compiler == "Visual Studio":
290+
compatible_pkg = self.info.clone()
291+
compatible_pkg.parent_compatible(compiler="intel", version=16)
292+
self.compatible_packages.append(compatible_pkg)
293+
294+
In this case, for a consumer specifying Visual Studio compiler, if no package is found, it will search for an "intel" package for the version 16.
295+
296+
297+
Take into account that you can use also these helpers without the "compatible packages" feature:
298+
299+
.. code-block:: python
300+
301+
def package_id(self):
302+
303+
if self.settings.compiler == "Visual Studio":
304+
self.info.parent_compatible(compiler="intel", version=16)
305+
306+
In the above example, we will transform the package ID of the ``Visual Studio`` package to be the same as the ``intel 16``, but you won't
307+
be able to differentiate the packages built with ``intel`` with the ones built by ``Visual Studio`` because both will have the same package ID,
308+
and that is not always desirable.
309+
310+
311+
229312

230313
.. _problem_of_dependencies:
231314

@@ -271,6 +354,7 @@ Then, **a new binary for MyLib/1.0 is required to be built for the new dependenc
271354
``addition()`` version. Even in the case that ``MyLib/1.0`` doesn't have any change in its code lines neither in the recipe, the resulting
272355
binary rebuilding ``MyLib`` requires ``MyOtherLib/2.1`` and the package to be different.
273356

357+
274358
.. _package_id_mode:
275359

276360
Using package_id() for Package Dependencies
@@ -564,6 +648,7 @@ The default behavior produces a *conaninfo.txt* that looks like:
564648
565649
Changing the default package-id mode
566650
++++++++++++++++++++++++++++++++++++
651+
567652
It is possible to change the default ``semver_direct_mode`` package-id mode, in the
568653
*conan.conf* file:
569654

@@ -591,6 +676,26 @@ that only generates 1 package-id for all possible configurations and versions of
591676

592677
Remember that *conan.conf* can be shared and installed with :ref:`conan_config_install`.
593678

679+
Take into account that you can combine the :ref:`compatible packages<compatible_packages>` with the package-id modes.
680+
681+
For example, if you are generating binary packages with the default ``recipe_revision_mode``,
682+
but you want these packages to be consumed from a client with a different mode activated,
683+
you can create a compatible package transforming the mode to ``recipe_revision_mode`` so the package
684+
generated with the ``recipe_revision_mode`` can be resolved if no package for the default mode is found:
685+
686+
.. code-block:: python
687+
688+
from conans import ConanFile, CompatiblePackage
689+
690+
class Pkg(ConanFile):
691+
...
692+
693+
def package_id(self):
694+
p = self.info.clone()
695+
p.requires.recipe_revision_mode()
696+
self.compatible_packages.append(p)
697+
698+
594699
Library Types: Shared, Static, Header-only
595700
++++++++++++++++++++++++++++++++++++++++++
596701

howtos.rst

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This section shows common solutions and different approaches to typical problems
1212
howtos/makefiles
1313
howtos/manage_gcc_abi
1414
howtos/vs2017_cmake
15+
howtos/intel_compiler
1516
howtos/manage_cpp_standard
1617
howtos/run_conan_in_docker
1718
howtos/python_code_reuse

howtos/intel_compiler.rst

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. _howto_intel_compiler:
2+
3+
Working with Intel compiler
4+
===========================
5+
6+
The ``Intel`` compiler is a particular case, as it uses ``Visual Studio`` compiler in Windows environments
7+
and ``gcc`` in Linux environments. If you are wondering how to manage the compatibility between the packages generated
8+
with ``intel`` and the generated with the pure base compiler (``gcc`` or ``Visual Studio``) check the
9+
:ref:`Compatible Packages<compatible_packages>` and :ref:`Compatible Compilers<compatible_compilers>` sections.

integrations.rst

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ packages can be consumed, created, and continuously deployed/tested with each, a
1010
.. toctree::
1111
:maxdepth: 2
1212

13+
integrations/compilers
1314
integrations/build_system
1415
integrations/ides
1516
integrations/ci

integrations/compilers.rst

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.. _integration_compilers:
2+
3+
Compilers
4+
=========
5+
6+
7+
Conan can work with any compiler, the most common ones are already declared in the default :ref:`settings.yml<settings_yml>`:
8+
9+
- `sun-cc`
10+
- `gcc`
11+
- `Visual Studio`
12+
- `clang`
13+
- `apple-clang`
14+
- `qcc`
15+
- `intel`
16+
17+
.. note ::
18+
19+
Remember that you can :ref:`customize Conan <extending>` to extend the supported compilers, build systems, etc.
20+
21+
22+
.. important::
23+
24+
If you work with a compiler like ``intel`` that uses ``Visual Studio`` in Windows environments
25+
and ``gcc`` in Linux environments and you are wondering how to manage the compatibility between the packages generated
26+
with ``intel`` and the generated with the pure base compiler (``gcc`` or ``Visual Studio``) check the
27+
:ref:`Compatible Packages<compatible_packages>` and :ref:`Compatible Compilers<compatible_compilers>` sections.

reference/config_files/settings.yml.rst

+19-9
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ are possible. These are the **default** values, but it is possible to customize
3030
version: ["5.0", "6.0", "7.0", "8.0"]
3131
Linux:
3232
Macos:
33-
version: [None, "10.6", "10.7", "10.8", "10.9", "10.10", "10.11", "10.12", "10.13", "10.14"]
33+
version: [None, "10.6", "10.7", "10.8", "10.9", "10.10", "10.11", "10.12", "10.13", "10.14", "10.15"]
3434
Android:
3535
api_level: ANY
3636
iOS:
37-
version: ["7.0", "7.1", "8.0", "8.1", "8.2", "8.3", "9.0", "9.1", "9.2", "9.3", "10.0", "10.1", "10.2", "10.3", "11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1"]
37+
version: ["7.0", "7.1", "8.0", "8.1", "8.2", "8.3", "9.0", "9.1", "9.2", "9.3", "10.0", "10.1", "10.2", "10.3", "11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4", "13.0", "13.1"]
3838
watchOS:
39-
version: ["4.0", "4.1", "4.2", "4.3", "5.0", "5.1"]
39+
version: ["4.0", "4.1", "4.2", "4.3", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1"]
4040
tvOS:
41-
version: ["11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1"]
41+
version: ["11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4", "13.0"]
4242
FreeBSD:
4343
SunOS:
4444
AIX:
@@ -53,18 +53,18 @@ are possible. These are the **default** values, but it is possible to customize
5353
version: ["5.10", "5.11", "5.12", "5.13", "5.14"]
5454
threads: [None, posix]
5555
libcxx: [libCstd, libstdcxx, libstlport, libstdc++]
56-
gcc:
56+
gcc: &gcc
5757
version: ["4.1", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9",
5858
"5", "5.1", "5.2", "5.3", "5.4", "5.5",
5959
"6", "6.1", "6.2", "6.3", "6.4",
60-
"7", "7.1", "7.2", "7.3",
60+
"7", "7.1", "7.2", "7.3", "7.4",
6161
"8", "8.1", "8.2", "8.3",
6262
"9", "9.1", "9.2"]
6363
libcxx: [libstdc++, libstdc++11]
6464
threads: [None, posix, win32] # Windows MinGW
6565
exception: [None, dwarf2, sjlj, seh] # Windows MinGW
6666
cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20]
67-
Visual Studio:
67+
Visual Studio: &visual_studio
6868
runtime: [MD, MT, MTd, MDd]
6969
version: ["8", "9", "10", "11", "12", "14", "15", "16"]
7070
toolset: [None, v90, v100, v110, v110_xp, v120, v120_xp,
@@ -74,21 +74,31 @@ are possible. These are the **default** values, but it is possible to customize
7474
cppstd: [None, 14, 17, 20]
7575
clang:
7676
version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0",
77-
"5.0", "6.0", "7.0",
78-
"8", "9"]
77+
"5.0", "6.0", "7.0", "7.1",
78+
"8", "9", "10"]
7979
libcxx: [libstdc++, libstdc++11, libc++, c++_shared, c++_static]
8080
cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20]
8181
apple-clang:
8282
version: ["5.0", "5.1", "6.0", "6.1", "7.0", "7.3", "8.0", "8.1", "9.0", "9.1", "10.0", "11.0"]
8383
libcxx: [libstdc++, libc++]
8484
cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20]
85+
intel:
86+
version: ["11", "12", "13", "14", "15", "16", "17", "18", "19"]
87+
base:
88+
gcc:
89+
<<: *gcc
90+
threads: [None]
91+
exception: [None]
92+
Visual Studio:
93+
<<: *visual_studio
8594
qcc:
8695
version: ["4.4", "5.4"]
8796
libcxx: [cxx, gpp, cpp, cpp-ne, accp, acpp-ne, ecpp, ecpp-ne]
8897
8998
build_type: [None, Debug, Release, RelWithDebInfo, MinSizeRel]
9099
cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] # Deprecated, use compiler.cppstd
91100
101+
92102
As you can see, the possible values ``settings`` can take are restricted in the same file. This is done to ensure matching naming and
93103
spelling as well as defining a common settings model among users and the OSS community.
94104
If a setting is allowed to be set to any value, you can use ``ANY``.

0 commit comments

Comments
 (0)