Skip to content

Commit 29e8a3d

Browse files
danimtbAbrilRBS
andauthored
Improve reference for the build_id() method (#4158)
* Improve reference for the build_id() method * fix * Update reference/conanfile/methods/build_id.rst Co-authored-by: Abril Rincón Blanco <[email protected]> * Update reference/conanfile/methods/build_id.rst Co-authored-by: Abril Rincón Blanco <[email protected]> * Update reference/conanfile/methods/build_id.rst --------- Co-authored-by: Abril Rincón Blanco <[email protected]>
1 parent bda5355 commit 29e8a3d

File tree

1 file changed

+70
-25
lines changed

1 file changed

+70
-25
lines changed

reference/conanfile/methods/build_id.rst

Lines changed: 70 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,101 @@
33
build_id()
44
==========
55

6-
The ``build_id()`` method allows to re-use the same build to create different binary packages in the cache,
7-
potentially saving build time as it can avoid some unnecessary re-builds. It is therefore an optimization method.
6+
The ``build_id()`` method allows you to **reuse a single build** to create multiple binary packages in the Conan cache,
7+
saving time by avoiding unnecessary rebuilds.
88

9-
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
10-
can be changed, there are a couple of scenarios that this might be useful:
9+
It is primarily an optimization tool for situations where **building each configuration separately isn't feasible**.
1110

12-
- 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.
13-
- 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).
11+
There are a couple of scenarios where this could be useful, for example, when a package build:
1412

15-
In the first case, we could for example write:
13+
* **Generates multiple configurations in a single build run**:
14+
Some build scripts always produce both Debug and Release artifacts together, without a way to build them separately.
1615

17-
.. code-block:: python
16+
17+
* **Produces one configuration but different sets of artifacts**:
18+
The build could generate the main library plus some test executables, and you want to create:
19+
20+
* one package with just the library (for general use), and
21+
* another package that includes both the library and the test binaries (for compliance, debugging, or reproducibility).
22+
23+
In these scenarios, **reusing the same build folder avoids recompiling the same sources multiple times** just because you need slightly different packaging.
24+
25+
How does the build folder relate to the package ID and the build ID?
26+
--------------------------------------------------------------------
27+
28+
By default, Conan creates **one build folder per unique package ID**, where:
29+
30+
* Generally, the **package ID** depends on the combination of `settings`, `options`, and dependencies.
31+
* Each different **package ID** triggers a separate ``build()`` execution and generates a separate build folder.
32+
33+
When you define the ``build_id()`` method, you can **force different package IDs to share the same build folder** by customizing `self.info_build`:
34+
35+
* ``self.info_build`` is like ``self.info``, but it only affects the computation of the **build ID**, not the final package ID.
36+
* Any package IDs with the same build ID will reuse the same build folder and the same build step.
37+
38+
39+
Example: sharing the build for Debug and Release
40+
++++++++++++++++++++++++++++++++++++++++++++++++
41+
42+
.. code-block:: python
1843
1944
settings = "os", "compiler", "arch", "build_type"
2045
2146
def build_id(self):
2247
self.info_build.settings.build_type = "Any"
2348
24-
This recipe will generate a final different package with a different ``package_id`` for debug and release configurations. But as the ``build_id()`` will generate the
25-
same ``build_id`` for any ``build_type``, then just one folder and one ``build()`` will be done, building both debug and release artifacts,
26-
and then the ``package()`` method will be called for each configuration, and it should package the artifacts conditionally to the ``self.settings.build_type`` value. Different builds will still be
27-
executed if using different compilers or architectures.
49+
* With this recipe, Debug and Release will each produce their own package IDs (and thus their own binary packages),
50+
but they will **share the same build folder**, because the build ID ignores the ``build_type`` setting.
51+
* **However, you still need to run one** :command:`conan create` **command per configuration** (e.g., once for Debug, once for Release).
52+
Conan will check if the build folder already exists (based on the shared build ID) and skip the actual compilation
53+
if it's already been built, only executing `package()` to create the corresponding package.
2854

29-
Other information like custom package options can also be changed:
55+
Example workflow:
3056

31-
.. code-block:: python
57+
.. code-block:: bash
3258
33-
def build_id(self):
34-
self.info_build.options.myoption = 'MyValue' # any value possible
35-
self.info_build.options.fullsource = 'Always'
59+
# First build: creates the build folder + packages the Debug package
60+
$ conan create . -s build_type=Debug
61+
62+
# Second build: reuses the previous build folder + packages the Release package without rebuilding
63+
$ conan create . -s build_type=Release
64+
65+
This way, although we called :command:`conan create` twice (once per package ID), the actual build will only happen once.
66+
67+
.. note::
68+
69+
You can also customize ``build_id()`` based on options:
70+
71+
.. code-block:: python
72+
73+
def build_id(self):
74+
self.info_build.options.myoption = "MyValue"
75+
self.info_build.options.fullsource = "Always"
76+
77+
Conditional usage of the build ID
78+
---------------------------------
3679

37-
If the ``build_id()`` method does not modify the ``info_build`` data, and it still produces a different id than
38-
the ``package_id``, then the standard behavior will be applied. Consider the following:
80+
If the ``build_id()`` method does not modify the ``self.info_build`` data, and produces the same build ID as the package ID,
81+
then the standard behavior will be applied. For example:
3982

40-
.. code-block:: python
83+
.. code-block:: python
4184
4285
settings = "os", "compiler", "arch", "build_type"
4386
4487
def build_id(self):
4588
if self.settings.os == "Windows":
4689
self.info_build.settings.build_type = "Any"
4790
48-
This will only produce a different ``build_id`` if the package is for Windows, thus running ``build()`` just
49-
once for all ``build_type`` values. The behavior
50-
in any other OS will be the standard one, as if the ``build_id()`` method was not defined, running
51-
one different ``build()`` for each ``build_type``.
91+
This will only produce a different **build ID** if the package is for Windows, so it will only run the ``build()`` method once
92+
for all the ``build_type`` values.
5293

94+
For any other OS, Conan will behave as usual (as if the ``build_id()`` method was not defined), running the ``build()`` method
95+
for every ``build_type`` configuration.
5396

5497
.. note::
5598

5699
**Best practices**
57100

58-
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.
101+
The goal of the ``build_id()`` method is to deal with legacy build scripts that cannot easily be changed
102+
to compile one configuration at a time. We strongly recommend to just package **one package binary per package ID**
103+
for each different configuration.

0 commit comments

Comments
 (0)