依赖项对 package_id
的影响¶
当一个给定包依赖并使用另一个包时,依赖项的影响会因包类型而异
对于库
非嵌入模式:当一个应用程序或共享库依赖于另一个共享库,或者当一个静态库依赖于另一个静态库时,“消费者”库根本不会复制“依赖项”的二进制工件。我们称之为非嵌入模式,依赖项的二进制文件没有被链接或嵌入到消费者中。这假设依赖项头文件中没有内联功能,并且头文件是纯接口而非实现。
嵌入模式:当一个应用程序或共享库依赖于一个仅头文件库或静态库时,依赖项的二进制文件会被复制或部分复制(取决于链接器)到消费者二进制文件中。同样,当一个静态库依赖于一个仅头文件库时,被认为这些头文件会嵌入到消费者二进制文件中,因为它们也将包含实现,所以它们不可能是纯接口。
对于应用程序 (tool_requires
)
构建模式:当某个包使用另一个包的
tool_requires
时,依赖项中的二进制工件永远不会被复制或嵌入。
非嵌入模式¶
当我们列出带有依赖项的 openssl
包的二进制文件时
$ 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
此二进制文件是一个 共享
库,以共享库形式链接 zlib
。这意味着它使用的是“非嵌入”模式。非嵌入模式的默认值是 minor_mode
,这意味着
所有
zlib
补丁版本都将映射到相同的zlib/1.3.Z
。这意味着如果我们的openssl/3.1.2
包的二进制文件0348efdcd0e319fb58ea747bb94dbd88850d6dd1
被认为与所有zlib/1.3.Z
版本(对于任何Z
)二进制兼容,则无需重新构建openssl
二进制文件。zlib
的新次要版本,如zlib/1.4.0
,将生成一个“次要模式”标识符,如zlib/1.4.Z
,然后,它将需要一个新的openssl/3.1.2
包二进制文件,带有新的package_id
嵌入模式¶
以下命令说明了嵌入模式的概念。我们创建一个包含静态库的 dep/0.1
包,然后创建一个 app/0.1
包,其中包含一个可执行文件,该文件链接到 dep/0.1
内部的静态库。我们可以使用 conan new
命令快速创建这两个包
$ 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!
如果我们现在列出 app/0.1
的二进制文件,我们将看到刚刚创建的二进制文件
$ 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
现在可以看到 app/0.1
的 package-id 依赖于 dep/0.1
依赖项的完整标识符,其中包括其配方修订版和 package_id
。
如果我们现在更改 dep
代码,并重新创建 dep/0.1
包,即使我们不提升版本,它也会创建一个新的配方修订版
$ 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
因此,如果我们现在尝试安装 app/0.1
的二进制文件,它将因“缺少二进制文件”错误而失败
$ 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'
由于 app
可执行文件链接到 dep
静态库,因此即使 dep/0.1
没有提升版本,它也需要重新构建以包含最新更改,app/0.1
以“嵌入模式”依赖于 dep/0.1
,因此它将使用到该依赖项标识符的 package_id
。
让我们构建新的 app/0.1
二进制文件
$ cd ../app
$ conan create .
dep/0.1: Hello Moon Release! # Message changed to Moon
...
app/0.1: Hello World Release!
现在我们将有两个不同的 app/0.1
二进制文件
$ 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
我们将有两个不同的二进制文件,其中一个链接到 dep/0.1
依赖项的第一个修订版(带有“Hello World”消息),另一个二进制文件带有另一个 package_id
,链接到 dep/0.1
依赖项的第二个修订版(带有“Hello Moon”消息)。
上述模式称为 full_mode
,它是 embed_mode
的默认值。