SDL
SDL copied to clipboard
Is it possible to remove the linker flag `-mwindows` in MinGW?
I'm using CMake & MinGW and I DON'T think the linker flag -mwindows
is useful at all for me and it has made me too inconvenient to develop console apps. I cannot use the stdout functions such as printf
and puts
because of this flag. Hope to remove it.
The CMake script of current master only adds -mwindows
fot the sdl2.pc
pkg-config file.
Neither -mwindows
and -lmingw32
are needed anymore since 5ec2d46f476f5019d1d0bb8345b7f6f79222d0c1.
So can you try with current master?
For reference, the last lines of configuration with mingw64 look like:
-- CFLAGS: -idirafter "/home/maarten/programming/SDL/src/video/khronos"
-- EXTRA_CFLAGS: -Wall -fno-strict-aliasing -Werror=declaration-after-statement -Wdeclaration-after-statement -fvisibility=hidden -Wshadow -fdiagnostics-color=always -mmmx -m3dnow -msse -msse2 -msse3
-- EXTRA_LDFLAGS: -Wl,--no-undefined
-- EXTRA_LIBS: m;iconv;user32;gdi32;winmm;imm32;ole32;oleaut32;version;uuid;advapi32;setupapi;shell32;dinput8
--
-- Build Shared Library: ON
-- Build Static Library: ON
-- Build Static Library with Position Independent Code: OFF
--
-- Configuring done
Currently, sdl2.pc
generated by CMake contains -mwindows
though.
I went ahead and removed the -mwindows
from the generated sdl2.pc
in https://github.com/libsdl-org/SDL/commit/d211aaddc1edaad0e7d461d6837f3f1d2f9f4b41.
Adding -mwindows
should be a decision made by a project, not by us.
autotools side needs a similar change, doesn't it?
Also: The sdl2-config
script needs a similar change.
Removing -mwindows will break all the applications which depend on it - any application which isn't a console application, e.g. all games, etc. Please revert this change. If someone specifically wants to build a console application with SDL, they can use their own link flags with their build.
If you want to add an option to disable that, that's fine, but we shouldn't change the default which has been in place for decades.
Reverted in fc2497b109f6d38a0e55f9af92162b9a90b36fcf
CMake adds -mwindows
again to the sdl2.pc
.
CMake projects will need to explicitly add WIN32
to switch between WinMain/main.
If there's an elegant way to parameterize that in the pkg-config / sdl-config / CMake cases, I'm totally fine with that, we just can't change the default.
I just compared with 2.0.22 and pkg-config/sdl-config behave the same.
Only CMake does not add -mwindows
to the SDL2 targets.
I argue this is fine because not everybody wants to build a WinMain
application every time.
Always adding -mwindows
would also make SDL_MAIN_HANDLED
more useless because the main
function will not be the entry function, and they would need a wrapper anyways.
Another argument is the only fix applications need to work is the following:
@@ CMakeLists.txt @@
-add_executable(mygame
+add_executable(mygame WIN32
The game will remain compatible with current and previous SDL versions. It will even be correcter.
Also, WIN32
will need to be added anyways when they want their game to be buildable by MSVC.
Okay, that's fine, as long as we document the requirement for CMake applications on Windows.
I will edit http://wiki.libsdl.org/Installation a bit. It still displays CMake as experimental.
See https://github.com/libsdl-org/sdlwiki/pull/243
https://github.com/libsdl-org/sdlwiki/pull/243 is merged, is that enough to resolve this issue?
For SDL3, we currently only add -mwindows
in sdl3.pc
.
Current sdl3.pc
looks like:
# sdl pkg-config source file
prefix=${pcfiledir}/../..
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: sdl3
Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer.
Version: 3.0.0
Requires.private:
Conflicts:
Libs: -L${libdir} -lSDL3 -mwindows
Libs.private: -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lversion -luuid -ladvapi32 -lsetupapi -lshell32 -ldinput8
Cflags: -I${includedir} -I${includedir}/SDL3
I think now would be an ideal time to remove -mwindows
.
Then, when building a Windows application, by default a console application will be built and only by manually adding -mwindows
will a gui application be built.
This is equivalent to cmake, which will build a console application by default (add_executable(app app.c)
), and will only build a gui application by passing WIN32
(add_executable(app WIN32 app.c)
)
CC'ing @DanielGibson because he got rid of SDL3_main
In general SDL applications on Windows will be gui applications and should not have a visible console. I don't think we should disable that by default.
Wasn't this for old static SDL_main? I'd argue that SDL should not set this (nor -mconsole), but that it should be up to the application (and not libs used by them) to decide whether to set it or not
You can still do the following to get a console application. The last argument will win.
x86_64-w64-mingw32-gcc src.c -o app.exe $(pkg-config sdl3 --cflags --libs) -mconsole
And I think you're right the -mwindows
being for old static SDL_main: libSDL2_main.a
provided a WinMain
method that calls sdl_main
. Without -mwindows
, no main
method would be found and a linker error would occur.
You can still do the following (...)
true, but still, what's the point of having a library set this
Without -mwindows, no main method would be found and a linker error would occur.
don't know if it used to be like this, but when I recently tested what kind of main function mingw expects, both main() and WinMain() were accepted in both -mwindows and -mconsole mode (though IIRC it preferred plain main() in both cases - and it was picky about getting wmain() or wWinMain() if -municode was set)
This whole main()
, wmain()
, WinMain()
, wWinMain()
, and -mconsole
/-mwindows
situation is a complete disaster in SDL2.
And, although nobody wants to hear an inconvenient truth, the truth still has to be said; because only then an opportunity for improvement may open: this situation exists because apparently the SDL2 maintainers have no clue what they are doing on Windows, what the default on Windows is and what the conventions on Windows are.
Here are a few hints what to fix:
- It is an absolute :no_entry:no no:no_entry: on Windows for any dependency to force or expect any consumer to set either application type.
- The default on Windows for any compiler, or rather linker, is to build a console application (CUI). Any project that wants to build a GUI application must set
-mwindows
/--subsystem=windows
//SUBSYSTEM:WINDOWS
explicitly. The same should be true for SDL2. If it had a correct implementation ofSDL_windows_main.c
things would be easy. - By convention, UNICODE enabled libraries on Windows provide ANSI sibling symbols at the same time. Hence, any
UNICODE
macros https://github.com/libsdl-org/SDL/blob/707e9397cae56a3db2835b474c20f22778765e6b/src/main/windows/SDL_windows_main.c#L32-L34 https://github.com/libsdl-org/SDL/blob/707e9397cae56a3db2835b474c20f22778765e6b/src/main/windows/SDL_windows_main.c#L97-L103 are rather redundant because even pure ANSI consumers should be able to link to proper UNICODE libraries. Unless you want to provide a pure ANSI flavor of SDL2, there is really no point in doing so but there is also no point in providing a pure ANSI flavor of SDL2 either.<BR> TheUNICODE
macro has been introduced with application authors in mind, not library authors because only applications are built to either flavors and are usually not intended to be used as dependencies.<BR> Thus,SDL_windows_main.c
still lacks an implementation ofwWinMain()
and an ANSI implementation ofmain_getcmdline()
. Pure ANSI consumers are unable to executemain_getcmdline()
.
Have you checked the SDL3 SDL_main implementation?
https://github.com/libsdl-org/SDL/blob/main/include/SDL3/SDL_main.h and https://github.com/libsdl-org/SDL/blob/main/include/SDL3/SDL_main_impl.h SDL_RunApp() for Windows is implemented in SDL3.dll in https://github.com/libsdl-org/SDL/blob/b6ca3602289aa2b0c34856f31e0214d924bda2c9/src/core/windows/SDL_windows.c#L348-L405
There main()/WinMain() is implemented in the header and -mwindows isn't set anymore (I think it shouldn't at least). As it's implemented in the header it can also check UNICODE and implements wmain()/wWinMain() accordingly
Have you checked the SDL3 SDL_main implementation?
No, I have not because I am sort of stuck on SDL2 for now. However, I would be happy if this bug could also be finally fixed in SDL2.
There main()/WinMain() is implemented in the header…
This is an odd way of doing things. Static code should go into static libraries or object files but okay, … I guess. Anyhow, it is nice to see there is hope and progress.
No, I have not because I am sort of stuck on SDL2 for now.
That's ok, SDL3 isn't even done yet, just wondering if you have objections to the new implementation
I would be happy if this bug could also be finally fixed in SDL2.
Not sure if it's a good idea to change this in SDL2, it might break things for users who already made it work somehow?
Static code should go into static libraries or object files
But it's not static, it has to handle main vs wmain which, as you pointed out, is only known when building the application, not when building SDL itself. Furthermore, some platforms (like WinRT and iOS, IIRC) don't even support main() being in a static lib - in SDL2 you had to handle them specially by copying a C-file from the SDL2 source to your own code that contained the platform-specific main() implementation which then called your SDL_main().
But if you check out the code I linked you'll notice that the header-only part is absolutely minimal, basically just a platform-specific main()-function calling SDL_RunApp(..., SDL_main, ...)
(where SDL_main is the users standard-C int main(int argc, char* argv[])
function that gets renamed to SDL_main with a macro, like in SDL2), so the real logic (like translating commandline arguments to UTF-8 on Windows) that used to be in the static SDL_main lib is now in the dynamic SDL3 lib (in SDL_RunApp()
)
But it's not static, it has to handle main vs wmain which, as you pointed out, is only known when building the application, not when building SDL itself.
Au contraire 2×. :laughing: It is static. What you are talking about is conditional compilation. :wink:
This decision does not have to be made at SDL2 compile‑time. The linker can make this decision at application link‑time too because by design e.g. either -mwindows
makes WinMain
or -mconsole
makes main
an unresolved symbol by effectively linking with a toolchain provided object file. Likewise -municode -mwindows
makes wWinMain
and -municode -mconsole
makes wmain
an unresolved symbol. SDL2 just has to provide all possible entry points. The linker can resolve the correct entry point at application link‑time.
Furthermore, some platforms (like WinRT and iOS, IIRC) don't even support main() being in a static lib
I would be curious to know why this might be because every application has a static main()
in some object file. The linker does not care whether you pass it an object file from your project or a static lib form somewhere else. The linker just resolves all symbols, no matter where they might come from.
(the following applies to SDL2 only) This whole "redefine main" business does not seem to be much of an issue. See SDL_main.h lines 162 and following,
This function is defined in SDL_main.h, along with the preprocessor rule to redefine main() as SDL_main(). Thus to ensure that your main() function will not be changed it is necessary to define SDL_MAIN_HANDLED before including SDL.h.
So in your main include file, do this, and it is out of the way, and we are in control of our platform specific linker entry point once again:
#define SDL_MAIN_HANDLED
#include <SDL.h>