能跑通的conanfile.py核心是正确实现source()、build()、package()、package_info()四个方法:source()拉取源码,build()用cmake等构建,package()用self.copy()精准拷贝头文件到include、库文件到lib/bin,package_info()必须设self.cpp_info.libs=["foo"]且名称与实际库一致。

直接用 conan create 就能打包,但关键在配方(conanfile.py)里是否准确描述了构建逻辑、头文件路径、库名和链接信息——漏掉 self.cpp_info.libs 或路径错配,下游项目一链接就报 undefined reference。
怎么写一个能跑通的 conanfile.py
核心是四个方法: source()、build()、package()、package_info()。不依赖 CMake 的纯头文件库可以跳过 build(),但只要生成 .a、.so、.lib 或 .dll,就必须有 build() 步骤。
-
source()要确保源码能拉下来,比如self.run("git clone -b v1.2.0 https://...");如果本地已有源码,改用tools.get()或直接copy到self.source_folder -
build()推荐用CMake(self)封装,避免手动拼命令行;注意传参source_folder和build_folder,否则 CMake 找不到CMakeLists.txt -
package()里self.copy()的dst和src路径容易反:头文件进include,静态库进lib,动态库 Windows 进bin、Linux/macOS 进lib;keep_path=False很重要,否则可能把build/lib/Release/libfoo.a整层拷进去 -
package_info()必须设self.cpp_info.libs = ["foo"](名字要和实际产出的库名一致,不含前缀lib或后缀),否则下游find_package(foo)会找不到符号
为什么 conan create 会找不到库文件
常见原因是 package() 没拷对位置,或 build() 根本没执行成功但被忽略。运行 conan create . user/channel -s build_type=Release 后,检查临时构建目录(默认在 ~/.conan/data/xxx 下对应路径的 build/ 子目录)里是否有 libfoo.a;再看 package/ 目录下 lib/ 是否真有该文件。如果 build() 报错但被静默吞掉,加 --build=missing 强制重跑,或临时注释掉 build() 改成 self.run("ls -l build/") 看输出。
- Windows MSVC 下常见
/MDvs/MT不匹配:在CMakeLists.txt里硬编码set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$:Debug>DLL"),或用tools.replace_in_file()注入conan_basic_setup() - 交叉编译时
settings.arch和settings.os必须和目标平台完全一致,比如armv7和armv8是不同包 ID,不能混用 - 如果用了
cmake_layout(),source()拉的代码必须放在self.source_folder,否则cmake.configure(source_folder=...)会失败
怎么验证包是否真的可用
别急着 upload,先用 conan install 在空项目里测。建个最小测试项目:
mkdir test_consumer && cd test_consumer echo "[requires]\nyourlib/1.0.0@user/channel" > conanfile.txt echo "[generators]\ncmake_find_package" >> conanfile.txt conan install . --build=missing
然后检查 conanbuildinfo.cmake 里有没有 set(yourlib_LIBS ...) 和 set(yourlib_INCLUDE_DIRS ...)。再写个极简 CMakeLists.txt:find_package(yourlib REQUIRED) + target_link_libraries(main PRIVATE yourlib::yourlib),cmake .. && cmake --build . 能过才算真正可用。
- 如果
find_package()失败,先确认conan remote add加了对应远程,且conan search yourlib/1.0.0@user/channel能查到 - 如果链接失败但头文件能找到,90% 是
self.cpp_info.libs值不对,或者self.cpp_info.libdirs指向了空目录 - Mac 上动态库要留意
self.cpp_info.set_property("cmake_file_name", "YourLib"),否则 CMake target 名可能不匹配
最常被跳过的其实是 package_id() ——如果你的库不随 compiler.version 变化(比如纯 C++20 模板库),得显式写 self.info.clear() 或 self.info.header_only(),否则 Conan 默认为每个编译器版本都生成独立包 ID,徒增缓存体积和上传负担。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











