CMake结果dlopen“未定义符号”的不同版本要求

2024-01-10

我正在使用 g++/KDevelop/CMake(3.16.3) 进行构建。

在我放之前cmake_minimum_required( VERSION 3.0.0 )在我的 CMakeLists.txt 的第一行中,一切正常,现在我需要将其更改为cmake_minimum_required( VERSION 3.4.0 )因为其他要求。但是有了这个我可以NOT使用新的主程序加载库。

我的程序是一些小的 *.so 库作为“模块”,并且是dlopen由主程序。

头文件.hpp

#pragma once
int GetNumber();

小模块.cpp

#include "header.hpp"
extern "C" int newStrategy() {
    return GetNumber();
};

加载器.cpp

#include <dlfcn.h>
#include "header.hpp"

int GetNumber() {
    return 123;
};

bool anyError( void* pFunc ) {
    const char* err_msg = dlerror();
    if( err_msg != nullptr ) {
        lg_erro << "Error on loading:" << err_msg;
        return true;
    }
    
    if( pFunc == nullptr ) {
        lg_erro << "Error on loading:NULL ptr";
        return true;
    }
    
    return false;
};
    
using StrategyMaker_f = auto( * )()->int;
    
int main( int argc, char** args ) {
    void* pFunc = args; // any ptr not NULL
    
    // no err left before
    if( anyError( pFunc ) )
        exit( EXIT_FAILURE );
    
    auto lib_handle = dlopen( "/path/to/modules/littleModule.so", RTLD_NOW );
    if( anyError( lib_handle ) )
        exit( EXIT_FAILURE );
    
    pFunc = dlsym( lib_handle, "newStrategy" );
    if( anyError( pFunc ) )
        exit( EXIT_FAILURE );
    
    auto _mk_func = reinterpret_cast<StrategyMaker_f>( pFunc );
    lg_debg << "Success with:" << _mk_func();
    
    exit( EXIT_SUCCESS );
};

CMakeLists.txt (loader.cpp)

cmake_minimum_required( VERSION 3.0.0 )
# cmake_minimum_required( VERSION 3.4.0 )
add_executable( loader Loader.cpp
    common/log/Log2Console.cpp
    common/misc/Converts.cpp
)
target_link_libraries( loader dl )
install( TARGETS loader RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )

CMakeLists.txt (littleModule.cpp)

cmake_minimum_required( VERSION 3.0.0 )
# cmake_minimum_required( VERSION 3.4.0 ) still don't work
# add_library( littleModule SHARED littleModule.cpp )
# As @Tsyvarev's hint
add_library( littleModule MODULE littleModule.cpp )
set_target_properties( littleModule PROPERTIES
    PREFIX              ""
    OUTPUT_NAME_RELEASE littleModule
    OUTPUT_NAME_DEBUG   littleModule
    VERSION             ${PROJECT_VERSION}
)
install( TARGETS littleModule LIBRARY DESTINATION strategies )

错误输出:

加载错误:未定义符号:_Z9GetNumberv


这是政策造成的CMP0065 https://cmake.org/cmake/help/latest/policy/CMP0065.html其中指出:

3.4 版本中的新功能。

不要添加标志来从可执行文件导出符号,除非ENABLE_EXPORTS目标财产。

由于历史原因,CMake 3.3 及更低版本在某些平台上始终使用以下标志链接可执行文件-rdynamic从可执行文件中导出符号以供它们可能通过加载的任何插件使用dlopen。 CMake 3.4 及更高版本更喜欢仅对明确标记为的可执行文件执行此操作ENABLE_EXPORTS目标财产。

The OLD此策略的行为是在链接可执行文件时始终使用附加链接标志,无论ENABLE_EXPORTS目标财产。

