undefined reference to WinMain@16 C++, SDL-2
Asked Answered
N

2

15

I've been getting the error undefined reference to WinMain@16. To save space, here's a link to all the files currently in the project. At present, it shouldn't do much other than create a window, fill it in green and then draw a box in the corner, all the while tracking my mouse's position through the console. However, it won't build and I'm given the aforementioned error.

My linker libraries are:

  • glew32s
  • libSDL2main
  • mingw32
  • libSDL2
  • opengl32
  • glew32

I am using Codeblocks 13.12 with g++ following the C++11 ISO C++ language standard. My PC is using windows 10 in case that's relevant.

I've spent quite a while trying to find a solution and it seems everyone has an entirely different one, and so far none of them have worked for me. A few examples include:

  • Adding SDL2_image to my link libraries in accordance with this similar question. It gave me the error -lSDL2_image.
  • Starting the project entirely from scratch in case some typo I failed to notice was the cause. (I got exactly the same error).
  • Changing my main function to WinMain. I got the same error message.
  • Adding a Windows.h header. This did nothing noticeable.
  • Various alleged "right orders" for my liker libraries. None of those have seemed to help thus far.

I should also point out that the answer provide by the user, Cheers and hth. - Alf, here might be what I'm looking for, but in all honesty I can't fully understand what I'm supposed to do in based on it.

If there's any relevant information that I forgot to include, please tell me and I'll do so as soon as possible. Thanks in advance.

Norton answered 1/9, 2015 at 23:13 Comment(2)
Possible duplicate of #12574316Fusillade
Try #undef main at the beginning of main.cppTomkins
L
32

I think you want

#define SDL_MAIN_HANDLED

in your main file, BEFORE the line

#include <SDL2/SDL.h>

Explanation:

In SDL / SDL2, in an effort to try to make cross-platform development of certain kinds of applications simpler, SDL creates a custom "entry-point" to your application. That is, your int main() is not the real main. What happens is, main is defined as a macro in the SDL header and this causes your main to be renamed to SDL_main or similar. Then, in the "SDL_main" library a different main is defined which will be the real main of your application. This main just fetches the command-line arguments in whatever way is appropriate for the platform, and calls your main (which was renamed SDL_main).

On windows, there are also some differences regarding whether your application is started as a console program vs. as a gui program, iiuc.

Sometimes you want SDL to do these things for you, but if you are developing a traditional console program, usually you don't. So you pass SDL this SDL_MAIN_HANDLED define in order to prevent from doing all this stuff.

The #undef main approach will work also, but it's not quite as good because this way, you tell SDL what is going on, with the other method, SDL thinks that all it's stuff is going to be used and in fact you crudely disable it with #undef later.

If you want to see details of the various macros / platform checks, you can look in the SDL_main.h header. If you want to know what the benefits of the SDL main system are, you can look at SDL documentation.

Literacy answered 2/9, 2015 at 1:0 Comment(1)
This got rid of the error. Thanks. If you don't mind me asking, why/how does this solve the issue?Norton
C
11

The solution suggested in the accepted answer (undefining main, defining SDL_MAIN_HANDLED and all that) deviates from how SDL2 is intended to be used. It's another question if the intended approach is sound, but I prefer to stick to it nontheless.


This error means that you didn't link the right libraries, or linked them in the wrong order.
You need following, in this exact order: -lmingw32 -lSDL2main -lSDL2.

It's possible that doing so will change the error to undefined reference to `SDL_main'. This means that the signature of main you used differs from what SDL expects. It must be int main(int, char **) or int main(int, char *[]). Adding parameter names is allowed, but you can't change anything else: you have to have parameters, even if you don't use them.

Cestar answered 5/12, 2020 at 9:22 Comment(7)
Thank you that worked. This should be accepted answer.Cassandracassandre
If you're using CMake, and you want to be able to compile on other platforms, you can use MINGW to check if you're compiling with mingw before linking mingw32 to your target. E.g target_link_libraries(target_name PRIVATE $<$<BOOL:MINGW>:mingw32 SDLmain> SDL2 ...)Hickerson
@JosieThompson CMake should determine the correct flags automatically, you shouldn't hardcode this logic.Cestar
I'm not entirely sure what you mean by CMake will determine the correct flags. When I'm compiling without an IDE on linux, just linking SDL2 without mingw32 or SDL2main works just fine. However, when I compile on Windows with CLion (using mingw gcc as the compiler) I have to add those two first. Though I suppose I haven't tested compiling with those two flags on linux without an IDEHickerson
@JosieThompson I don't use CMake, so I don't know what exactly you need to do to automatically determine those flags for the current platform, but there's surely a way. Even when using pkg-config -lmingw32 -lSDL2main are added automatically.Cestar
@JosieThompson Found it: github.com/libsdl-org/SDL/blob/SDL2/docs/…Cestar
Ohh, I think I get it - It seems that the namespaced target will link the required libraries while the target without the namespace won'tHickerson

© 2022 - 2024 — McMap. All rights reserved.