The effect of dependencies on package_id
When a given package depends on a another package and uses it, the effect of dependencies can be different based on the package types:
For libraries:
Non-embed mode: When an application or a shared library depends on another shared library, or when a static library depends on another static library, the “consumer” library does not do a copy of the binary artifacts of the “dependency” at all. We call it non-embed mode, the dependency binaries are not being linked or embedded in the consumer. This assumes that there are not inlined functionalities in the dependency headers, and the headers are pure interface and not implementation.
Embed mode: When an application or a shared library depends on a header-only or a static-library, the dependencies binaries are copied or partially copied (depending on the linker) in the consumer binary. Also when a static library depends on a header-only library, it is considered that there will be embedding in the consumer binary of such headers, as they will also contain the implementation, it is impossible that they are a pure interface.
For applications (tool_requires
):
- Build mode: When some package uses a
tool_requires
of another package, the binary artifacts in the dependency are never copied or embedded.
Non-embed mode
When we list the binaries of a package like openssl
with dependencies:
$ conan list openssl/3.1.2:* -r=conancenter
conancenter
openssl
openssl/3.1.2
revisions
8879e931d726a8aad7f372e28470faa1 (2023-09-13 18:52:54 UTC)
packages
0348efdcd0e319fb58ea747bb94dbd88850d6dd1 # package_id
info
options
shared: True
...
requires
zlib/1.3.Z
This binary was a shared
library, linking with zlib
as a shared library. This means it was using “non-embed” mode. The default of non-embed mode is minor_mode
, which means:
All
zlib
patch versions will be mapped to the samezlib/1.3.Z
. This means that if ouropenssl/3.1.2
package binary0348efdcd0e319fb58ea747bb94dbd88850d6dd1
binary is considered binary compatible with allzlib/1.3.Z
versions (for anyZ
), and will not require to rebuild theopenssl
binary.New
zlib
minor versions, likezlib/1.4.0
will result in a “minor-mode” identifier likezlib/1.4.Z
, and then, it will require a newopenssl/3.1.2
package binary, with a newpackage_id
Embed mode
The following commands illustrate the concept of embed-mode. We create a dep/0.1
package with a static library, and then we create a app/0.1
package with an executable that links with static library inside dep/0.1
. We can use the conan new
command for quickly creating these two packages:
$ mkdir dep && cd dep
$ conan new cmake_lib -d name=dep -d version=0.1
$ conan create . -tf=""
$ cd .. && mkdir app && cd app
$ conan new cmake_exe -d name=app -d version=0.1 -d requires=dep/0.1
$ conan create .
dep/0.1: Hello World Release!
...
app/0.1: Hello World Release!
If we now list the app/0.1
binaries, we will see the binary just created:
$ conan list app/0.1:*
Local Cache
app/0.1
revisions
632e236936211ac2293ec33339ce582b (2023-09-25 22:34:17 UTC)
packages
3ca530d20914cf632eb00efbccc564da48190314
info
settings
...
requires
dep/0.1#d125304fb1fb088d5b92d4f8135f4dff:9bdee485ef71c14ac5f8a657202632bdb8b4482b
It is now visible that the app/0.1
package-id depends on the full identifier of the dep/0.1
dependency, that includes both its recipe revision and package_id
.
If we do a change now to the dep
code, and re-create the dep/0.1
package , even if we don’t bump the version, it will create a new recipe revision:
$ cd ../dep
# Change the "src/dep.cpp" code to print a new message, like "Hello Moon"
$ conan create . -tf=""
# New recipe revision dep/0.1#1c90e8b8306c359b103da31faeee824c
So if we try now to install app/0.1
binary, it will fail with a “missing binary” error:
$ conan install --requires=app/0.1
ERROR: Missing binary: app/0.1:ef2b5ed33d26b35b9147c90b27b217e2c7bde2d0
app/0.1: WARN: Can't find a 'app/0.1' package binary 'ef2b5ed33d26b35b9147c90b27b217e2c7bde2d0' for the configuration:
[settings]
...
[requires]
dep/0.1#1c90e8b8306c359b103da31faeee824c:9bdee485ef71c14ac5f8a657202632bdb8b4482b
ERROR: Missing prebuilt package for 'app/0.1'
As the app
executable links with the dep
static library, it needs to be rebuilt to include the latest changes, even if dep/0.1
didn’t bump its version, app/0.1
depends on “embed-mode” on dep/0.1
, so it wil use down to the package_id
of such dependency identifier.
Let’s build the new app/0.1
binary:
$ cd ../app
$ conan create .
dep/0.1: Hello Moon Release! # Message changed to Moon
...
app/0.1: Hello World Release!
Now we will have two app/0.1
different binaries:
$ conan list "app/0.1:*"
Local Cache
app
app/0.1
revisions
632e236936211ac2293ec33339ce582b (2023-09-25 22:49:32 UTC)
packages
3ca530d20914cf632eb00efbccc564da48190314
info
settings
...
requires
dep/0.1#d125304fb1fb088d5b92d4f8135f4dff:9bdee485ef71c14ac5f8a657202632bdb8b4482b
ef2b5ed33d26b35b9147c90b27b217e2c7bde2d0
info
settings
...
requires
dep/0.1#1c90e8b8306c359b103da31faeee824c:9bdee485ef71c14ac5f8a657202632bdb8b4482b
We will have these two different binaries, one of them linking with the first revision of the dep/0.1
dependency (with the “Hello World” message), and the other binary with the other package_id
linked with the second revision of the dep/0.1
dependency (with the “Hello Moon” message).
The above described mode is called full_mode
, and it is the default for the embed_mode
.