Okay so I'm going through hell trying to compile a program on Windows that compiles quite easily on Linux and I've narrowed it down to a single command generated by CMake whose linker flag that doesn't seem to do what it's supposed to.
Here are the steps I'm doing and where it's going wrong:
I'm using MSVC compiler via the commandline, 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... ]
and 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 ...>
to compile a simple C++ program that uses SDL2 to display a Window. Here is a minimum reproducible code which I confirmed compiles and runs:
#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;
}
Pretty straightforward, nothing complicated.
To compile this, I run the following:
cl main.cpp -I "C:/SDL2/include" /c
Which compiles the program into main.obj
. The /c
flag is so that it doesn't link it.
Then to link, I run link.exe
and pass the path to my library and here's where it goes wrong.
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
No error messages, nothing, it's as if I didn't pass the library at all (and yes I tried that too but same error!)
I tried running in /VERBOSE
and after searching through the 1,338 lines of logs, nowhere is SDL2.lib even mentioned. And yes, I ran BOTH with and without the LIBPATH supplied and then diffchecked the two produced logs and they are literally the same.
Bizarrely when I instead run the linker like this:
link.exe main.obj /LIBPATH C:/SDL2/lib/x86/SDL2.lib
It works! It produced a main.exe and when run shows a blank SDL window as expected. In case you didn't notice, the only difference was me removing a colon :
and adding a space.
(PS: Make sure to include SDL2.dll in the same folder in case you're testing this on your own)
So for some reason, when passed without the colon and space, it works as expected. However, Microsoft's OWN DOCUMENTATION show the following:
And somewhat more confusingly, when run without arguments, the link.exe
program says the same exact thing:
/LIBPATH:dir
Except when I follow its own instructions, it doesn't work ðŸ˜.
So my question is, why is it doing that? Is this a bug? Am I using it incorrectly?
I'm actually not the one to use link.exe
, it's CMake that actually generates that - technically correct - call to the linker. So in that case, how come this hasn't been fixed yet and can I do something to make CMake produce the correct output? The fact that I haven't found similar questions online suggests to me that I'm doing something wrong.
Are there any workarounds or can I straight up not use CMake with link.exe
?
Sorry if I sound a bit hysterical I've been stuck on this for 3 days and can feel my sanity slipping away
The /LIBPATH
option specifies a directory to be searched for a library, it should not include the name of the library itself. Library names are given along with other input files to the linker command.
Using the example given
link.exe main.obj /LIBPATH:C:/SDL2/lib/x86/SDL2.lib
should be
link.exe main.obj SDL2.lib /LIBPATH:C:/SDL2/lib/x86
In other words /LIBPATH
operates in a similar way to the -L
option of gcc.