[PATCH v3 0/8] MR9027: winegcc: Force subsystem version to 5.2 on both Clang and MinGW.
This would hopefully fix some comctl32 test failures which started happening after I changed my nightly winetest runs to build Wine with Clang. -- v3: winegcc: Force default subsystem version to MSVC modern values. user32/tests: Force console subsystem version 5.2. quartz/tests: Force console subsystem version 5.2. dxgi/tests: Force console subsystem version 5.2. comctl32/tests: Force console subsystem version 5.2. winegcc: Support subsystem version number in link.exe-style cmdline. winegcc: Set the default subsystem to console. winegcc: Consistently use the subsystem option with Clang and MinGW. https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> Instead of the -mwindows / -mconsole flags with MinGW. --- tools/winegcc/winegcc.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 7322feaaf80..46a63453985 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -170,7 +170,6 @@ enum file_type { file_na, file_other, file_obj, file_res, file_rc, file_arh, fil static bool is_pe; static bool is_static; static bool is_shared; -static bool is_gui_app; static bool is_unicode_app; static bool is_win16_app; static bool is_arm64x; @@ -541,10 +540,9 @@ static struct strarray get_link_args( const char *output_name ) strarray_add( &flags, "-shared" ); strarray_add( &flags, "-Wl,--kill-at" ); } - else strarray_add( &flags, is_gui_app ? "-mwindows" : "-mconsole" ); if (is_unicode_app) strarray_add( &flags, "-municode" ); - if (subsystem) strarray_add( &flags, strmake("-Wl,--subsystem,%s", subsystem )); + if (subsystem) strarray_add( &flags, strmake( "-Wl,--subsystem,%s", subsystem ) ); strarray_add( &flags, "-Wl,--exclude-all-symbols" ); strarray_add( &flags, "-Wl,--nxcompat" ); @@ -600,10 +598,7 @@ static struct strarray get_link_args( const char *output_name ) if (entry_point) strarray_add( &flags, strmake( "-Wl,-entry:%s", entry_point )); - if (subsystem) - strarray_add( &flags, strmake("-Wl,-subsystem:%s", subsystem )); - else - strarray_add( &flags, strmake("-Wl,-subsystem:%s", is_gui_app ? "windows" : "console" )); + if (subsystem) strarray_add( &flags, strmake( "-Wl,--subsystem:%s", subsystem ) ); STRARRAY_FOR_EACH( file, &output_debug_files ) { @@ -1137,13 +1132,14 @@ static void build_spec_obj( const char *spec_file, const char *output_file, strarray_add(&spec_args, output_name); } - if (!is_shared) + if (subsystem) { - strarray_add(&spec_args, "--subsystem"); - strarray_add(&spec_args, is_gui_app ? "windows" : "console"); - if (large_address_aware) strarray_add( &spec_args, "--large-address-aware" ); + strarray_add( &spec_args, "--subsystem" ); + strarray_add( &spec_args, subsystem ); } + if (!is_shared && large_address_aware) strarray_add( &spec_args, "--large-address-aware" ); + if (target.platform == PLATFORM_WINDOWS && target.cpu == CPU_i386) strarray_add(&spec_args, "--safeseh"); @@ -1153,12 +1149,6 @@ static void build_spec_obj( const char *spec_file, const char *output_file, strarray_add(&spec_args, entry_point); } - if (subsystem) - { - strarray_add(&spec_args, "--subsystem"); - strarray_add(&spec_args, subsystem); - } - if (!is_pe) STRARRAY_FOR_EACH( imp, &delayimports ) strarray_add(&spec_args, strmake("-d%s", imp)); strarray_addall( &spec_args, resources ); @@ -1318,7 +1308,7 @@ static void build(struct strarray input_files, const char *output) if (!wine_objdir && !nodefaultlibs) { - if (is_gui_app) + if (subsystem && !strncmp( subsystem, "windows", 7 )) { add_library(lib_dirs, &files, "shell32"); add_library(lib_dirs, &files, "comdlg32"); @@ -1776,12 +1766,12 @@ int main(int argc, char **argv) } else if (strcmp("-mwindows", args.str[i]) == 0) { - is_gui_app = true; + subsystem = "windows"; raw_compiler_arg = 0; } else if (strcmp("-mconsole", args.str[i]) == 0) { - is_gui_app = false; + subsystem = "console"; raw_compiler_arg = 0; } else if (strcmp("-municode", args.str[i]) == 0) @@ -1856,6 +1846,7 @@ int main(int argc, char **argv) { is_shared = true; raw_compiler_arg = raw_linker_arg = 0; + if (!subsystem) subsystem = "console"; } else if (strcmp("-s", args.str[i]) == 0) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> --- tools/winegcc/winegcc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 46a63453985..65460937c54 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -542,7 +542,7 @@ static struct strarray get_link_args( const char *output_name ) } if (is_unicode_app) strarray_add( &flags, "-municode" ); - if (subsystem) strarray_add( &flags, strmake( "-Wl,--subsystem,%s", subsystem ) ); + strarray_add( &flags, strmake( "-Wl,--subsystem,%s", subsystem ) ); strarray_add( &flags, "-Wl,--exclude-all-symbols" ); strarray_add( &flags, "-Wl,--nxcompat" ); @@ -598,7 +598,7 @@ static struct strarray get_link_args( const char *output_name ) if (entry_point) strarray_add( &flags, strmake( "-Wl,-entry:%s", entry_point )); - if (subsystem) strarray_add( &flags, strmake( "-Wl,--subsystem:%s", subsystem ) ); + strarray_add( &flags, strmake( "-Wl,--subsystem:%s", subsystem ) ); STRARRAY_FOR_EACH( file, &output_debug_files ) { @@ -1132,11 +1132,8 @@ static void build_spec_obj( const char *spec_file, const char *output_file, strarray_add(&spec_args, output_name); } - if (subsystem) - { - strarray_add( &spec_args, "--subsystem" ); - strarray_add( &spec_args, subsystem ); - } + strarray_add( &spec_args, "--subsystem" ); + strarray_add( &spec_args, subsystem ); if (!is_shared && large_address_aware) strarray_add( &spec_args, "--large-address-aware" ); @@ -1308,7 +1305,7 @@ static void build(struct strarray input_files, const char *output) if (!wine_objdir && !nodefaultlibs) { - if (subsystem && !strncmp( subsystem, "windows", 7 )) + if (!strncmp( subsystem, "windows", 7 )) { add_library(lib_dirs, &files, "shell32"); add_library(lib_dirs, &files, "comdlg32"); @@ -1338,7 +1335,7 @@ static void build(struct strarray input_files, const char *output) /* set default entry point, if needed */ if (!entry_point) { - if (subsystem && !strcmp( subsystem, "native" )) + if (!strcmp( subsystem, "native" )) entry_point = (is_pe && target.cpu == CPU_i386) ? "DriverEntry(a)8" : "DriverEntry"; else if (use_msvcrt && !is_shared && !is_win16_app) entry_point = is_unicode_app ? "wmainCRTStartup" : "mainCRTStartup"; @@ -1621,6 +1618,7 @@ int main(int argc, char **argv) includedir = get_includedir( bindir ); target = init_argv0_target( argv[0] ); path_dirs = strarray_frompath( getenv( "PATH" )); + subsystem = "console"; /* setup tmp file removal at exit */ atexit(clean_temp_files); @@ -1846,7 +1844,6 @@ int main(int argc, char **argv) { is_shared = true; raw_compiler_arg = raw_linker_arg = 0; - if (!subsystem) subsystem = "console"; } else if (strcmp("-s", args.str[i]) == 0) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> --- tools/winegcc/winegcc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 65460937c54..c3618f16c21 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -495,6 +495,7 @@ static struct strarray get_link_args( const char *output_name ) { struct strarray link_args = get_translator(); struct strarray flags = empty_strarray; + char *version; strarray_addall( &link_args, linker_args ); @@ -598,7 +599,9 @@ static struct strarray get_link_args( const char *output_name ) if (entry_point) strarray_add( &flags, strmake( "-Wl,-entry:%s", entry_point )); - strarray_add( &flags, strmake( "-Wl,--subsystem:%s", subsystem ) ); + if ((version = strchr( subsystem, ':' ))) subsystem = strmake( "%.*s,%s", (int)(version - subsystem), subsystem, version + 1 ); + strarray_add( &flags, "-Xlinker" ); + strarray_add( &flags, strmake( "-subsystem:%s", subsystem ) ); STRARRAY_FOR_EACH( file, &output_debug_files ) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/comctl32/tests/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/dlls/comctl32/tests/Makefile.in b/dlls/comctl32/tests/Makefile.in index ee7fe6527fe..9c17acd77d7 100644 --- a/dlls/comctl32/tests/Makefile.in +++ b/dlls/comctl32/tests/Makefile.in @@ -1,5 +1,6 @@ TESTDLL = comctl32.dll IMPORTS = ole32 user32 gdi32 advapi32 imm32 uxtheme oleacc oleaut32 +EXTRADLLFLAGS = -Wl,--subsystem,console:5.2 SOURCES = \ animate.c \ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/dxgi/tests/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/dlls/dxgi/tests/Makefile.in b/dlls/dxgi/tests/Makefile.in index 43c7a55a88c..add3803ca40 100644 --- a/dlls/dxgi/tests/Makefile.in +++ b/dlls/dxgi/tests/Makefile.in @@ -1,5 +1,6 @@ TESTDLL = dxgi.dll IMPORTS = d3d10_1 dxgi user32 +EXTRADLLFLAGS = -Wl,--subsystem,console:5.2 SOURCES = \ dxgi.c -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/quartz/tests/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/dlls/quartz/tests/Makefile.in b/dlls/quartz/tests/Makefile.in index c3b96272fbf..1dd25efd19f 100644 --- a/dlls/quartz/tests/Makefile.in +++ b/dlls/quartz/tests/Makefile.in @@ -1,5 +1,6 @@ TESTDLL = quartz.dll IMPORTS = strmbase advapi32 d3d9 ddraw dsound msdmo msvfw32 ole32 oleaut32 user32 uuid winmm +EXTRADLLFLAGS = -Wl,--subsystem,console:5.2 SOURCES = \ acmwrapper.c \ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/user32/tests/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/dlls/user32/tests/Makefile.in b/dlls/user32/tests/Makefile.in index bff53de7713..4bc7172bdb9 100644 --- a/dlls/user32/tests/Makefile.in +++ b/dlls/user32/tests/Makefile.in @@ -1,5 +1,6 @@ TESTDLL = user32.dll IMPORTS = user32 gdi32 advapi32 hid imm32 setupapi +EXTRADLLFLAGS = -Wl,--subsystem,console:5.2 testdll_IMPORTS = user32 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
From: Rémi Bernon <rbernon(a)codeweavers.com> --- tools/winegcc/winegcc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index c3618f16c21..2f611940030 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -1612,7 +1612,7 @@ int main(int argc, char **argv) int i, c, next_is_arg = 0; int raw_compiler_arg, raw_linker_arg, raw_winebuild_arg; struct strarray args = empty_strarray; - const char* option_arg; + const char* option_arg, *subsystem_version; char* str; init_signals( exit_on_signal ); @@ -1621,7 +1621,8 @@ int main(int argc, char **argv) includedir = get_includedir( bindir ); target = init_argv0_target( argv[0] ); path_dirs = strarray_frompath( getenv( "PATH" )); - subsystem = "console"; + subsystem_version = target.cpu == CPU_i386 || target.cpu == CPU_x86_64 ? "6.0" : "6.2"; + subsystem = strmake( "console:%s", subsystem_version ); /* setup tmp file removal at exit */ atexit(clean_temp_files); @@ -1767,12 +1768,12 @@ int main(int argc, char **argv) } else if (strcmp("-mwindows", args.str[i]) == 0) { - subsystem = "windows"; + subsystem = strmake( "windows:%s", subsystem_version ); raw_compiler_arg = 0; } else if (strcmp("-mconsole", args.str[i]) == 0) { - subsystem = "console"; + subsystem = strmake( "console:%s", subsystem_version ); raw_compiler_arg = 0; } else if (strcmp("-municode", args.str[i]) == 0) @@ -1903,6 +1904,8 @@ int main(int argc, char **argv) if (!strcmp(Wl.str[j], "--subsystem") && j < Wl.count - 1) { subsystem = xstrdup( Wl.str[++j] ); + if (!strcmp( subsystem, "windows" ) || !strcmp( subsystem, "console" )) + subsystem = strmake( "%s:%s", subsystem, subsystem_version ); continue; } if (!strcmp(Wl.str[j], "--entry") && j < Wl.count - 1) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9027
v2: Use modern MSVC subsystem version values by default, compile the broken tests with the explicit older version. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119172
Jacek Caban (@jacek) commented about tools/winegcc/winegcc.c:
if (entry_point) strarray_add( &flags, strmake( "-Wl,-entry:%s", entry_point ));
- if (subsystem) - strarray_add( &flags, strmake("-Wl,-subsystem:%s", subsystem )); - else - strarray_add( &flags, strmake("-Wl,-subsystem:%s", is_gui_app ? "windows" : "console" )); + if (subsystem) strarray_add( &flags, strmake( "-Wl,--subsystem:%s", subsystem ) );
This should be `-subsystem`. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119184
Jacek Caban (@jacek) commented about tools/winegcc/winegcc.c:
} else if (strcmp("-mwindows", args.str[i]) == 0) { - is_gui_app = true; + subsystem = "windows";
This loses version information if both `--subsystem` and `-mwindows` are used in an unfortunate order. We may be better off separating the version from the subsystem immediately and storing them separately. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119185
Jacek Caban (@jacek) commented about tools/winegcc/winegcc.c:
includedir = get_includedir( bindir ); target = init_argv0_target( argv[0] ); path_dirs = strarray_frompath( getenv( "PATH" )); - subsystem = "console"; + subsystem_version = target.cpu == CPU_i386 || target.cpu == CPU_x86_64 ? "6.0" : "6.2";
Can we just use a consistent value instead? For Wine usage, I suppose we’ll eventually want this to match the reported Windows version, but that might be a separate change. I’m not sure whether we’d want to adjust the defaults in winegcc or the build system for that. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119186
On Tue Oct 21 11:00:10 2025 +0000, Jacek Caban wrote:
Can we just use a consistent value instead? For Wine usage, I suppose we’ll eventually want this to match the reported Windows version, but that might be a separate change. I’m not sure whether we’d want to adjust the defaults in winegcc or the build system for that. Which version do you suggest should be the default? This is meant to match the table here: https://learn.microsoft.com/en-us/cpp/build/reference/subsystem-specify-subs...
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119189
On Tue Oct 21 11:00:10 2025 +0000, Jacek Caban wrote:
This loses version information if both `--subsystem` and `-mwindows` are used in an unfortunate order. We may be better off separating the version from the subsystem immediately and storing them separately. Then what if command-line is like: `--subsystem=native:4.0 -mwindows`? Shouldn't `-mwindows` take over any previously set subsystem (which it does already) *and* its version?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119190
On Tue Oct 21 11:36:57 2025 +0000, Rémi Bernon wrote:
Which version do you suggest should be the default? This is meant to match the table here: https://learn.microsoft.com/en-us/cpp/build/reference/subsystem-specify-subs... Windows 10 components seem to use "10.0", so I’d be inclined to just use that. If it turns out not to work for some reason, LLD uses "6.0" on all targets anyway, so it should be fine to use that and drop the condition.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119191
On Tue Oct 21 11:55:19 2025 +0000, Jacek Caban wrote:
Windows 10 components seem to use "10.0", so I’d be inclined to just use that. If it turns out not to work for some reason, LLD uses "6.0" on all targets anyway, so it should be fine to use that and drop the condition. Ok, fwiw this only sets the "subsystem version" (as reported by winedump) in the PE header, not the "required OS version" or "image version". I don't know if there's compiler flags for these.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119192
On Tue Oct 21 12:05:12 2025 +0000, Rémi Bernon wrote:
Ok, fwiw this only sets the "subsystem version" (as reported by winedump) in the PE header, not the "required OS version" or "image version". I don't know if there's compiler flags for these. Also looks like using 10.0 causes Windows to fail to run the program with STATUS_INVALID_IMAGE_FORMAT, so I'll use 6.0 instead.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9027#note_119193
participants (2)
-
Jacek Caban (@jacek) -
Rémi Bernon