创建并使用Conan包时遇问题:库目录未设置
问题:Conan包hjson库目录未同步导致链接失败
问题背景
为第三方工具hjson创建了Conan包,执行conan create .成功部署到~/.conan目录,但测试使用时链接器找不到库。查看生成的hjson-config.cmake发现hjson_LIB_DIRS未设置,尽管已在包的package_info中配置了cpp_info.libdirs。
相关代码
1. hjson的conanfile.py
class HjsonConan(ConanFile): name = "hjson" version = "2.2" url = "https://github.com/hjson/hjson-cpp" license="MIT" # Optional metadata description = "hjson C++ json library" # Binary configuration settings = "os", "compiler", "build_type", "arch" options = {"shared": [True, False], "fPIC": [True, False], "version": "ANY"} default_options = {"shared": False, "fPIC": True, "version": "2.2"} # Sources are located in the same place as this recipe, copy them to the recipe exports_sources = ("hjson-src/*") def source(self): # unpacks into ./hjson-src get(self, f"https://github.com/hjson/hjson-cpp/archive/refs/tags/{self.options.version}.tar.gz", destination='hjson-src', strip_root=True) def config_options(self): if self.settings.os == "Windows": del self.options.fPIC def layout(self): # Sets source=., build=build/Release, generators=build/generators cmake_layout(self) def generate(self): tc = CMakeToolchain(self) # Here is where to set CMake variables ("-DXYZ") tc.variables["HJSON_ENABLE_INSTALL"] = 1 tc.generate() def build(self): cmake = CMake(self) cmake.configure(build_script_folder='hjson-src') cmake.build() def package(self): cmake = CMake(self) cmake.install() def package_info(self): self.cpp_info.libs = ["hjson"] # these are the defaults, here for clarity self.cpp_info.includedirs = ["include"] self.cpp_info.libdirs = ["lib"]
2. 测试用的conanfile.py
from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout from conan.tools.build import cross_building class HJsonTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" # VirtualBuildEnv and VirtualRunEnv can be avoided if "tools.env.virtualenv:auto_use" is defined # (it will be defined in Conan 2.0) generators = "CMakeDeps", "CMakeToolchain", "VirtualBuildEnv", "VirtualRunEnv" apply_env = False test_type = "explicit" def requirements(self): self.requires("hjson/2.2") def build(self): cmake = CMake(self) cmake.configure() cmake.build() def layout(self): cmake_layout(self) def test(self): if not cross_building(self): cmd = os.path.join(self.cpp.build.bindirs[0], "example") self.run(cmd, env="conanrun")
3. 测试用CMakeLists.txt
cmake_minimum_required(VERSION 3.15) project(PackageTest CXX) find_package(hjson CONFIG REQUIRED) add_executable(example src/example.cpp) set_property(TARGET example PROPERTY CXX_STANDARD 20) include_directories(${hjson_INCLUDE_DIRS}) link_directories(${hjson_LIB_DIRS}) target_link_libraries(example hjson)
生成的hjson-config.cmake内容
set(hjson_VERSION_STRING "2.2") set(hjson_INCLUDE_DIRS ${hjson_INCLUDE_DIRS_RELEASE} ) set(hjson_INCLUDE_DIR ${hjson_INCLUDE_DIRS_RELEASE} ) set(hjson_LIBRARIES ${hjson_LIBRARIES_RELEASE} ) set(hjson_DEFINITIONS ${hjson_DEFINITIONS_RELEASE} )
Conan包结构
~/.conan/data/hjson/2.2/_/_/package/37c9d02f...91ef ├── conaninfo.txt ├── conanmanifest.txt ├── include │ └── hjson │ └── hjson.h └── lib ├── hjson │ ├── hjson-config-version.cmake │ ├── hjson-config.cmake │ ├── hjson-release.cmake │ └── hjson.cmake └── libhjson.a
原因分析与解决方法
核心原因
问题出在测试工程优先使用了hjson官方自带的CMake配置文件,而非Conan生成的CMakeDeps配置。执行cmake.install()时,hjson源码自带的hjson-config.cmake会被安装到包的lib/hjson目录,当测试工程执行find_package(hjson CONFIG REQUIRED)时,会优先加载这个官方配置,而官方配置里没有定义hjson_LIB_DIRS变量。
解决步骤
方案1:修改测试工程CMakeLists.txt(推荐,符合现代CMake实践)
官方hjson的CMake配置已经提供了hjson::hjson目标,无需手动设置头文件和库路径,直接链接目标即可:
cmake_minimum_required(VERSION 3.15) project(PackageTest CXX) find_package(hjson CONFIG REQUIRED) add_executable(example src/example.cpp) set_property(TARGET example PROPERTY CXX_STANDARD 20) # 直接链接官方提供的目标,自动处理头文件和库路径 target_link_libraries(example PRIVATE hjson::hjson)
方案2:禁用官方CMake配置文件安装,使用Conan生成的配置
修改conanfile.py的generate方法,添加禁用官方CMake配置安装的参数:
def generate(self): tc = CMakeToolchain(self) tc.variables["HJSON_ENABLE_INSTALL"] = 1 # 禁用安装官方CMake配置文件,避免干扰Conan的CMakeDeps tc.variables["HJSON_INSTALL_CMAKE_CONFIG"] = 0 tc.generate()
重新执行conan create .创建包,此时Conan会生成包含正确hjson_LIB_DIRS的配置文件,原测试工程的CMakeLists.txt可正常使用。
备选方案:手动删除官方CMake配置文件
如果hjson源码没有HJSON_INSTALL_CMAKE_CONFIG选项,可在package步骤中删除安装的官方配置:
def package(self): cmake = CMake(self) cmake.install() # 删除官方安装的CMake配置目录 import shutil shutil.rmtree(os.path.join(self.package_folder, "lib", "hjson"))
内容的提问来源于stack exchange,提问作者GaryO
相关产品推荐
相关产品推荐

