【问题标题】:CMake shared dll not working after compiling编译后 CMake 共享 dll 不起作用
【发布时间】:2021-05-02 17:31:06
【问题描述】:

我最近刚从使用 Visual Studio 切换到 CLion,因为我发现它更容易工作。我最大的问题是我对 CMake 的工作原理以及为什么一个非常简单的项目不适合我一无所知。

我有一个非常小的项目,它为 Windows 制作了一个 .dll 文件——它只有几行加上我机器上某个 API 库的链接。这是 CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.17)
project(pushpull)

set(CMAKE_CXX_STANDARD 14)

set(API_SRC_Files  "D:/Work/API_SRC_Files")
include_directories(
        .
        ${API_SRC_Files}
        ${API_SRC_Files}/Core

)

add_library(pushpull SHARED CPushPull.cpp CPushPull.h PushPull.cpp)

没有警告或错误,编译似乎成功:

[100%] Linking CXX shared library pushpull.dll
   Creating library pushpull.lib and object pushpull.exp
   Creating library pushpull.lib and object pushpull.exp
[100%] Built target pushpull

Build finished

但是,当我去加载 .dll 时,它无法正常工作,并且我从该 .dll 的程序中收到“无法加载”类型的警告。

我使用 windows 和 Visual Studio 作为工具链。

我的怀疑与编译器标志有关,因为我知道在 linux 上使用 gcc 时我需要添加 -fPIC 所以我尝试添加:

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

但这并没有什么不同。

我也试过了:

if(MSVC)
    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
    set(BUILD_SHARED_LIBS TRUE)
endif()

再一次,虽然一切都编译得很好,但仍然无法加载。

我知道我一定遗漏了一些东西,很可能是在 CMakeLists 文件而不是项目设置中,因为如果我只是打开 Visual Studio 在那里创建一个空的 dll 项目并添加这些文件,一切都会完美运行。

帮助表示赞赏。

更新

正如 cmets 中提到的,错误消息是模糊的 - 就是这样,但仅此而已。它希望始终能够加载 dll,所以当它不能加载时,它只会说“无法加载 %NAME%”。

如下所示,我可能没有正确链接 VS 自动执行的库,因此我尝试与 VS 项目模板中提到的所有库进行链接:

target_link_libraries(pushpull kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib)

但这也行不通。值得注意的是,CMake dll 只有 71kb,而 VS 是 73kb。有什么东西被遗漏了吗?

【问题讨论】:

  • 确保dll在程序目录中或者将dll目录添加到path环境变量中。
  • 与位置无关的代码仅对您想要链接到 dll 的静态库很重要。对于 dll,您不需要它。 BUILD_SHARED_LIBS 仅与您未在 add_library 中设置类型的库相关。顺便说一句:运行程序时是工作目录中的dll还是路径环境var?路径/工作目录中的程序和 dll 也是 32 位还是 64 位?
  • 是的,.dll 位于正确的工作目录中。它与从 VS(有效)构建的位置相同,但名称不同。
  • '我从该 .dll 的程序中收到“无法加载”类型的警告。' - 相当模糊的描述。请显示(添加到问题帖子中)您收到的确切错误消息
  • 是的,它非常模糊,但仅此而已。当 dll 文件不起作用时,它会简单地抛出该消息。除了 CLIon 中 CMake 编译的 dll 不起作用,而使用 Visual Studio 从完全相同的文件编译的 dll 之外,没有什么需要特别注意的。

标签: c++ windows cmake clion


【解决方案1】:

cmake 中创建DLL 类似于创建可执行文件! 您必须通过SHARED 标志和代码文件列表调用add_library!和你一样!

接下来你必须在add_library 命令之后调用target_link_libraries 并引入要链接的库!我在您的帖子中没有看到target_link_libraries

如果两者都做,请仔细检查日志,您会发现问题。

【讨论】:

  • 我在链接什么? pushpull 是 dll 并且已经编译成功。 target_link_libraries(pushpull pushpull.lib pushpull.exp) ?
  • 您可以查看 Visual Studio 链接部分并查看链接了哪些库!所有这些都必须由“target_link_libraries”添加,例如 target_link_libraries(pushpull kernel32.lib user32.lib)
  • 没有自动的方法吗?我可以将大约 10 或 15 个库的列表复制到 target_link_libraries() 中,它应该可以工作吗?
  • 不! VS IDE 会自动为默认库执行此操作!如user32.lib,自定义库必须手动提及!但在 cmake 中,您必须手动执行此操作!库文件的数量无关紧要!
  • 我已经包含了默认 VS 项目模板中提到的每个库,但这仍然不能使 dll 工作。 target_link_libraries(pushpull kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib)。显然还有其他东西需要设置。我知道为什么人们不从 VS 切换 - 至少它有效!
猜你喜欢
  • 1970-01-01
  • 2018-03-06
  • 2021-08-15
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-07
相关资源
最近更新 更多