好吧,我正在经历地狱般的尝试,试图在 Windows 上编译一个在 Linux 上很容易编译的程序,我已将其范围缩小到由 CMake 生成的单个命令,其链接器标志似乎没有执行其应有的操作.
以下是我正在执行的步骤以及出错的地方:
我通过命令行使用 MSVC 编译器,
cl.exe
:
Microsoft (R) C/C++ Optimizing Compiler Version 19.40.33812 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
和
link.exe
:
Microsoft (R) Incremental Linker Version 14.40.33812.0
Copyright (C) Microsoft Corporation. All rights reserved.
usage: LINK [options] [files] [@commandfile]
<... some more helptext down here ...>
编译一个简单的 C++ 程序,使用 SDL2 显示窗口。这是我确认编译并运行的最小可重现代码:
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include <Windows.h>
using namespace std;
int main(int argc, char **argv) {
SDL_SetMainReady();
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
return 1;
}
// Create a window
SDL_Window *window = SDL_CreateWindow("SDL2 Window",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
640, 480, SDL_WINDOW_SHOWN);
if (window == nullptr) {
SDL_Quit();
return 1;
}
// Event loop
bool isRunning = true;
SDL_Event event;
while (isRunning) {
while (SDL_PollEvent(&event) != 0) {
if (event.type == SDL_QUIT) {
isRunning = false;
}
}
}
// Cleanup
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
非常简单,没什么复杂的。
为了编译它,我运行以下命令:
cl main.cpp -I "C:/SDL2/include" /c
将程序编译为
main.obj
。 /c
标志是为了不链接它。
然后要链接,我运行
link.exe
并将路径传递到我的库,这就是出错的地方。
link.exe main.obj /LIBPATH:C:/SDL2/lib/x86/SDL2.lib
Microsoft (R) Incremental Linker Version 14.40.33812.0
Copyright (C) Microsoft Corporation. All rights reserved.
main.obj : error LNK2019: unresolved external symbol _SDL_SetMainReady referenced in function _main
main.obj : error LNK2019: unresolved external symbol _SDL_CreateWindow referenced in function _main
main.obj : error LNK2019: unresolved external symbol _SDL_DestroyWindow referenced in function _main
main.obj : error LNK2019: unresolved external symbol _SDL_PollEvent referenced in function _main
main.obj : error LNK2019: unresolved external symbol _SDL_Init referenced in function _main
main.obj : error LNK2019: unresolved external symbol _SDL_Quit referenced in function _main
main.exe : fatal error LNK1120: 6 unresolved externals
没有错误消息,什么都没有,就好像我根本没有通过库(是的,我也尝试过,但同样的错误!)
我尝试在
/VERBOSE
中运行,在搜索了 1,338 行日志后,甚至没有 SDL2.lib 提到。是的,我在提供和不提供 LIBPATH 的情况下都运行了,然后对两个生成的日志进行了差异检查,它们字面上是相同的。
奇怪的是,当我像这样运行链接器时:
link.exe main.obj /LIBPATH C:/SDL2/lib/x86/SDL2.lib
有效!它生成了一个 main.exe,运行时按预期显示一个空白的 SDL 窗口。如果您没有注意到,唯一的区别是我删除了冒号
:
并添加了一个空格。
(PS:确保在同一文件夹中包含SDL2.dll,以防您自己测试)
因此,由于某种原因,当在没有冒号和空格的情况下传递时,它会按预期工作。然而,微软自己的文档显示以下内容:
更令人困惑的是,当不带参数运行时,
link.exe
程序会说同样的事情:
/LIBPATH:dir
除非我按照它自己的说明进行操作,否则它不起作用。
所以我的问题是,为什么要这样做?这是一个错误吗?难道是我使用方法不对?
我实际上不是使用
link.exe
的人,实际上是 CMake 生成了对链接器的调用(技术上是正确的)。那么在这种情况下,为什么这个问题还没有得到解决,我可以做些什么来让 CMake 产生正确的输出吗?事实上,我在网上没有找到类似的问题,这表明我做错了什么。
是否有任何解决方法,或者我可以直接不将 CMake 与
link.exe
一起使用吗?
抱歉,如果我听起来有点歇斯底里,我已经坚持了三天,可以感觉到我的理智正在消失
/LIBPATH
选项指定要搜索库的目录,它不包括库本身的名称。库名称与链接器命令的其他输入文件一起给出。
使用给出的示例
link.exe main.obj /LIBPATH:C:/SDL2/lib/x86/SDL2.lib
应该是
link.exe main.obj SDL2.lib /LIBPATH:C:/SDL2/lib/x86
换句话说,
/LIBPATH
的操作方式与gcc的-L
选项类似。