【C++/CMake】从静态库到动态库:一行改动解决 “找不到 -ljsoncpp” 链接报错

1. 前言

在使用 CMake 构建 C++ 项目时,链接第三方库往往会碰到一些"链接失败"的问题,尤其在 Linux 环境下比较常见。最近我在编译一个涉及 JSON 解析功能的项目时,遇到如下错误:

bash 复制代码
/usr/bin/ld: 找不到 -ljsoncpp: 没有那个文件或目录
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/run_intrinsic_calibration.dir/build.make:113: ../bin/run_intrinsic_calibration] 错误 1
make[1]: *** [CMakeFiles/Makefile2:111: CMakeFiles/run_intrinsic_calibration.dir/all] 错误 2
make: *** [Makefile:91: all] 错误 2

很明显,链接器找不到 jsoncpp 相关的库文件。通过在 CMakeLists.txt 中把对 jsoncpp.a 的静态库链接改成链接 jsoncpp.so(动态库),最终成功解决了问题。本文就把这个过程分享给大家,供遇到类似问题的同学参考。


2. 问题背景

在项目的 CMakeLists.txt 中,原先有这样的链接语句:

cmake 复制代码
target_link_libraries(
    ${PROJECT_NAME}
    jsoncpp.a
    ${OpenCV_LIBS}
    ${Boost_SYSTEM_LIBRARY}
)

这表示显式地去链接名为 jsoncpp.a 的静态库。但是在实际环境中,系统安装的只是 libjsoncpp.so(动态库),并不存在对应的 jsoncpp.a(静态库)。因此,链接器自然找不到 jsoncpp.a 文件,就会报类似 "找不到 -ljsoncpp" 或 "无法打开 jsoncpp.a" 这样的错误。

2.1 为什么只安装了 .so 而没有 .a

在大多数 Linux 发行版上,默认安装的 libjsoncpp-dev(或同名开发包)只会提供共享库(libjsoncpp.so)和头文件,而不一定会提供静态库(libjsoncpp.a)。这是因为静态库往往需要额外维护,并且在普通场景中使用动态库更方便、可维护性更高。


3. 解决思路

要想解决这个报错,无非两种方案:

  1. 改用动态库:如果只是想让项目能正常编译和运行,直接链接动态库就可以了。
  2. 自行安装/编译静态库 :如果明确需要静态链接(比如某些嵌入式场景、需要单文件发布等),就得手动编译并安装 jsoncpp.a

在这里,我的需求只是能让程序正常编译、运行,不依赖完全的静态链接。因此,选择了 最简单的 方案 ------ 把 ".a" 改成 ".so" ,或者更常见的是 直接写 "jsoncpp" 让 CMake 自动去查找共享库和头文件。


4. 改动一行,链接成功

我只需要在 CMakeLists.txt 中,把原先的

cmake 复制代码
target_link_libraries(
    ${PROJECT_NAME}
    jsoncpp.a
    ${OpenCV_LIBS}
    ${Boost_SYSTEM_LIBRARY}
)

改成:

cmake 复制代码
target_link_libraries(
    ${PROJECT_NAME}
    jsoncpp.so
    ${OpenCV_LIBS}
    ${Boost_SYSTEM_LIBRARY}
)

或者:

cmake 复制代码
target_link_libraries(
    ${PROJECT_NAME}
    jsoncpp
    ${OpenCV_LIBS}
    ${Boost_SYSTEM_LIBRARY}
)

然后重新 cmake .. && make -j,就可以看到编译顺利通过。因为系统在 /usr/lib/x86_64-linux-gnu/ (不同发行版可能略有差异)下找到了 libjsoncpp.so 这个文件,满足了链接要求。


5. 动态库与静态库的区别

简单科普一下:

  • 动态库(.so :程序运行时需要依赖外部的共享库文件,升级库时不需要重新编译所有应用,发布体积小,但需要在环境中保留 .so 文件。
  • 静态库(.a:编译时将第三方库的代码直接打包进可执行文件,发布时无需再携带库文件,更独立,但是体积变大,且若库有更新,需要重新编译可执行文件。

常见情况下,如果你没有特殊需求,使用动态库更方便。


6. 总结

  • 问题核心 :CMake 链接阶段找不到 jsoncpp.a,因为系统并没有安装静态库。
  • 解决方法 :直接改用已经安装的动态库 jsoncpp.so,或者在链接指令里只写 jsoncpp 让 CMake 自动匹配到共享库。
  • 经验教训
    1. 安装 libjsoncpp-dev 一类的开发包后,大多数情况下只会得到 .so 文件而不是 .a 文件。
    2. 如果想要静态库 .a,通常要自己编译或者额外安装静态库包。
    3. 若非必要,动态库 .so 更常用。

希望这篇文章对同样遇到 "找不到 -ljsoncpp" 链接错误的朋友有所帮助。如果对你有用,欢迎点赞、收藏或关注。我们下篇文章再见!

参考gpt sharehttps://chatgpt.com/share/67760c04-d638-8010-84a6-9bcaa52e5144

相关推荐
w36250126631 分钟前
Java NIO
java·开发语言·nio
叫我阿呆就好了1 小时前
C 实现植物大战僵尸(四)
c语言·开发语言
xianwu5432 小时前
cpp编译链接等
linux·开发语言·网络·c++·git
懒大王爱吃狼2 小时前
Python基于wordcloud库绘制词云图
开发语言·python·学习·python基础·python学习
wjs20242 小时前
Ruby 中文编码
开发语言
山语山2 小时前
C#多线程精解
开发语言·数据库·后端·c#
froginwe112 小时前
SQLite AND/OR 运算符
开发语言
我是唐青枫3 小时前
C# Lambda 表达式详解
开发语言·c#·.net
CharlesC++3 小时前
JAVA类和对象练习
java·开发语言
huluang3 小时前
构建JS全栈开发的CMS系统——从零开始搭建前后端
开发语言·javascript·ecmascript