如何在项目子目录中正确集成jsoncpp并解决编译头文件缺失错误
问题描述
我的项目目录结构如下:
WeaselTestApp --build ... --weasel ... --CMakeLists.txt --main.cpp --CMakeLists.txt --conanfile.txt
根目录CMakeLists.txt内容:
cmake_minimum_required(VERSION 3.16) project(WeaselTestApp LANGUAGES CXX) add_executable(WeaselTestApp main.cpp) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) enable_testing() add_subdirectory(weasel) target_link_libraries(WeaselTestApp PRIVATE Weasel)
weasel子目录的CMakeLists.txt内容:
add_library(Weasel Utils.cpp HttpMethod.cpp HttpStatus.cpp Request.cpp Response.cpp Router.cpp Server.cpp) include_directories(${CONAN_INCLUDE_DIRS_JSONCPP}) set(jsoncpp_DIR "/home/emmanuel/weasle/build") find_package(jsoncpp REQUIRED) target_link_libraries(Weasel PRIVATE jsoncpp)
根目录conanfile.txt内容:
[requires] jsoncpp/1.9.5 gtest/1.11.0 [generators] CMakeDeps CMakeToolchain cmake_find_package
运行cmake --build /home/user/weasle/build时出现编译错误:
[ 10%] Building CXX object weasel/CMakeFiles/Weasel.dir/Utils.cpp.o [ 20%] Building CXX object weasel/CMakeFiles/Weasel.dir/HttpMethod.cpp.o [ 30%] Building CXX object weasel/CMakeFiles/Weasel.dir/HttpStatus.cpp.o [ 40%] Building CXX object weasel/CMakeFiles/Weasel.dir/Request.cpp.o In file included from /home/user/weasle/weasel/Request.cpp:1: /home/user/weasle/weasel/Request.h:5:10: fatal error: json/json.h: No such file or directory 5 | #include <json/json.h> | ^~~~~~~~~~~~~ compilation terminated. gmake[2]: *** [weasel/CMakeFiles/Weasel.dir/build.make:118: weasel/CMakeFiles/Weasel.dir/Request.cpp.o] Error 1 gmake[1]: *** [CMakeFiles/Makefile2:126: weasel/CMakeFiles/Weasel.dir/all] Error 2 gmake: *** [Makefile:101: all] Error 2
我计划将来把weasel目录做成独立包,因此不想在根目录CMake中处理jsoncpp,请问如何在项目中正确使用jsoncpp?
解决方案
1. 修正Weasel子目录的CMake配置
核心是移除硬编码路径,使用Conan生成的标准化配置,并用目标级设置替代全局设置:
修改weasel/CMakeLists.txt为:
add_library(Weasel Utils.cpp HttpMethod.cpp HttpStatus.cpp Request.cpp Response.cpp Router.cpp Server.cpp) # 依赖Conan生成的CMakeDeps配置自动查找jsoncpp,无需硬编码路径 find_package(jsoncpp REQUIRED) # 仅给Weasel目标添加jsoncpp的包含路径,避免污染全局环境 target_include_directories(Weasel PRIVATE ${jsoncpp_INCLUDE_DIRS}) # 使用Conan生成的命名空间目标链接jsoncpp(官方推荐的标准化写法) target_link_libraries(Weasel PRIVATE jsoncpp::jsoncpp)
2. 执行正确的编译流程
编译前必须先在build目录完成Conan依赖安装,生成正确的依赖配置文件:
cd /home/user/weasle/build conan install .. --build=missing cmake .. cmake --build .
3. 为Weasel独立成包提前适配
如果将来要把Weasel做成独立CMake包,可在weasel/CMakeLists.txt末尾添加以下配置(用于生成包的元配置文件):
include(CMakePackageConfigHelpers) write_basic_package_version_file( WeaselConfigVersion.cmake VERSION 0.1.0 COMPATIBILITY SameMajorVersion ) install(TARGETS Weasel EXPORT WeaselTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include ) install(EXPORT WeaselTargets FILE WeaselTargets.cmake NAMESPACE Weasel:: DESTINATION lib/cmake/Weasel ) # 需在weasel目录下新建WeaselConfig.cmake文件,内容见下方 install(FILES "${CMAKE_CURRENT_BINARY_DIR}/WeaselConfigVersion.cmake" WeaselConfig.cmake DESTINATION lib/cmake/Weasel )
同时在weasel目录下创建WeaselConfig.cmake,内容:
include(CMakeFindDependencyMacro) # 当Weasel作为独立包被引入时,自动查找依赖的jsoncpp find_dependency(jsoncpp REQUIRED) include("${CMAKE_CURRENT_LIST_DIR}/WeaselTargets.cmake")
错误原因说明
- 硬编码
jsoncpp_DIR会导致路径适配问题,Conan的CMakeDeps生成器已经会自动配置依赖路径,无需手动指定。 - 全局的
include_directories不如目标级别的target_include_directories灵活,后者只会影响Weasel自身,符合模块化要求。 - 直接链接
jsoncpp而非jsoncpp::jsoncpp不符合Conan的标准化目标命名规则,后者是Conan生成的官方推荐目标。
内容的提问来源于stack exchange,提问作者Emmanuel Amodu
相关产品推荐
相关产品推荐

