【发布时间】: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 之外,没有什么需要特别注意的。