不能,find_package默认查找库的接口定义而非静态/动态形态;Conan生成的Config.cmake根据安装选项决定暴露静态或动态target,需显式设shared=False并验证IMPORTED_LOCATION指向.a文件。

find_package 能直接找到静态库吗
不能,默认情况下 find_package 找到的是库的“接口定义”,不是静态/动态形态本身。Conan 生成的 xxxConfig.cmake(比如 fmtConfig.cmake)里会根据你安装时的构建配置,决定暴露 fmt::fmt 是链接静态库还是动态库——这取决于 Conan 包本身的 package_id 策略和你 conan install 时的 -s build_type=Release、-o shared=False 等设置。
关键点在于:Conan 不控制 CMake 如何链接,它只提供可被 find_package 消费的 target;最终链接静态还是动态,由 Conan 包作者在 package() 和 cpp_info.libs 中声明,以及你在 conanfile.py 或 conanfile.txt 中传入的选项共同决定。
如何确保链接的是静态库
必须显式开启静态构建选项,并确认包支持该模式。常见错误是以为只要 find_package(xxx REQUIRED) 就自动静态链接,其实默认可能走动态路径。
-
conan install . --build=missing -o xxx:shared=False:对每个依赖加-o :shared=False,强制其构建/使用静态版本(前提是该包支持此选项,如fmt、spdlog默认支持,openssl则需额外指定no_shared) - 在
conanfile.py的requirements()或configure()中写死:def configure(self): self.options["fmt"].shared = False self.options["spdlog"].shared = False - 检查生成的
xxxTargets.cmake文件(通常在build/conan/xxx/xxxTargets.cmake),搜索IMPORTED_LOCATION或IMPORTED_LOCATION_RELEASE,确认路径指向的是.a文件而非.so或.dll
CMakeLists.txt 里怎么写才不踩坑
很多人在 target_link_libraries() 后发现链接失败或运行时报 undefined symbol,问题常出在头文件路径、依赖顺序或隐式依赖缺失上。
正确写法示例(Conan 2.x + CMakeDeps):
cmake_minimum_required(VERSION 3.15)
project(myapp LANGUAGES CXX)
<h1>必须先加载 Conan 工具链,再 find_package</h1><p>include(${CMAKE_BINARY_DIR}/conan_toolchain.cmake)</p><p>find_package(fmt REQUIRED CONFIG)
find_package(spdlog REQUIRED CONFIG)</p><p>add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt spdlog::spdlog)</p><h1>静态库依赖常需额外链接系统库(如 pthread、dl)</h1><p>target_link_libraries(myapp PRIVATE ${CMAKE_DL_LIBS} pthread)注意几个硬性要求:
-
include(${CMAKE_BINARY_DIR}/conan_toolchain.cmake)必须在find_package()之前,否则 CMake 不知道去哪里找fmtConfig.cmake - 不要手动
target_include_directories(... PUBLIC ${CONAN_INCLUDE_DIRS_FMT})—— Conan 2.x 的CMakeDeps已通过INTERFACE_INCLUDE_DIRECTORIES自动注入 - 如果依赖链中有 header-only 库(如
nlohmann_json),它不会生成.a,但find_package(nlohmann_json REQUIRED)依然有效,只是不参与链接阶段
install 后静态库文件去哪儿了
Conan 安装后的静态库不会落到你的项目目录,而是存于 Conan 本地缓存(如 ~/.conan2/p/fmt/...),CMake 通过 IMPORTED_LOCATION 属性间接引用。你不需要、也不应该手动 install(TARGETS ... ARCHIVE DESTINATION ...) 这些 Conan 提供的库。
真正需要你 install 的,是你自己的 target:
install(TARGETS myapp RUNTIME DESTINATION bin # 不要试图 install(fmt::fmt) —— 它不是你的 target,且 Conan 已管理其部署逻辑 )
容易忽略的一点:如果你把项目打包成 SDK 或分发给他人,必须同时提供 Conan lockfile(conan.lock)和 conanfile.py,否则对方无法复现相同的静态链接行为——尤其是当某个依赖在不同平台下默认构建策略不一致时(比如 Windows 下 zlib 可能默认用 DLL,Linux 下默认静态)。


















