Conan create链接失败主因是package()未按约定路径拷贝库文件:头文件须进include/,静态库.a/.lib进lib/,动态库.so/.dll进bin/;否则下游链接器找不到符号或库。

Conan create 打包时链接失败,90% 是 package() 方法没把库文件拷对位置,不是代码或 CMake 写错了。
conan create 报 undefined reference 或找不到 .so/.a 文件
典型现象是 conan create . user/channel 运行到 build 步骤成功,但 package 阶段或后续 consumer 项目链接时报错,比如:
undefined reference to 'xxx::func()'cannot find -lmylib- 用
conan test时提示Could not find library 'mylib'
根本原因不是源码编译失败,而是 Conan 包结构不合规:它只认固定路径下的文件。CMake 构建生成的 lib/ 或 bin/ 目录内容,必须显式复制进 Conan 的包布局里。
正确做法是在 conanfile.py 的 package() 方法中写:
def package(self):
self.copy("*.h", dst="include", src="include")
self.copy("*.lib", dst="lib", keep_path=False)
self.copy("*.a", dst="lib", keep_path=False)
self.copy("*.so", dst="lib", keep_path=False)
self.copy("*.dll", dst="bin", keep_path=False)注意:dst="lib" 不是随便起的,Conan 的 cmake_find_package 等 generator 就是靠这个目录名自动加 -L 和 -l;dst="bin" 则用于 runtime 查找动态库(Windows/Linux 均适用)。
头文件能 include 但链接器找不到符号
这说明头文件路径对了(include() 拷过去了),但静态/动态库没进 lib/,或者名字不匹配。常见疏漏包括:
- 忘记拷
.a或.so—— 只拷了.h和.cmake文件 - 库名带版本后缀(如
libmylib.so.1.2),但target_link_libraries()写的是mylib;Conan 默认不处理 soname,得手动 symlink 或用self.copy("libmylib.so*", ...) - CMake 构建时用了
INSTALL,但package()里没调用cmake.install(),导致 install 目录没被读取
建议统一走 cmake.install() 路径,更可控:
def package(self):
cmake = self._configure_cmake()
cmake.install() # 这会把 install 目录下所有内容按 CMake install 规则映射进 Conan 包前提是你的 CMakeLists.txt 里写了 install(TARGETS ... LIBRARY DESTINATION lib) 等语句。
conan create 时提示找不到 xxx.h 或链接失败,但本地编译正常
这是最易误判的情况。本地编译走的是源码树路径(${CMAKE_SOURCE_DIR}/include),而 conan create 进入的是隔离的构建沙盒,且最终包结构和源码结构完全分离。
关键检查点:
-
exports_sources是否包含所有需要参与构建的源文件?漏掉src/或CMakeLists.txt就会报找不到xxx.h -
source()方法是否把第三方源码(如 git clone 或解压 tarball)拉到了正确位置?路径不对会导致build()阶段找不到头文件 - 是否在
build()里执行了cmake.configure(),但没传source_folder参数,导致 CMake 在空目录下运行
简单验证法:打包前加一行 self.run("ls -R", run_environment=True),看实际工作目录里有没有你认为该有的文件。
Conan 的包结构是硬编码约定的,不是“CMake 怎么装它就怎么认”。哪怕你 CMakeLists.txt 写得再标准,只要 package() 没把东西塞进 include/、lib/、bin/ 这三个目录,下游就一定链不上——这点比 CMake 的 install 规则更刚性,也最容易被忽略。

















