SDL icon indicating copy to clipboard operation
SDL copied to clipboard

Is it possible to remove the linker flag `-mwindows` in MinGW?

Open vhyijk opened this issue 2 years ago • 22 comments

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. image

vhyijk avatar Jul 23 '22 01:07 vhyijk

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.

madebr avatar Jul 23 '22 01:07 madebr

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.

madebr avatar Jul 23 '22 15:07 madebr

autotools side needs a similar change, doesn't it?

sezero avatar Jul 23 '22 15:07 sezero

Also: The sdl2-config script needs a similar change.

sezero avatar Jul 23 '22 15:07 sezero

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.

slouken avatar Jul 23 '22 16:07 slouken

Reverted in fc2497b109f6d38a0e55f9af92162b9a90b36fcf CMake adds -mwindows again to the sdl2.pc.

CMake projects will need to explicitly add WIN32 to switch between WinMain/main.

madebr avatar Jul 23 '22 16:07 madebr

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.

slouken avatar Jul 23 '22 16:07 slouken

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.

madebr avatar Jul 23 '22 17:07 madebr

Okay, that's fine, as long as we document the requirement for CMake applications on Windows.

slouken avatar Jul 23 '22 17:07 slouken

I will edit http://wiki.libsdl.org/Installation a bit. It still displays CMake as experimental.

madebr avatar Jul 23 '22 17:07 madebr

See https://github.com/libsdl-org/sdlwiki/pull/243

madebr avatar Jul 23 '22 20:07 madebr

https://github.com/libsdl-org/sdlwiki/pull/243 is merged, is that enough to resolve this issue?

icculus avatar Jul 24 '22 05:07 icculus

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

madebr avatar Jan 15 '23 20:01 madebr

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.

slouken avatar Jan 15 '23 21:01 slouken

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

DanielGibson avatar Jan 15 '23 21:01 DanielGibson

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.

madebr avatar Jan 15 '23 21:01 madebr

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)

DanielGibson avatar Jan 15 '23 22:01 DanielGibson

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:

  1. 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.
  2. 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 of SDL_windows_main.c things would be easy.
  3. 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> The UNICODE 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 of wWinMain() and an ANSI implementation of main_getcmdline(). Pure ANSI consumers are unable to execute main_getcmdline().

JakeSmarter avatar May 03 '23 22:05 JakeSmarter

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

DanielGibson avatar May 03 '23 22:05 DanielGibson

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.

JakeSmarter avatar May 03 '23 23:05 JakeSmarter

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())

DanielGibson avatar May 03 '23 23:05 DanielGibson

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.

JakeSmarter avatar May 04 '23 00:05 JakeSmarter

(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>

dlatikaynen avatar Jun 11 '23 15:06 dlatikaynen