conanfile.py中exports_sources必须显式声明源文件路径,漏配会导致包内缺失头文件或cmakelists.txt;需用list类型、posix路径、**通配符覆盖子目录,并配合package()中正确self.copy()及--build=missing强制重建。

检查 conanfile.py 中的 exports_sources 是否漏配
Conan 打包时不会自动包含所有源文件,exports_sources 字段必须显式声明哪些文件参与构建。漏写路径、用错通配符(比如写成 "src/*" 却忘了 "src/**" 不匹配子目录)、或路径拼写大小写错误,都会导致最终生成的包里缺头文件、CMakeLists.txt 甚至 .cpp 文件。
常见错误现象:conan create . 成功,但下游项目 #include "mylib.h" 报 C1083;或者 conan install 后 conanfile.py 里定义的 self.cpp_info.includedirs 指向的目录为空。
- 确认
exports_sources是 list 类型,不是 str(错误写法:exports_sources = "src/*.h") - Windows 下路径分隔符用
/,别用(Conan 内部统一处理为 POSIX 风格) - 若含子目录,优先用
**:例如"include/**", "src/**", "CMakeLists.txt" - 运行
conan export-pkg . --build=missing后,进缓存目录手动验证:ls ~/.conan/data/mylib/1.0/_/_/export/看文件是否真在
验证 package() 方法里是否漏 copy 或路径写错
package() 是把源码中需要交付的文件真正拷贝进二进制包的关键步骤。这里出错比 exports_sources 更隐蔽——因为 build 过程可能成功,但 package() 里的 self.copy() 路径没对上,结果包里只有空目录。
典型表现:本地 conan create 成功,但远程 conan install 后找不到头文件;或 conan inspect mylib/1.0@ -a cpp_info.includedirs 返回空列表。
-
self.copy()的src参数是相对于source_folder(默认是self.source_folder),不是当前 conanfile.py 所在目录 - 别依赖相对路径如
"../include",应统一用os.path.join(self.source_folder, "include") - 加
keep_path=True才保留子目录结构;否则所有头文件会被扁平化到同一级 - 调试时临时加
self.output.info(f"Copying from {src_dir}"),看日志是否真执行了 copy
确认 settings 和 options 是否导致 package_id 分裂却没重建
Conan 2.0 默认按 settings(如 os, compiler, build_type)和 options(如 shared=True)动态计算 package_id。如果你改了 conanfile.py 但没改 version,又没清缓存,Conan 可能复用旧二进制包——而那个旧包压根没包含你新加的文件。
错误现象:改完 exports_sources 和 package() 后 conan create 日志显示 “Package already exists”,但实际文件还是旧的。
- 强制重建:加
--build=missing或--build=mylib - 查缓存里到底有哪些变体:
conan list mylib/1.0@ --graph=file.json,再用jq看package_id列表 - 临时简化
settings(比如删掉compiler.version)可快速验证是否因 ABI 分裂导致“看似创建成功实则未更新”
检查 Conan 缓存权限与符号链接行为
在 macOS 或 Linux 上,如果项目用了 git submodule 或硬链接,Conan 默认不会递归拷贝符号链接目标内容;Windows WSL2 下若源文件在 Windows 分区(如 /mnt/c/...),self.copy() 可能因跨文件系统权限失败而静默跳过。
最易被忽略的一点:Conan 缓存目录(~/.conan2)若挂载在 NFS 或加密卷上,某些 os.walk() 操作会因权限拒绝中断,copy 不报错但不生效。
- 用
conan cache path mylib/1.0@定位实际缓存位置,ls -la看 owner 和 perm - 测试是否 link 问题:把源码复制到
~/tmp/mylib再conan create - Windows 用户注意:WSL2 中避免
self.source_folder指向/mnt/c/...,改用\wsl$路径或纯 Linux 路径
package() 开头加一行 self.output.info(f"Source folder: {self.source_folder}"),再进缓存目录手动 ls,眼见为实。











