You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开发rowen.so动态库:未链接jsoncpp无报错、链接后无法检测依赖的问题

关于rowen共享库与jsoncpp链接的问题

我正在开发名为“rowen”的so文件,库内包含一个封装jsoncpp部分功能的json相关模块(路径为Libs/json/json.cpp)。


Q1:在print函数中调用jsoncpp的write接口,但未链接jsoncpp时并未出现报错,原因是什么?

相关代码

json.hpp

#include <jsoncpp/json/json.h>

namespace Json
{
    inline void print(Json::Value& __param, std::string __title);
}

json.cpp

namespace Json
{
    void print(Json::Value& __param, std::string __title)
    {
        Json::StyledWriter style_writer;
        std::string output = style_writer.write(__param);
        printf("=========== %s ===========================\n", __title.c_str());
        printf("%s\n", output.c_str());
    }
}

CMake配置片段

根目录CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(Rowen-Libraries)

set(rowenSources )

# set libraries (default)
include(Libs/core/import.cmake)

# set libraries (optional)
OPTION(ENABLE_JSON      "Enable Json Wrapping Library"      ON)

if (ENABLE_JSON)
include(Libs/json/import.cmake)
endif()

# build shared libraries
add_library(rowen SHARED ${rowenSources})

Libs/json/import.cmake

insert(${CMAKE_CURRENT_LIST_DIR}/json.hpp) # include to rowenIncludes
insert(${CMAKE_CURRENT_LIST_DIR}/json.inl) # include to rowenIncludes
insert(${CMAKE_CURRENT_LIST_DIR}/json.cpp) # include to rowenSources

# Check for pkg-config
find_package(PkgConfig REQUIRED)
pkg_check_modules(JSONCPP REQUIRED jsoncpp)
link_libraries(${JSONCPP_LIBRARIES})  # ${JSONCPP_LIBRARIES} print "jsoncpp"

原因分析

  1. 编译阶段仅需函数声明:编译器只需要头文件中提供的Json::StyledWriter::write函数声明就能通过编译,不检查实际实现是否存在,因此编译生成目标文件时不会报错。
  2. 共享库默认允许未定义符号:构建共享库(.so)时,链接器默认采用延迟绑定(lazy binding)策略,不会强制检查所有符号的存在性,仅在运行时实际调用该函数时才会解析符号。如果测试过程中没有调用print函数,或者未开启-Wl,--no-undefined这类强制检查未定义符号的选项,链接阶段就不会报错。

Q2:已配置链接jsoncpp,但通过ldd、nm等工具无法检测到该依赖,原因是什么?如何让librowen.so必须依赖libjsoncpp才能使用?

相关命令执行结果

$ ldd librowen.so 
        linux-vdso.so.1 (0x0000007fb750f000)
        libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000007fb745a000)
        libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007fb72c6000)
        libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007fb72a2000)
        libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000007fb7149000)
        /lib/ld-linux-aarch64.so.1 (0x0000007fb74e3000)
        libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000007fb7090000)

$ nm -D librowen.so | grep jsoncpp        # 无输出
$ objdump -T librowen.so | grep jsoncpp   # 无输出

原因分析

  1. CMake链接命令作用时机错误:全局link_libraries命令的作用可靠性低于目标专属的target_link_libraries,且当前CMakeLists中目标创建与模块导入的顺序可能导致链接配置未正确作用于rowen库。
  2. 未被引用的符号被优化移除:如果Json::print函数没有被librowen.so的其他代码引用,且开启了链接时优化(LTO),编译器会将这个未被使用的函数整个移除,导致jsoncpp的符号没有被引用,链接器也就不会将libjsoncpp添加为依赖。
  3. json.cpp未被正确编译进库:如果insert函数没有正确将json.cpp路径加入rowenSources变量,该文件不会被编译进librowen.so,自然不会产生对jsoncpp的依赖。

解决方法

  1. 改用目标专属链接命令:替换全局link_libraries为CMake推荐的target_link_libraries,确保链接配置仅作用于rowen目标:
    • 调整根目录CMakeLists.txt顺序,先创建目标再导入json模块:
      cmake_minimum_required(VERSION 3.20)
      project(Rowen-Libraries)
      
      set(rowenSources )
      
      # set libraries (default)
      include(Libs/core/import.cmake)
      
      # build shared libraries
      add_library(rowen SHARED ${rowenSources})
      
      # set libraries (optional)
      OPTION(ENABLE_JSON      "Enable Json Wrapping Library"      ON)
      
      if (ENABLE_JSON)
      include(Libs/json/import.cmake)
      endif()
      
    • 修改Libs/json/import.cmake中的链接命令:
      # 替换原link_libraries行
      target_link_libraries(rowen PRIVATE ${JSONCPP_LIBRARIES})
      
  2. 验证jsoncpp代码是否被编译进库:在CMake中添加日志验证rowenSources是否包含json.cpp:
    message(STATUS "rowenSources content: ${rowenSources}")
    
    若未包含,检查insert函数的实现是否正确将文件路径添加到变量中。
  3. 强制保留未被引用的符号:如果print函数未被其他代码引用导致被优化,可在函数声明中添加__attribute__((used))标记强制保留:
    namespace Json
    {
        __attribute__((used))
        void print(Json::Value& __param, std::string __title)
        {
            // 原函数代码
        }
    }
    
  4. 验证动态依赖:使用readelf -d librowen.so查看动态段,确认是否存在NEEDED条目指向libjsoncpp.so。如果配置正确,该条目会被自动添加。

内容的提问来源于stack exchange,提问作者mystes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 09:22:55