Search code examples
cwindowssdl-2mingw-w64

Basic SDL2 app compiles with MinGW-w64 but doesn't run


I'm trying to set up a SDL2 and C development environment on Windows 10 with MinGW-w64.

When trying to run the basic c app with SDL initialization, it compiles without warnings but fails to run afterwards, again without any warnings. Executable just exits.

Here's the source:

#include<SDL2/SDL.h>

int main(int argc, char* argv[]) {

    puts("\nmain...\n");

    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("\nInit error: %s\n", SDL_GetError());
    }
    else {
        puts("\nSDL init success...");
    }
}

... and the makefile:

OBJS = sdl_init.c
EXE_NAME = sdl_init_test
CFLAGS_W = -w -Wl,-subsystem,windows
LFLAGS_W = -lmingw32 -lSDL2main -lSDL2
INCS_W = -IC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\include
LIBS_W = -LC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\lib

windows_debug:
    gcc $(OBJS) $(INCS_W) $(LIBS_W) $(CFLAGS_W) $(LFLAGS_W) -g -o $(EXE_NAME).exe

... and the weird output from gdb:

Reading symbols from .\sdl_init_test.exe...
(gdb) list main
12      ../../src/mingw-w64-crt/crt/crt0_c.c: No such file or directory.
(gdb) b main
Breakpoint 1 at 0x402e70: file ../../src/mingw-w64-crt/crt/crt0_c.c, line 17.

I'm assuming I'm doing something wrong in the linking phase, but can't pinpoint it exactly. On Linux, everything compiles, runs and debugs as expected.


Here's a corrected makefile, as answered which will compile and work fine in Windows console:

SRC = sdl_init.c
EXE_NAME = sdl_init_test

CFLAGS_W = -Wall -Wl,-subsystem,console
LFLAGS_W = -lmingw32 -lSDL2main -lSDL2
INCS_W = -IC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\include
LIBS_W = -LC:\MinGW\devlibs\SDL2-2.0.12\x86_64-w64-mingw32\lib


windows_debug:
    gcc $(SRC) $(INCS_W) $(LIBS_W) $(CFLAGS_W) $(LFLAGS_W) -g -o $(EXE_NAME).exe

Solution

  • Aside from startup issue with missing dynamic library, you seem to be mislead (arguably by SDL actually being misleading in that aspect) that your b main in gdb sets breakpoint in your main function. That's not the case as SDL redefines main to SDL_main, so if you have #include "SDL2.h" or something similar and SDL have main wrapper implemented for your operating system - your function gets renamed. Internally main (or wmain, or WinMain, or whatever target system uses as user-defined code entry point) is implemented in SDL2main library that you link with, and it calls SDL_main (your code).

    TL;DR use b SDL_main in gdb instead.

    Second point is why you don't see output text. That's once again windows specific, basically because you've build "GUI" app, which is different from "console" app, and don't really have its stdout associated with console output. Output is still there but you can't see it - but it can be redirected to other program or file, e.g. your_program.exe | more or your_program.exe > stdout.txt. There are ways to reconnect stdout to console (some freopen with CON magic, as I recall), or you can just build console program instead with -Wl,-subsystem,console.

    As a side note, -w compiler flag (that could be loosely read as "don't ever warn me about any potential problems with my code as I'm 100% sure it is absolutely perfect and all your warnings are unjustified complaints about my perfect code" (sorry)) is a really really bad idea, with some very rare exceptions. Compilers, especially gcc and clang, are very good at giving warnings in places where it really matter, allowing you to spot mistakes early. You want more warnings (e.g. -Wall -Wextra, probably more), not no warnings at all. And while we're at it, OBJS in makefile logically should mean object files, not sources (of course you technically can call your variables anything you like, it is just misleading).