package_info() 必须填写 self.cpp_info.libs、includedirs 和 defines 等关键信息,否则 find_package() 或 target_link_libraries() 会因链接失败或头文件找不到而报错;需按实际库名(不含前缀/后缀)、安装后路径和构建选项条件配置,并与 package_id() 联动确保二进制兼容性。

package_info() 里必须填什么
这个方法不是可选的——只要你的包要被别人 find_package() 或 target_link_libraries(),就必须在 package_info() 中明确告诉消费者:链接哪些库、加什么宏、包含哪些头文件路径。漏掉 self.cpp_info.libs 是最常见错误,结果就是 CMake 找得到包但链接失败,报 undefined reference。
-
self.cpp_info.libs = ["mylib", "mylib_static"]:按实际生成的库文件名写(不含lib前缀或后缀,Linux/macOS 下是mylib,Windows 下也写mylib,Conan 会自动补.lib/.a/.so) -
self.cpp_info.includedirs = ["include"]:头文件根目录,相对于包安装后的路径(不是源码路径) -
self.cpp_info.defines = ["MYLIB_SHARED"]:需要传递给消费者的预处理器宏 - 如果库依赖其他 Conan 包,用
self.requires("zlib/1.2.11")声明即可,不用在package_info()里重复导出
动态库 vs 静态库怎么区分配置
Conan 不会自动判断你打包的是 .dll/.so 还是 .a/.lib,package_info() 必须配合 settings.build_type 和 options.shared 做条件分支,否则 Windows 下容易出现 LNK2019(导入库没导出符号)或 Linux 下 -lmylib 找不到动态库。
- 用
if self.options.shared:判断是否启用了共享构建,然后设置不同的libs和defines - 静态库通常需要额外链接运行时(如
self.cpp_info.system_libs = ["m", "pthread"]),动态库一般不需要 - 不要硬编码
mylib.dll或libmylib.so——self.cpp_info.libs只写逻辑名,后缀由 Conan 根据平台和shared选项自动处理
为什么 package_id() 和 package_info() 要联动
package_info() 里暴露的内容,直接影响 package_id() 的计算结果。比如你只在 shared=True 时才加 MYLIB_SHARED 宏,但 package_id() 没把 shared 选项纳入哈希,就会导致:同一个二进制包被同时用于 shared=True 和 shared=False 场景,链接时符号不匹配。
- 默认情况下,
shared选项已参与package_id计算,但如果你重写了package_id()却忘了调用self.info.include(self.settings)或self.info.include(self.options),就可能丢失关键维度 - 如果
package_info()中根据self.settings.os == "Windows"添加了self.cpp_info.system_libs = ["ws2_32"],那package_id()就必须保留os设置,否则 Linux 用户可能误取到 Windows 二进制 - 验证方式:
conan create . user/channel --build=missing后,检查conan search mylib/1.0@user/channel输出的 package ID 是否随-o mylib:shared=True/False改变
CMakeDeps 生成器下 package_info() 还要不要写 include dirs
要写,而且必须写对。CMakeDeps 不会读取你源码里的 include_directories(),它只信任 package_info().cpp_info.includedirs。如果你写成 ["src/include"] 但实际安装后头文件在 include/ 目录下,CMake 就会报 fatal error: mylib/myheader.h: No such file or directory。
- 路径必须是安装后结构中的相对路径,不是源码树路径;典型做法是在
package()方法里用self.copy("*.h", dst="include", src="src/include"),然后includedirs = ["include"] - 如果头文件分散在多级目录(如
include/mylib/v1/和include/mylib/detail/),统一设为["include"]即可,让使用者用#include <mylib></mylib> - 不要依赖
self.cpp_info.builddirs或self.cpp_info.resdirs来“修复”头文件路径问题——那是给构建时资源用的,不是给#include用的
package_info(),必须重新 conan create 或 conan export-pkg,否则旧二进制包里的元信息不会更新,下游 conan install 拿到的还是老配置。











