winegcc now overrides --entry only when it applies to any compiler (e.g. kernel drivers or msvcrt) but leaves spec details to winebuild.
It therefore now forwards -municode so winebuild will know which to use.
Signed-off-by: Kevin Puetz PuetzKevinA@JohnDeere.com --- tools/winebuild/build.h | 1 + tools/winebuild/main.c | 9 +++++++-- tools/winegcc/winegcc.c | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 03715af9563..26a0539c500 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -136,6 +136,7 @@ typedef struct int subsystem; /* subsystem id */ int subsystem_major; /* subsystem version major number */ int subsystem_minor; /* subsystem version minor number */ + int unicode_app; /* default to unicode entry point */ ORDDEF *entry_points; /* dll entry points */ ORDDEF **names; /* array of entry point names (points into entry_points) */ ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */ diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 0e5e1627dda..b1e6d115717 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -396,8 +396,12 @@ static const char *get_default_entry_point( const DLLSPEC *spec ) { if (spec->characteristics & IMAGE_FILE_DLL) return "DllMain"; if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry"; - if (spec->type == SPEC_WIN16) return "__wine_spec_exe16_entry"; - return "__wine_spec_exe_entry"; + if (spec->type == SPEC_WIN16) + return "__wine_spec_exe16_entry"; + else if (spec->unicode_app) + return "__wine_spec_exe_wentry"; + else + return "__wine_spec_exe_entry"; }
/* parse options from the argv array and remove all the recognized ones */ @@ -448,6 +452,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) else if (!strcmp( optarg, "thumb" )) thumb_mode = 1; else if (!strcmp( optarg, "no-cygwin" )) use_msvcrt = 1; else if (!strcmp( optarg, "unix" )) unix_lib = 1; + else if (!strcmp( optarg, "unicode" )) spec->unicode_app = 1; else if (!strncmp( optarg, "cpu=", 4 )) cpu_option = xstrdup( optarg + 4 ); else if (!strncmp( optarg, "fpu=", 4 )) fpu_option = xstrdup( optarg + 4 ); else if (!strncmp( optarg, "arch=", 5 )) arch_option = xstrdup( optarg + 5 ); diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 9268a5dfd1d..cef0832455c 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -1245,8 +1245,6 @@ static void build(struct options* opts) entry_point = (is_pe && opts->target_cpu == CPU_x86) ? "DriverEntry@8" : "DriverEntry"; else if (opts->use_msvcrt && !opts->shared && !opts->win16_app) entry_point = opts->unicode_app ? "wmainCRTStartup" : "mainCRTStartup"; - else if (!is_pe && !opts->shared && opts->unicode_app) - entry_point = "__wine_spec_exe_wentry"; } else entry_point = opts->entry_point;
@@ -1258,6 +1256,8 @@ static void build(struct options* opts) spec_o_name = get_temp_file(output_name, ".spec.o"); if (opts->force_pointer_size) strarray_add(spec_args, strmake("-m%u", 8 * opts->force_pointer_size )); + if(opts->unicode_app) + strarray_add(spec_args, "-municode"); strarray_add(spec_args, "-D_REENTRANT"); if (opts->pic && !is_pe) strarray_add(spec_args, "-fPIC"); strarray_add(spec_args, opts->shared ? "--dll" : "--exe");
Have the winebuild -spec.o include an undefined .globl referencing symbols we know the winecrt0 entry point will eventually reference, so ld knows about that need while scanning library archives.
Signed-off-by: Kevin Puetz PuetzKevinA@JohnDeere.com ---
wine.exe.so files set __wine_spec_exe_entry as the entry point. Therefore the linker is not initially looking for main and will pass over objects in lib.a archives that might provide it. When it gets to libwinecrt0.a, it finds __wine_spec_exe_entry and learns that it wants but the resulting rescan will find the winecrt0 default definition (in terms of WinMain), before rescanning earlier libraries.
So only a direct .o file (which is never passed over) can override the winecrt0 definition, and libraries like -lgtest_main do not work.
Another way to let the linker see these dependencies would be to split up libwinecrt0.a, so that we can link the portion containing exe*_entry.o immediately after the winebuild spec file, before the the user code/libs and then finish up with a libwinecrtdefs.a (or whatever name) that contains the remainder (definitions of w?main as wrappers of w?WinMain).
But that takes more change and does not seem particularly more clear. Opinions? --- tools/winebuild/build.h | 1 + tools/winebuild/main.c | 11 +++++++++++ tools/winebuild/spec32.c | 12 ++++++++++++ 3 files changed, 24 insertions(+)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 26a0539c500..a4b9bc97e3e 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -300,6 +300,7 @@ extern void output_gnu_stack_note(void); extern void add_import_dll( const char *name, const char *filename ); extern void add_delayed_import( const char *name ); extern void add_extra_ld_symbol( const char *name ); +extern void add_spec_extra_ld_symbol( const char *name ); extern void read_undef_symbols( DLLSPEC *spec, char **argv ); extern void resolve_imports( DLLSPEC *spec ); extern int is_undefined( const char *name ); diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index b1e6d115717..b37aec9cf6f 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -397,11 +397,22 @@ static const char *get_default_entry_point( const DLLSPEC *spec ) if (spec->characteristics & IMAGE_FILE_DLL) return "DllMain"; if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry"; if (spec->type == SPEC_WIN16) + { + add_spec_extra_ld_symbol("WinMain16"); return "__wine_spec_exe16_entry"; + } else if (spec->unicode_app) + { + /* __wine_spec_exe_wentry always calls wmain */ + add_spec_extra_ld_symbol("wmain"); return "__wine_spec_exe_wentry"; + } else + { + /* __wine_spec_exe_entry always calls main */ + add_spec_extra_ld_symbol("main"); return "__wine_spec_exe_entry"; + } }
/* parse options from the argv array and remove all the recognized ones */ diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index ba2edfb588f..a12e7d38aac 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -50,6 +50,13 @@ int needs_get_pc_thunk = 0;
static const char builtin_signature[32] = "Wine builtin DLL"; static const char fakedll_signature[32] = "Wine placeholder DLL"; +static struct strarray spec_extra_ld_symbols = { 0 }; /* list of extra symbols that ld should resolve */ + +/* add a symbol to the list of extra symbols that ld must resolve */ +void add_spec_extra_ld_symbol( const char *name ) +{ + strarray_add( &spec_extra_ld_symbols, name, NULL ); +}
static unsigned int hash_filename( const char *name ) { @@ -610,6 +617,7 @@ void output_exports( DLLSPEC *spec ) void output_module( DLLSPEC *spec ) { int machine = 0; + int i; unsigned int page_size = get_page_size(); const char *data_dirs[16] = { NULL };
@@ -688,6 +696,10 @@ void output_module( DLLSPEC *spec ) output( "\t.long 0\n" ); /* SizeOfCode */ output( "\t.long 0\n" ); /* SizeOfInitializedData */ output( "\t.long 0\n" ); /* SizeOfUninitializedData */ + + for (i = 0; i < spec_extra_ld_symbols.count; i++) + output( "\t.globl %s\n", asm_name(spec_extra_ld_symbols.str[i]) ); + /* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */ output( "\t%s %s\n", /* AddressOfEntryPoint */ get_asm_ptr_keyword(), spec->init_func ? asm_name(spec->init_func) : "0" );
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Kevin Puetz PuetzKevinA@JohnDeere.com --- Jacek found this part a bit more controversial and asked me to split it.
Today, winegcc will let you set -mwindows, yet still use main. MinGW gcc allows this as well. With this change, that will no longer work, since there will be an undefined symbol referencing WinMain.
MSVC does not allow this; main matches /subsytem:console, and WinMain matches /subsystem:windows; mismatching flags and symbols is a link error (consistent with the behavior after this patch).
I think the MinGW behavior is an artifact of a similar runtime structure to winecrt0: entry at a mainCRTStartup that calls main(), with a default main() that calls WinMain unless you replaced it. But I don't think it's seems intentional (or correct) in either case to allow the mismatch, they just lacked MSVC's linker support to set subsystem by flavor of main.
However, the use case I had (things like gtest_main) won't use WinMain. So if this is too controversial you could take just the first two patches. This one is more "for completeness" than because I have a real need. --- tools/winebuild/main.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index b37aec9cf6f..0ce7816cd8a 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -405,12 +405,16 @@ static const char *get_default_entry_point( const DLLSPEC *spec ) { /* __wine_spec_exe_wentry always calls wmain */ add_spec_extra_ld_symbol("wmain"); + if(spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) + add_spec_extra_ld_symbol("wWinMain"); return "__wine_spec_exe_wentry"; } else { /* __wine_spec_exe_entry always calls main */ add_spec_extra_ld_symbol("main"); + if(spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) + add_spec_extra_ld_symbol("WinMain"); return "__wine_spec_exe_entry"; } }
Signed-off-by: Jacek Caban jacek@codeweavers.com