The NEW此策略的行为是仅在链接可执行文件时使用附加链接标志(如果ENABLE_EXPORTS目标属性设置为True.

该策略是在 CMake 3.4 版本中引入的。与大多数策略不同,CMake 版本 3.24.0-rc2 确实not当未设置此策略并且仅使用时默认发出警告OLD行为。请参阅文档CMAKE_POLICY_WARNING_CMP0065变量来控制警告。

注:OLD根据定义,策略的行为已被弃用,并且可能会在 CMake 的未来版本中删除。

因此,CMake 正在按预期工作。这确实是一个合理的政策;添加此类标志会影响链接器加载库的方式,并且在实际未使用此类功能时可能会产生性能后果。

To fix your程序,写:

add_executable(loader
    Loader.cpp
    common/log/Log2Console.cpp
    common/misc/Converts.cpp
)
target_link_libraries(loader PRIVATE ${CMAKE_DL_LIBS})
set_target_properties(loader PROPERTIES ENABLE_EXPORTS TRUE)

最后一行对于您的问题很重要;它将确保可执行文件中的符号可用于动态加载的库/插件。变化自dl to ${CMAKE_DL_LIBS}是为了考虑没有单独的系统dllib 或以不同的方式命名(例如大多数 BSD,包括 macOS 和 HP-UX)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMake结果dlopen“未定义符号”的不同版本要求 的相关文章

  • 如何从 CMake 运行 .bat 文件?

    如何在预链接或构建后事件中从 CMake 运行 bat 文件 你可以使用add custom command e g if WIN32 add custom command TARGET
  • 使用 OpenCL 支持构建 OpenCV

    在 CMake 中 我使用 OpenCL Enable ON 构建了 OpenCV 它自动检测到OPENCL INCLUDE DIR路径但是OPENCL LIBRARY即使单击配置后也是空的 为了OPENCL LIBRARY我也没有看到浏览
  • Qt5 CMake 将所有库包含到可执行文件中

    我正在尝试使用 Qt 5 14 构建一个发布模式下的应用程序 并且 Qt Creator 内部一切正常 但是当我尝试单独运行可执行文件时 我收到如下错误 OS Windows 10 Qt 5 14 Cmake 3 5 我尝试过的 设置 CM
  • grpc找不到protobuf库

    我检查了 grpc 安装并完成了构建和安装 现在当我尝试 find package gRPC CONFIG REQUIRED I get CMake Error at CMakeLists txt 15 find package Found
  • 如何在 Cmake 生成的 ALL_BUILD 和 ZERO_CHECK Visual Studio 2013 项目中将 unicode 设置为字符集?

    我目前正在使用 CMake 创建一堆 Visual Studio 2013 项目 并且它可以工作 但是 自动创建的 ZERO CHECK 和 ALL BUILD 项目默认设置为使用 MBCS 尽管我希望它们使用 Unicode 字符集 我确
  • 从不同的程序集中动态加载类(具有自定义行为)?

    我们正在为少数客户构建应用程序 每个客户都有自己的要求以及类似的要求 我们还希望将所有代码保留在同一个应用程序中 而不是对其进行分支 并且 IF 不是一个好的选择 因为它会遍布各处 我计划为所有人开设基础课程 然后每个客户都会有自己的类 其
  • 将 cmake 与自定义文件生成器结合使用

    我想使用 CMake 生成混淆的 lua 文件以供交付 在我的一生中 我无法让 add custom command add custom target 为我构建这些文件 我缺少一些东西 ADD CUSTOM TARGET LUABIND
  • 使用动态链接器包装 glibc 函数

    我正在尝试包装 GLIBCfstat通过将我的库注入可执行文件来实现函数 可以是任何其他 这只是概念证明 我通过将我的库放置在可执行文件的位置来做到这一点RPATH用名字指着libc so 6 我的库的源代码如下 define GNU SO
  • 来自库的 CMake link_directories

    我正在尝试使用 CMake 和 Xcode 从另一个库链接到一个库 这对任何图书馆来说都是一个问题 但为了让事情更容易传达 让我们使用zlib举个例子 这似乎适用于可执行文件 如下所示 LINK DIRECTORIES LIB DIR zl
  • clang-tidy - 忽略第三方标头代码

    我正在为我的项目使用 CMake 并且我想向项目引入 clang tidy 检查 我用于此目的CMAKE CXX CLANG TIDY and clang tidy用于检查设置的文件 我想在 CI 中使用警告作为错误来可靠地检查提交是否引入
  • 修改编译共享库中符号的可见性

    我的项目依赖于一个第三方库 该库导出了更多应有的符号 其中一些符号被其他库和主程序无意地覆盖 如何更改已编译共享对象的函数和变量的可见性 如何更改已编译共享对象的函数和变量的可见性 您可以通过修改动态符号部分来更改符号的可见性 dynsym
  • 编译器 libstdc++ 版本与系统版本

    我试图了解 g 如何选择它链接的 libstdc 版本 以及当库的 系统 版本不同时它意味着什么 我正在使用 gcc g 4 1 2 根据ABI 指南 http gcc gnu org onlinedocs libstdc manual a
  • C++ 将枚举值捕获为异常

    我正在尝试使用external C 库将其异常定义为 enum MY ERRORS ERR NONE 0 ERR T1 ERR T2 然后在代码中抛出异常是这样的 if throw ERR T1 作为 C 编程新手 我会这样做 try ca
  • CMake:如何将 .def 文件添加到 Visual Studio 项目过滤器?

    如何将 def 文件添加到 Visual Studio 项目过滤器 filters文件 Visual Studio 使用 def 文件 CMake代码 set a src a cpp a def add library a SHARED a
  • MySQL C++ 连接器未解决的依赖关系(VS 2015)

    我正在尝试在 Windows Visual Studio 2015 上编译 MySQL Connector C 我根据以下内容使用CMake生成了项目文件官方说明 https dev mysql com doc connector cpp
  • 无法在 Visual Studio 和 vcpkg 中构建 cmake 项目(致命错误 C1083)

    我今天安装了vcpkg 启用了与Visual Studio的集成 即 vcpkg集成安装 并开始安装库 我基本上安装了 cpprestsdk 并触发了 boost 库的安装 然后我在 Visual Studio CMake 中打开该项目 当
  • CMake 中的 FindSDL2 发生了什么?

    我在游戏中使用 SDL2 我一直使用自定义 FindSDL2 cmake 因为标准 CMake 集中没有 然而 前段时间确实出现了有关 FindSDL2 的帖子 例子 红迪网帖子 https www reddit com r opengl
  • 如何在Android studio中调用.so库上的方法

    编辑 请参阅我的第一个答案 我想在我的项目中使用 android 串口 api 我这样做有很多麻烦 关于如何配置旧版本的 gradle 或如何使用 NDK 进行编译 存在大量相互冲突的信息 而这两者都没有用 我完全迷失了 我发现唯一可能正确
  • 如何在 C++ 项目的 Cmake 文件上添加 Mac OS 框架

    我正在尝试将外部库 Vulkan 添加到我的项目中 这个库是预编译的并且有一个框架 我的项目树 build source Entry main cpp include ext vulkan macos include lib Framewo
  • 如何将 LC_LOAD_DYLIB 命令插入 Mach-O 二进制文件或将静态库加入现有二进制文件 (IOS)

    这是我第一次在 stackoverflow 上提问 我很绝望 我的任务是加载 dylib 或将静态库加入到 IOS 设备的现有可执行文件中 我将使用static void attribute constructor initialize v

随机推荐