work is still in progress.
todo: - ensure that all affected sources (i.e. C sources with any kind of assembly) are listed in either way for all architectures - test Wine built with LTO
From: Konstantin Demin rockdrilla@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41712 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51051
Signed-off-by: Konstantin Demin rockdrilla@gmail.com --- configure.ac | 7 ++ tools/makedep.c | 139 +++++++++++++++++++++++++++++++++++++++ tools/tools.h | 72 ++++++++++++++++++++ tools/winebuild/build.h | 1 + tools/winebuild/import.c | 39 ++++++++++- tools/winebuild/main.c | 6 +- tools/winebuild/utils.c | 22 ++++++- tools/winegcc/winegcc.c | 17 +++++ 8 files changed, 297 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac index 6596f653fb1..207871d99e5 100644 --- a/configure.ac +++ b/configure.ac @@ -24,6 +24,7 @@ AC_ARG_ENABLE(maintainer-mode, AS_HELP_STRING([--enable-maintainer-mode],[enable AC_ARG_ENABLE(sast, AS_HELP_STRING([--enable-sast],[enable static application security testing using Clang])) AC_ARG_ENABLE(silent-rules, AS_HELP_STRING([--enable-silent-rules],[use silent build rules (override: "make V=1")])) AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror],[treat compilation warnings as errors])) +AC_ARG_ENABLE(lto, AS_HELP_STRING([--enable-lto],[build with LTO (EXPERIMENTAL)]))
AC_ARG_WITH(alsa, AS_HELP_STRING([--without-alsa],[do not use the Alsa sound support])) AC_ARG_WITH(capi, AS_HELP_STRING([--without-capi],[do not use CAPI (ISDN support)])) @@ -837,6 +838,11 @@ do AS_VAR_COPY([${wine_arch}_LDFLAGS],[LDFLAGS]) AS_VAR_SET([${wine_arch}_EXTRACFLAGS],["-D__WINE_PE_BUILD -Wall"])
+ if test "x$enable_lto" = xyes + then + AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" -D__WINE_LTO_BUILD"]) + fi + target="" set x $CC shift @@ -2377,6 +2383,7 @@ AS_ECHO_N("creating Makefile rules...") >&AS_MESSAGE_FD
makedep_flags=" -C" test "x$enable_silent_rules" = xyes && makedep_flags="$makedep_flags -S" +test "x$enable_lto" = xyes && makedep_flags="$makedep_flags -L"
wine_srcdir= test "$srcdir" = . || wine_srcdir="$srcdir/" diff --git a/tools/makedep.c b/tools/makedep.c index c1937363c39..7c58e8b1c43 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -175,6 +175,7 @@ static struct strarray disabled_dirs[MAX_ARCHS]; static unsigned int native_archs[MAX_ARCHS]; static unsigned int hybrid_archs[MAX_ARCHS]; static struct strarray hybrid_target_flags[MAX_ARCHS]; +static struct strarray global_lto_skip[MAX_ARCHS];
struct makefile { @@ -229,6 +230,8 @@ struct makefile struct strarray res_files[MAX_ARCHS]; struct strarray all_targets[MAX_ARCHS]; struct strarray install_rules[NB_INSTALL_RULES]; + int lto_skip[MAX_ARCHS]; + struct strarray lto_skip_src[MAX_ARCHS]; };
static struct makefile *top_makefile; @@ -242,6 +245,7 @@ static const char *output_file_name; static const char *temp_file_name; static int compile_commands_mode; static int silent_rules; +static int with_lto = 0; static int input_line; static int output_column; static FILE *output_file; @@ -270,6 +274,13 @@ static void fatal_perror( const char *msg, ... ) __attribute__ ((__format__ (__p static void output( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2))); static char *strmake( const char* fmt, ... ) __attribute__ ((__format__ (__printf__, 1, 2)));
+static void parse_global_lto_skip_lists( void ); +static int is_lto_enabled_source( struct makefile *make, struct incl_file *source, unsigned int arch ); +static int is_lto_enabled_target( struct makefile *make, unsigned int arch ); +static void output_lto_flags( int use_lto, int use_env ); +static void output_lto_flags_source( struct makefile *make, struct incl_file *source, unsigned int arch, int use_env ); +static void output_lto_flags_target( struct makefile *make, unsigned int arch, int use_env ); + /******************************************************************* * fatal_error */ @@ -2439,6 +2450,7 @@ static const char *cmd_prefix( const char *cmd ) static void output_winegcc_command( struct makefile *make, unsigned int arch ) { output( "\t%s%s -o $@", cmd_prefix( "CCLD" ), tools_path( make, "winegcc" )); + output_lto_flags_target( make, arch, 0 /* use_env = FALSE */ ); output_filename( "--wine-objdir ." ); if (tools_dir) { @@ -3271,6 +3283,7 @@ static void output_source_one_arch( struct makefile *make, struct incl_file *sou output_filenames( defines ); output_filenames( cflags ); output_filename( var_cflags ); + output_lto_flags_source( make, source, arch, 1 /* use_env = TRUE */ ); output( "\n" );
if (make->testdll && strendswith( source->name, ".c" ) && @@ -3545,6 +3558,7 @@ static void output_import_lib( struct makefile *make, unsigned int arch ) if (hybrid_arch) output_filenames_obj_dir( make, make->implib_files[hybrid_arch] ); output( "\n" ); output( "\t%s%s -w --implib -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" ) ); + output_lto_flags_target( make, arch, 0 /* use_env = FALSE */ ); if (!delay_load_flags[arch]) output_filename( "--without-dlltool" ); output_filenames( target_flags[hybrid_arch ? hybrid_arch : arch] ); if (make->is_win16) output_filename( "-m16" ); @@ -3579,6 +3593,7 @@ static void output_unix_lib( struct makefile *make ) output_filenames( unix_deps ); output( "\n" ); output( "\t%s$(CC) -o $@", cmd_prefix( "CCLD" )); + output_lto_flags_target( make, arch, 1 /* use_env = TRUE */ ); output_filenames( get_expanded_make_var_array( make, "UNIXLDFLAGS" )); output_filenames_obj_dir( make, make->unixobj_files ); output_filenames( unix_libs ); @@ -3604,6 +3619,7 @@ static void output_static_lib( struct makefile *make, unsigned int arch ) if (!arch) output_filenames_obj_dir( make, make->unixobj_files ); output( "\n" ); output( "\t%s%s -w --staticlib -o $@", cmd_prefix( "BUILD" ), tools_path( make, "winebuild" )); + output_lto_flags_target( make, arch, 0 /* use_env = FALSE */ ); output_filenames( target_flags[hybrid_arch ? hybrid_arch : arch] ); output_filenames_obj_dir( make, make->object_files[arch] ); if (hybrid_arch) output_filenames_obj_dir( make, make->object_files[hybrid_arch] ); @@ -3730,6 +3746,7 @@ static void output_programs( struct makefile *make ) output_filenames( deps ); output( "\n" ); output( "\t%s$(CC) -o $@", cmd_prefix( "CCLD" )); + output_lto_flags_target( make, arch, 1 /* use_env = TRUE */ ); output_filenames_obj_dir( make, objs ); output_filenames( all_libs ); output_filename( "$(LDFLAGS)" ); @@ -4490,6 +4507,22 @@ static void load_sources( struct makefile *make )
for (i = 0; i < make->delayimports.count; i++) strarray_add_uniq( &delay_import_libs, get_base_name( make->delayimports.str[i] )); + + if (with_lto) + { + for (arch = 0; arch < archs.count; arch++) + { + const char * lto_skip; + lto_skip = get_expanded_arch_var( make, "LTO_SKIP", arch ); + + make->lto_skip[arch] = var_to_bool(lto_skip); + + memset( &make->lto_skip_src[arch], 0, sizeof(struct strarray) ); + value = get_expanded_arch_var_array( make, "LTO_SKIP_SRC", arch ); + for (i = 0; i < value.count; i++) + strarray_add( &make->lto_skip_src[arch], xstrdup( value.str[i] )); + } + } }
@@ -4537,6 +4570,9 @@ static int parse_option( const char *opt ) case 'S': silent_rules = 1; break; + case 'L': + with_lto = 1; + break; default: fprintf( stderr, "Unknown option '%s'\n%s", opt, Usage ); exit(1); @@ -4679,6 +4715,7 @@ int main( int argc, char *argv[] )
for (i = 0; i < subdirs.count; i++) submakes[i] = parse_makefile( subdirs.str[i] );
+ parse_global_lto_skip_lists(); load_sources( top_makefile ); load_sources( include_makefile ); for (i = 0; i < subdirs.count; i++) @@ -4691,3 +4728,105 @@ int main( int argc, char *argv[] )
return 0; } + + +static void parse_global_lto_skip_lists( void ) +{ + unsigned int arch; + char *buffer; + FILE *file; + + if (!with_lto) return; + + for (arch = 0; arch < archs.count; arch++) + { + memset( &global_lto_skip[arch], 0, sizeof(struct strarray) ); + + input_file_name = root_src_dir_path( arch ? strmake( "tools/makedep.lto-skip.%s.list", archs.str[arch] ) : "tools/makedep.lto-skip.any.list" ); + input_line = 0; + if (!(file = fopen( input_file_name, "r" ))) + { + /* skip nonexistent files */ + input_file_name = NULL; + continue; + } + + while ((buffer = get_line( file ))) + { + if (*buffer == '#') continue; /* comment */ + buffer = skip_spaces( buffer ); + strarray_add( &global_lto_skip[arch], xstrdup( buffer )); + } + fclose( file ); + input_file_name = NULL; + } +} + +static int is_lto_enabled_source( struct makefile *make, struct incl_file *source, unsigned int arch ) +{ + if (!with_lto) return 0; + + /* target config */ + if (strarray_exists( &make->lto_skip_src[0], source->name )) + return 0; + + if (arch) + { + /* target config */ + if (strarray_exists( &make->lto_skip_src[arch], source->name )) + return 0; + + /* global config */ + if (strarray_exists( &global_lto_skip[arch], source->filename )) + return 0; + } + + /* global config */ + if (strarray_exists( &global_lto_skip[0], source->filename )) + return 0; + + return 1; +} + + +static int is_lto_enabled_target( struct makefile *make, unsigned int arch ) +{ + if (!with_lto) return 0; + + if (make->lto_skip[0]) return 0; + + if (arch && make->lto_skip[arch]) + return 0; + + return 1; +} + + +static void output_lto_flags( int use_lto, int use_env ) +{ + struct strarray lto_flags = empty_strarray; + append_lto_flags( <o_flags, use_lto, use_env ); + output_filenames( lto_flags ); +} + + +static void output_lto_flags_source( struct makefile *make, struct incl_file *source, unsigned int arch, int use_env ) +{ + int use_lto = 0; + + if (!with_lto) return; + + use_lto = is_lto_enabled_target( make, arch ) && is_lto_enabled_source( make, source, arch ); + output_lto_flags( use_lto, use_env ); +} + + +static void output_lto_flags_target( struct makefile *make, unsigned int arch, int use_env ) +{ + int use_lto = 0; + + if (!with_lto) return; + + use_lto = is_lto_enabled_target( make, arch ); + output_lto_flags( use_lto, use_env ); +} diff --git a/tools/tools.h b/tools/tools.h index b840a85b2e5..7c1f4a22a39 100644 --- a/tools/tools.h +++ b/tools/tools.h @@ -949,4 +949,76 @@ static inline struct strarray parse_options( int argc, char **argv, const char * #undef OPT_ERR }
+static int var_to_bool( const char *var ) +{ + if (!var) return 0; + if (!( var[0] )) return 0; + + switch (var[0]) + { + /* "1" */ + case '1': + if (!var[1]) return 1; + break; + + /* "[Tt]", "[Tt][Rr][Uu][Ee]" */ + case 'T': /* -fallthrough */ + case 't': + if (!var[1]) return 1; + + if (strlen( var ) != 4) break; + if ((var[1] != 'R') && (var[1] != 'r')) break; + if ((var[2] != 'U') && (var[2] != 'u')) break; + if ((var[3] != 'E') && (var[3] != 'e')) break; + return 1; + + break; + + /* "[Yy]", "[Yy][Ee][Ss]" */ + case 'Y': /* -fallthrough */ + case 'y': + if (!var[1]) return 1; + + if (strlen( var ) != 3) break; + if ((var[1] != 'E') && (var[1] != 'e')) break; + if ((var[2] != 'S') && (var[2] != 's')) break; + return 1; + + break; + } + + return 0; +} + +static int adjust_verbose_lto( int with_lto, int verbose ) +{ + const char* lto_debug; + + if (with_lto < 1) return verbose; + if (verbose) return verbose; + + lto_debug = getenv("WINE_LTO_DEBUG"); + if (!lto_debug) return verbose; + if (!strlen( lto_debug )) return verbose; + + return var_to_bool(lto_debug); +} + +static void append_lto_flags( struct strarray *args, int with_lto, int use_env ) +{ + if (with_lto < 0) return; + + while (use_env > 0) + { + const char *flags = getenv( (with_lto) ? "WINE_LTO_FLAGS" : "WINE_LTO_SKIP_FLAGS" ); + if (!flags) break; + if (!strlen( flags )) break; + + strarray_addall( args, strarray_fromstring( flags, " " ) ); + return; + } + + strarray_add( args, with_lto ? "-flto" : "-fno-lto" ); +} + #endif /* __WINE_TOOLS_H */ diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index e5ede93425b..f6a57db1a2e 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -363,6 +363,7 @@ extern void put_pword( unsigned int val );
extern int current_line; extern int UsePIC; +extern int UseLTO; extern int nb_errors; extern int display_warnings; extern int kill_at; diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 6aee0fa98f8..3223795e430 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1241,11 +1241,27 @@ static const char *get_target_machine(void) /* build a library from the current asm files and any additional object files in argv */ void output_static_lib( const char *output_name, struct strarray files, int create ) { - struct strarray args; + struct strarray args = empty_strarray;
if (!create || target.platform != PLATFORM_WINDOWS) { - args = find_tool( "ar", NULL ); + while (UseLTO) + { + static const char * _cmd[2] = { 0 }; + if (!_cmd[0]) + { + const char *_ar = getenv( "WINE_LTO_AR" ); + if (!_ar) break; + if (!strlen( _ar )) break; + _cmd[0] = _ar; + } + args = find_tool( "ar", _cmd ); + break; + } + if (!args.count) + { + args = find_tool( "ar", NULL ); + } strarray_add( &args, create ? "rc" : "r" ); strarray_add( &args, output_name ); } @@ -1263,7 +1279,24 @@ void output_static_lib( const char *output_name, struct strarray files, int crea
if (target.platform != PLATFORM_WINDOWS) { - struct strarray ranlib = find_tool( "ranlib", NULL ); + struct strarray ranlib = empty_strarray; + while (UseLTO) + { + static const char * _cmd[2] = { 0 }; + if (!_cmd[0]) + { + const char *_ranlib = getenv( "WINE_LTO_RANLIB" ); + if (!_ranlib) break; + if (!strlen( _ranlib )) break; + _cmd[0] = _ranlib; + } + ranlib = find_tool( "ranlib", _cmd ); + break; + } + if (!ranlib.count) + { + ranlib = find_tool( "ranlib", NULL ); + } strarray_add( &ranlib, output_name ); spawn( ranlib ); } diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 63d65e7bcd0..49331544822 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -34,6 +34,7 @@ #include "build.h"
int UsePIC = 0; +int UseLTO = -1; int nb_errors = 0; int display_warnings = 0; int native_arch = -1; @@ -185,7 +186,7 @@ static const char usage_str[] = " -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n" " -E, --export=FILE Export the symbols defined in the .spec or .def file\n" " --external-symbols Allow linking to external symbols\n" -" -f FLAGS Compiler flags (-fPIC and -fasynchronous-unwind-tables are supported)\n" +" -f FLAGS Compiler flags (-flto, -fPIC and -fasynchronous-unwind-tables are supported)\n" " -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n" " --fake-module Create a fake binary module\n" " -h, --help Display this help message\n" @@ -405,6 +406,8 @@ static void option_callback( int optc, char *optarg ) if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1; else if (!strcmp( optarg, "asynchronous-unwind-tables")) unwind_tables = 1; else if (!strcmp( optarg, "no-asynchronous-unwind-tables")) unwind_tables = 0; + else if (!strcmp( optarg, "lto" )) UseLTO = 1; + else if (!strcmp( optarg, "no-lto" )) UseLTO = 0; /* ignore all other flags */ break; case 'h': @@ -569,6 +572,7 @@ int main(int argc, char **argv) if (is_pe()) unwind_tables = 1;
files = parse_options( argc, argv, short_options, long_options, 0, option_callback ); + verbose = adjust_verbose_lto( UseLTO, verbose );
atexit( cleanup ); /* make sure we remove the output file on exit */
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 05595f86d37..bd016107232 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -303,6 +303,7 @@ struct strarray get_as_command(void)
if (using_cc) { + append_lto_flags( &args, (UseLTO == -1) ? -1 : 0, 1 /* use_env = TRUE */ ); strarray_add( &args, "-xassembler" ); strarray_add( &args, "-c" ); if (force_pointer_size) @@ -345,6 +346,7 @@ struct strarray get_ld_command(void) }
strarray_addall( &args, ld_command ); + append_lto_flags( &args, UseLTO, 1 /* use_env = TRUE */ );
if (force_pointer_size) { @@ -380,8 +382,24 @@ const char *get_nm_command(void) { if (!nm_command.count) { - static const char * const commands[] = { "nm", "gnm", NULL }; - nm_command = find_tool( "nm", commands ); + while (UseLTO) + { + static const char * _cmd[2] = { 0 }; + if (!_cmd[0]) + { + const char *_nm = getenv( "WINE_LTO_NM" ); + if (!_nm) break; + if (!strlen( _nm )) break; + _cmd[0] = _nm; + } + nm_command = find_tool( "nm", _cmd ); + break; + } + if (!nm_command.count) + { + static const char * const commands[] = { "nm", "gnm", NULL }; + nm_command = find_tool( "nm", commands ); + } } if (nm_command.count > 1) fatal_error( "multiple arguments in nm command not supported yet\n" ); diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 5b60c57daf7..2108d0e9374 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -177,6 +177,7 @@ struct options int unwind_tables; int strip; int pic; + int lto; int no_default_config; int build_id; const char* wine_objdir; @@ -364,6 +365,7 @@ static struct strarray get_link_args( struct options *opts, const char *output_n struct strarray flags = empty_strarray;
strarray_addall( &link_args, opts->linker_args ); + append_lto_flags( &link_args, opts->lto, 1 /* use_env = TRUE */ );
if (verbose > 1) strarray_add( &flags, "-v" );
@@ -653,6 +655,14 @@ static void compile(struct options* opts, const char* lang) break; }
+ switch(opts->processor) + { + case proc_cc: /* -fallthrough */ + case proc_cxx: + append_lto_flags( &comp_args, opts->lto, 1 /* use_env = TRUE */ ); + break; + } + if (opts->target.platform == PLATFORM_WINDOWS || opts->target.platform == PLATFORM_CYGWIN || opts->target.platform == PLATFORM_MINGW) @@ -835,6 +845,7 @@ static struct strarray get_winebuild_args( struct options *opts, const char *tar strarray_add( &spec_args, binary ); if (verbose) strarray_add( &spec_args, "-v" ); if (keep_generated) strarray_add( &spec_args, "--save-temps" ); + append_lto_flags( &spec_args, opts->lto, 0 /* use_env = FALSE */ ); if (target) { strarray_add( &spec_args, "--target" ); @@ -1502,6 +1513,7 @@ int main(int argc, char **argv) memset(&opts, 0, sizeof(opts)); opts.target = init_argv0_target( argv[0] ); opts.pic = 1; + opts.lto = -1;
/* determine the processor type */ if (strendswith(argv[0], "winecpp")) opts.processor = proc_cpp; @@ -1653,6 +1665,10 @@ int main(int argc, char **argv) opts.pic = 1; else if (!strcmp("-fno-PIC", opts.args.str[i]) || !strcmp("-fno-pic", opts.args.str[i])) opts.pic = 0; + else if (!strcmp( "-flto", opts.args.str[i] )) + opts.lto = 1; + else if (!strcmp( "-fno-lto", opts.args.str[i] )) + opts.lto = 0; break; case 'i': if (!strcmp( "-isysroot", opts.args.str[i] )) opts.isysroot = opts.args.str[i + 1]; @@ -1942,6 +1958,7 @@ int main(int argc, char **argv) strarray_add( &opts.files, opts.args.str[i] ); } } + verbose = adjust_verbose_lto( opts.lto, verbose );
if (opts.force_pointer_size) set_target_ptr_size( &opts.target, opts.force_pointer_size ); if (opts.processor == proc_cpp) linking = 0;
From: Konstantin Demin rockdrilla@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41712 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51051
Signed-off-by: Konstantin Demin rockdrilla@gmail.com --- dlls/d3d8/Makefile.in | 3 +++ dlls/d3d9/Makefile.in | 3 +++ dlls/dbghelp/Makefile.in | 2 ++ dlls/ddraw/Makefile.in | 3 +++ dlls/hal/Makefile.in | 2 ++ dlls/hidclass.sys/Makefile.in | 2 ++ dlls/kernel32/Makefile.in | 4 ++++ dlls/kernelbase/Makefile.in | 5 +++++ dlls/krnl386.exe16/Makefile.in | 2 ++ dlls/mmsystem.dll16/Makefile.in | 2 ++ dlls/mshtml/Makefile.in | 3 +++ dlls/msi/Makefile.in | 2 ++ dlls/msvcirt/Makefile.in | 2 ++ dlls/msvcp60/Makefile.in | 2 ++ dlls/msvcp90/Makefile.in | 2 ++ dlls/ntoskrnl.exe/Makefile.in | 2 ++ dlls/ole32/Makefile.in | 2 ++ dlls/oleaut32/Makefile.in | 4 ++++ dlls/riched20/Makefile.in | 2 ++ dlls/rpcrt4/Makefile.in | 2 ++ dlls/system.drv16/Makefile.in | 2 ++ dlls/user32/Makefile.in | 2 ++ dlls/vcomp/Makefile.in | 4 ++++ dlls/win32u/Makefile.in | 4 ++++ dlls/win87em.dll16/Makefile.in | 2 ++ dlls/winebus.sys/Makefile.in | 2 ++ dlls/winecrt0/Makefile.in | 5 +++++ dlls/wineusb.sys/Makefile.in | 2 ++ dlls/winex11.drv/Makefile.in | 2 ++ dlls/winexinput.sys/Makefile.in | 2 ++ dlls/wow64/Makefile.in | 2 ++ dlls/wow64cpu/Makefile.in | 2 ++ dlls/xaudio2_7/Makefile.in | 2 ++ loader/Makefile.in | 3 +++ programs/rundll32/Makefile.in | 2 ++ programs/wineboot/Makefile.in | 3 +++ tools/makedep.lto-skip.any.list | 17 +++++++++++++++++ tools/makedep.lto-skip.i386.list | 11 +++++++++++ tools/makedep.lto-skip.x86_64.list | 3 +++ 39 files changed, 123 insertions(+) create mode 100644 tools/makedep.lto-skip.any.list create mode 100644 tools/makedep.lto-skip.i386.list create mode 100644 tools/makedep.lto-skip.x86_64.list
diff --git a/dlls/d3d8/Makefile.in b/dlls/d3d8/Makefile.in index 5a718b2d22d..1a2ec0c3357 100644 --- a/dlls/d3d8/Makefile.in +++ b/dlls/d3d8/Makefile.in @@ -14,3 +14,6 @@ SOURCES = \ version.rc \ vertexdeclaration.c \ volume.c + +i386_LTO_SKIP_SRC = device.c +x86_64_LTO_SKIP_SRC = device.c diff --git a/dlls/d3d9/Makefile.in b/dlls/d3d9/Makefile.in index 5a717b11863..d200933e3d1 100644 --- a/dlls/d3d9/Makefile.in +++ b/dlls/d3d9/Makefile.in @@ -16,3 +16,6 @@ SOURCES = \ version.rc \ vertexdeclaration.c \ volume.c + +i386_LTO_SKIP_SRC = device.c +x86_64_LTO_SKIP_SRC = device.c diff --git a/dlls/dbghelp/Makefile.in b/dlls/dbghelp/Makefile.in index 152ef80611a..1d3b1b163da 100644 --- a/dlls/dbghelp/Makefile.in +++ b/dlls/dbghelp/Makefile.in @@ -27,3 +27,5 @@ SOURCES = \ symbol.c \ type.c \ version.rc + +i386_LTO_SKIP_SRC = minidump.c diff --git a/dlls/ddraw/Makefile.in b/dlls/ddraw/Makefile.in index e6d6dddddef..c919424f588 100644 --- a/dlls/ddraw/Makefile.in +++ b/dlls/ddraw/Makefile.in @@ -17,3 +17,6 @@ SOURCES = \ version.rc \ vertexbuffer.c \ viewport.c + +i386_LTO_SKIP_SRC = device.c +x86_64_LTO_SKIP_SRC = device.c diff --git a/dlls/hal/Makefile.in b/dlls/hal/Makefile.in index 7e9928f0e57..12ead12f877 100644 --- a/dlls/hal/Makefile.in +++ b/dlls/hal/Makefile.in @@ -5,3 +5,5 @@ IMPORTS = ntoskrnl SOURCES = \ hal.c \ version.rc + +i386_LTO_SKIP = yes diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in index 57a8fd79297..5179cc13193 100644 --- a/dlls/hidclass.sys/Makefile.in +++ b/dlls/hidclass.sys/Makefile.in @@ -6,3 +6,5 @@ SOURCES = \ device.c \ hidclass.rc \ pnp.c + +i386_LTO_SKIP_SRC = pnp.c diff --git a/dlls/kernel32/Makefile.in b/dlls/kernel32/Makefile.in index ca5bb437e24..d4782e01596 100644 --- a/dlls/kernel32/Makefile.in +++ b/dlls/kernel32/Makefile.in @@ -32,3 +32,7 @@ SOURCES = \ version.rc \ virtual.c \ volume.c + +i386_LTO_SKIP_SRC = process.c sync.c thread.c +x86_64_LTO_SKIP_SRC = module.c +arm64ec_LTO_SKIP_SRC = module.c diff --git a/dlls/kernelbase/Makefile.in b/dlls/kernelbase/Makefile.in index 081e9bfbb64..212c329415b 100644 --- a/dlls/kernelbase/Makefile.in +++ b/dlls/kernelbase/Makefile.in @@ -26,3 +26,8 @@ SOURCES = \ version.c \ volume.c \ winerror.mc + +LTO_SKIP_SRC = debug.c thread.c +i386_LTO_SKIP_SRC = sync.c +x86_64_LTO_SKIP_SRC = loader.c +arm64ec_LTO_SKIP_SRC = loader.c diff --git a/dlls/krnl386.exe16/Makefile.in b/dlls/krnl386.exe16/Makefile.in index 4251c83e158..38cf42bd9ce 100644 --- a/dlls/krnl386.exe16/Makefile.in +++ b/dlls/krnl386.exe16/Makefile.in @@ -35,3 +35,5 @@ SOURCES = \ version.rc \ vxd.c \ wowthunk.c + +LTO_SKIP_SRC = instr.c ne_module.c relay.c selector.c thunk.c wowthunk.c diff --git a/dlls/mmsystem.dll16/Makefile.in b/dlls/mmsystem.dll16/Makefile.in index 08334cb8f83..7638a7bbca7 100644 --- a/dlls/mmsystem.dll16/Makefile.in +++ b/dlls/mmsystem.dll16/Makefile.in @@ -9,3 +9,5 @@ SOURCES = \ message16.c \ mmio16.c \ mmsystem.c + +LTO_SKIP_SRC = mmsystem.c diff --git a/dlls/mshtml/Makefile.in b/dlls/mshtml/Makefile.in index bc712a202c5..957c60b5190 100644 --- a/dlls/mshtml/Makefile.in +++ b/dlls/mshtml/Makefile.in @@ -67,3 +67,6 @@ SOURCES = \ xmlhttprequest.c
nsembed_EXTRADEFS = -DINSTALL_DATADIR=""${datadir}"" + +i386_LTO_SKIP_SRC = ifacewrap.c nsembed.c +x86_64_LTO_SKIP_SRC = ifacewrap.c diff --git a/dlls/msi/Makefile.in b/dlls/msi/Makefile.in index 21420909a92..1c5c0cc9627 100644 --- a/dlls/msi/Makefile.in +++ b/dlls/msi/Makefile.in @@ -49,3 +49,5 @@ SOURCES = \ upgrade.c \ where.c \ winemsi.idl + +i386_LTO_SKIP_SRC = custom.c diff --git a/dlls/msvcirt/Makefile.in b/dlls/msvcirt/Makefile.in index 4f60ea36b3e..c0483368e50 100644 --- a/dlls/msvcirt/Makefile.in +++ b/dlls/msvcirt/Makefile.in @@ -6,3 +6,5 @@ IMPORTS = msvcrt SOURCES = \ exception.c \ msvcirt.c + +i386_LTO_SKIP_SRC = msvcirt.c diff --git a/dlls/msvcp60/Makefile.in b/dlls/msvcp60/Makefile.in index d7beeb0f989..cb4b828dd84 100644 --- a/dlls/msvcp60/Makefile.in +++ b/dlls/msvcp60/Makefile.in @@ -14,3 +14,5 @@ SOURCES = \ memory.c \ misc.c \ string.c + +i386_LTO_SKIP_SRC = main.c diff --git a/dlls/msvcp90/Makefile.in b/dlls/msvcp90/Makefile.in index 5438b518260..63281c4739f 100644 --- a/dlls/msvcp90/Makefile.in +++ b/dlls/msvcp90/Makefile.in @@ -12,3 +12,5 @@ SOURCES = \ misc.c \ msvcp_main.c \ string.c + +i386_LTO_SKIP_SRC = exception.c msvcp_main.c diff --git a/dlls/ntoskrnl.exe/Makefile.in b/dlls/ntoskrnl.exe/Makefile.in index a04a75e7f52..b69f8d49528 100644 --- a/dlls/ntoskrnl.exe/Makefile.in +++ b/dlls/ntoskrnl.exe/Makefile.in @@ -10,3 +10,5 @@ SOURCES = \ plugplay.idl \ pnp.c \ sync.c + +LTO_SKIP_SRC = instr.c ntoskrnl.c diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in index ee0fcc41f7d..0132d1f8e9f 100644 --- a/dlls/ole32/Makefile.in +++ b/dlls/ole32/Makefile.in @@ -44,3 +44,5 @@ SOURCES = \ usrmarshal.c
dlldata_EXTRADEFS = -DENTRY_PREFIX=OLE32_ -DPROXY_CLSID=CLSID_PSFactoryBuffer -DWINE_REGISTER_DLL + +i386_LTO_SKIP_SRC = stg_prop.c diff --git a/dlls/oleaut32/Makefile.in b/dlls/oleaut32/Makefile.in index 1e85c4bd299..badaa07b559 100644 --- a/dlls/oleaut32/Makefile.in +++ b/dlls/oleaut32/Makefile.in @@ -25,3 +25,7 @@ SOURCES = \ vartype.c
dlldata_EXTRADEFS = -DENTRY_PREFIX=OLEAUTPS_ -DPROXY_DELEGATION -DWINE_REGISTER_DLL -DPROXY_CLSID=CLSID_PSFactoryBuffer + +LTO_SKIP_SRC = thunks.c +i386_LTO_SKIP_SRC = vartype.c +x86_64_LTO_SKIP_SRC = vartype.c diff --git a/dlls/riched20/Makefile.in b/dlls/riched20/Makefile.in index cd9d5ff63b1..808934144cc 100644 --- a/dlls/riched20/Makefile.in +++ b/dlls/riched20/Makefile.in @@ -27,3 +27,5 @@ SOURCES = \ version.rc \ wrap.c \ writer.c + +i386_LTO_SKIP_SRC = txthost.c txtsrv.c diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index 69f6961eff3..f0ebbc7b162 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -28,3 +28,5 @@ SOURCES = \ rpcrt4_main.c \ thunks.c \ version.rc + +LTO_SKIP_SRC = ndr_stubless.c thunks.c diff --git a/dlls/system.drv16/Makefile.in b/dlls/system.drv16/Makefile.in index 260bf957f10..26346994bb6 100644 --- a/dlls/system.drv16/Makefile.in +++ b/dlls/system.drv16/Makefile.in @@ -3,3 +3,5 @@ EXTRADLLFLAGS = -m16
SOURCES = \ system.c + +LTO_SKIP = yes diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in index 69e1fa24e15..6006ef28825 100644 --- a/dlls/user32/Makefile.in +++ b/dlls/user32/Makefile.in @@ -68,3 +68,5 @@ SOURCES = \ winproc.c \ winstation.c \ wsprintf.c + +i386_LTO_SKIP_SRC = hook.c sysparams.c win.c winproc.c diff --git a/dlls/vcomp/Makefile.in b/dlls/vcomp/Makefile.in index ec1f82cc33b..d3dfb6e984c 100644 --- a/dlls/vcomp/Makefile.in +++ b/dlls/vcomp/Makefile.in @@ -3,3 +3,7 @@ MODULE = vcomp.dll SOURCES = \ fork.c \ main.c + +LTO_SKIP_SRC = fork.c +i386_LTO_SKIP = yes +x86_64_LTO_SKIP = yes diff --git a/dlls/win32u/Makefile.in b/dlls/win32u/Makefile.in index 6326a3cd302..9c1912ab3c8 100644 --- a/dlls/win32u/Makefile.in +++ b/dlls/win32u/Makefile.in @@ -56,3 +56,7 @@ SOURCES = \ vulkan.c \ window.c \ winstation.c + +LTO_SKIP_SRC = main.c +i386_LTO_SKIP_SRC = dibdrv/primitives.c winstation.c +x86_64_LTO_SKIP_SRC = dibdrv/primitives.c winstation.c diff --git a/dlls/win87em.dll16/Makefile.in b/dlls/win87em.dll16/Makefile.in index 03bf1b5853b..2636f3e1205 100644 --- a/dlls/win87em.dll16/Makefile.in +++ b/dlls/win87em.dll16/Makefile.in @@ -3,3 +3,5 @@ EXTRADLLFLAGS = -m16
SOURCES = \ win87em.c + +LTO_SKIP = yes diff --git a/dlls/winebus.sys/Makefile.in b/dlls/winebus.sys/Makefile.in index db32faee5b3..a24aa9ba97e 100644 --- a/dlls/winebus.sys/Makefile.in +++ b/dlls/winebus.sys/Makefile.in @@ -14,3 +14,5 @@ SOURCES = \ main.c \ unixlib.c \ winebus.rc + +i386_LTO_SKIP_SRC = main.c diff --git a/dlls/winecrt0/Makefile.in b/dlls/winecrt0/Makefile.in index 863e5ed4190..df8818a31d5 100644 --- a/dlls/winecrt0/Makefile.in +++ b/dlls/winecrt0/Makefile.in @@ -21,3 +21,8 @@ SOURCES = \ setjmp.c \ stub.c \ unix_lib.c + +LTO_SKIP_SRC = setjmp.c +i386_LTO_SKIP_SRC = exception.c +x86_64_LTO_SKIP_SRC = exception.c +arm64ec_LTO_SKIP_SRC = arm64ec.c unix_lib.c diff --git a/dlls/wineusb.sys/Makefile.in b/dlls/wineusb.sys/Makefile.in index 0c6bb77f143..d4d58d5554b 100644 --- a/dlls/wineusb.sys/Makefile.in +++ b/dlls/wineusb.sys/Makefile.in @@ -10,3 +10,5 @@ SOURCES = \ unixlib.c \ wineusb.c \ wineusb.rc + +i386_LTO_SKIP_SRC = wineusb.c diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in index 9806dd350e9..1e814929d37 100644 --- a/dlls/winex11.drv/Makefile.in +++ b/dlls/winex11.drv/Makefile.in @@ -29,3 +29,5 @@ SOURCES = \ xrandr.c \ xrender.c \ xvidmode.c + +i386_LTO_SKIP_SRC = opengl.c diff --git a/dlls/winexinput.sys/Makefile.in b/dlls/winexinput.sys/Makefile.in index 64241631552..c07b7b8bd9f 100644 --- a/dlls/winexinput.sys/Makefile.in +++ b/dlls/winexinput.sys/Makefile.in @@ -5,3 +5,5 @@ EXTRADLLFLAGS = -Wl,--subsystem,native SOURCES = \ main.c \ winexinput.rc + +i386_LTO_SKIP = yes diff --git a/dlls/wow64/Makefile.in b/dlls/wow64/Makefile.in index b58b6eb803a..76a3cae7290 100644 --- a/dlls/wow64/Makefile.in +++ b/dlls/wow64/Makefile.in @@ -13,3 +13,5 @@ SOURCES = \ syscall.c \ system.c \ virtual.c + +LTO_SKIP_SRC = syscall.c diff --git a/dlls/wow64cpu/Makefile.in b/dlls/wow64cpu/Makefile.in index b06fc8f9f64..26b1d61087f 100644 --- a/dlls/wow64cpu/Makefile.in +++ b/dlls/wow64cpu/Makefile.in @@ -5,3 +5,5 @@ EXTRADLLFLAGS = -nodefaultlibs -Wl,--image-base,0x7a400000
SOURCES = \ cpu.c + +LTO_SKIP = yes diff --git a/dlls/xaudio2_7/Makefile.in b/dlls/xaudio2_7/Makefile.in index 0d88bfe6dd3..6ae757c9c47 100644 --- a/dlls/xaudio2_7/Makefile.in +++ b/dlls/xaudio2_7/Makefile.in @@ -10,3 +10,5 @@ SOURCES = \ xaudio_allocator.c \ xaudio_classes.idl \ xaudio_dll.c + +i386_LTO_SKIP_SRC = xaudio_dll.c diff --git a/loader/Makefile.in b/loader/Makefile.in index 191ab81e1d2..f9fde87d669 100644 --- a/loader/Makefile.in +++ b/loader/Makefile.in @@ -33,3 +33,6 @@ wine_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS) wine64_preloader_OBJS = preloader.o preloader_mac.o wine64_preloader_DEPS = $(WINELOADER_DEPENDS) wine64_preloader_LDFLAGS = $(WINEPRELOADER_LDFLAGS) + +# LTO_SKIP_SRC = preloader.c preloader_mac.c +LTO_SKIP = yes diff --git a/programs/rundll32/Makefile.in b/programs/rundll32/Makefile.in index f2aa9742e36..d2ddc87cc02 100644 --- a/programs/rundll32/Makefile.in +++ b/programs/rundll32/Makefile.in @@ -5,3 +5,5 @@ EXTRADLLFLAGS = -mwindows -municode
SOURCES = \ rundll32.c + +i386_LTO_SKIP = yes diff --git a/programs/wineboot/Makefile.in b/programs/wineboot/Makefile.in index 0983420a91f..81f31dc945d 100644 --- a/programs/wineboot/Makefile.in +++ b/programs/wineboot/Makefile.in @@ -9,3 +9,6 @@ SOURCES = \ wineboot.c \ wineboot.man.in \ wineboot.rc + +i386_LTO_SKIP_SRC = wineboot.c +x86_64_LTO_SKIP_SRC = wineboot.c diff --git a/tools/makedep.lto-skip.any.list b/tools/makedep.lto-skip.any.list new file mode 100644 index 00000000000..e24fec819e0 --- /dev/null +++ b/tools/makedep.lto-skip.any.list @@ -0,0 +1,17 @@ +dlls/msvcrt/except_arm.c +dlls/msvcrt/except_arm64.c +dlls/msvcrt/except_arm64ec.c +dlls/msvcrt/except_i386.c +dlls/msvcrt/except_x86_64.c +dlls/msvcrt/math.c +dlls/ntdll/relay.c +dlls/ntdll/signal_arm.c +dlls/ntdll/signal_arm64.c +dlls/ntdll/signal_arm64ec.c +dlls/ntdll/signal_i386.c +dlls/ntdll/signal_x86_64.c +dlls/ntdll/unix/signal_arm.c +dlls/ntdll/unix/signal_arm64.c +dlls/ntdll/unix/signal_i386.c +dlls/ntdll/unix/signal_x86_64.c +dlls/ntdll/unix/system.c diff --git a/tools/makedep.lto-skip.i386.list b/tools/makedep.lto-skip.i386.list new file mode 100644 index 00000000000..2147073a594 --- /dev/null +++ b/tools/makedep.lto-skip.i386.list @@ -0,0 +1,11 @@ +dlls/dinput/dinput.c +dlls/msvcrt/exception_ptr.c +dlls/msvcrt/file.c +dlls/msvcrt/misc.c +dlls/msvcrt/string.c +dlls/ntdll/large_int.c +dlls/ntdll/loader.c +dlls/ntdll/math.c +dlls/ntdll/resource.c +dlls/ntdll/rtl.c +dlls/ntdll/unix/loader.c diff --git a/tools/makedep.lto-skip.x86_64.list b/tools/makedep.lto-skip.x86_64.list new file mode 100644 index 00000000000..2edd78cfab4 --- /dev/null +++ b/tools/makedep.lto-skip.x86_64.list @@ -0,0 +1,3 @@ +dlls/msvcrt/string.c +dlls/ntdll/loader.c +dlls/ntdll/process.c
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150774
Your paranoid android.
=== debian11b (64 bit WoW report) ===
dmime: dmime.c:1950: Test failed: got mtTime 25, expected 24 dmime.c:1962: Test failed: got mtTime 50, expected 49 dmime.c:1974: Test failed: got mtTime 75, expected 74 dmime.c:1986: Test failed: got mtTime 125, expected 124 dmime.c:1998: Test failed: got mtTime 650, expected 649
Hi, thanks for tackling this issue. I think it's unfortunate Wine doesn't allow being built with LTO still, especially when some of the reason is that Wine's code is simply wrong—and it happens to work without LTO, but it's actually bad/undefined behavior.
But I think it's overcomplicated, especially the tool/build changes you've done. Why not just do something similar to my MR !4908? Why use environment variables for NM/AR/RANLIB? Autodetection could be done, but in the case of my MR, gcc prefixed versions are a superset (feature-wise) of the normal ar/nm/ranlib so using them unconditionally is totally fine, if they're available. Similar things are done for LLVM, I don't get why not for GCC.
Sadly I haven't got any comments on it, but I do think it's much simpler and has 0 configuration issues.
With respect to the other "skip source file" changes: I personally would prefer to isolate the reason those sources fail and fix that instead. With some asm functions it's harder (because of a GCC bug), but in many cases it's just a matter of applying the `used` attribute where applicable. Some functions are only called from asm code, so marking them as `used` is the right thing to do. Currently IMO it's actually undefined behavior since they're not exported, so we shouldn't rely on them not being cleaned up if unused.
I'd like to clarify changes:
- support building Wine with LTO is enabled via `--enable-lto` option for "./configure" script - "./configure" script appends `-D__WINE_LTO_BUILD` to CFLAGS (this may be useful somehow in future) - support for generating Makefile with LTO flags is done by `-L` option for "tools/makedep" (passed by "./configure --enable-lto") - "winebuild" and "winegcc" support `-flto` / `-fno-lto` options - all modified tools ("tools/makedep", "winebuild" and "winegcc") will pass at least `-flto` / `-fno-lto` to subsequent tools (see notes on environment variables below)
---
Environment variables for toolchain LTO flags:
`WINE_LTO_FLAGS` - flags to be passed for targets to be built with LTO; defaults to "-flto" if unspecified or empty.
`WINE_LTO_SKIP_FLAGS` - flags to be passed for targets to be built without LTO; defaults to "-fno-lto" if unspecified or empty.
Environment variables for tools:
`WINE_LTO_AR`, `WINE_LTO_NM`, `WINE_LTO_RANLIB` (used by "winebuild") - first priority tool for `ar`, `nm` and `ranlib` respectively. For GCC-based toolchain the one should specify "gcc-ar", "gcc-nm" and "gcc-ranlib" accordingly; for LLVM-based toolchain these are "llvm-ar", "llvm-nm" and "llvm-ranlib".
`WINE_LTO_DEBUG` (used by "winebuild" and "winegcc") - boolean switch to enable verbose mode without specifying command-line options; accepts "`1`", "`t`", "`true`", "`y`" and "`yes`" in all letter case variants.
These environment variables are used only if LTO switch was specified: `-L` for "tools/makedep" and `-flto` / `-fno-lto` for "winebuild" and "winegcc".
---
Hovewer, some sources/targets can't be built with LTO (due to current toolchain limitations).
There're two ways to build source without LTO:
1. via target's `Makefile.in`: specify file name in `LTO_SKIP_SRC` (for all architectures) or `${arch}_LTO_SKIP_SRC` variable, e.g.
```diff --- a/dlls/kernelbase/Makefile.in +++ b/dlls/kernelbase/Makefile.in @@ -26,3 +26,8 @@ SOURCES = \ version.c \ volume.c \ winerror.mc + +LTO_SKIP_SRC = debug.c thread.c +i386_LTO_SKIP_SRC = sync.c +x86_64_LTO_SKIP_SRC = loader.c +arm64ec_LTO_SKIP_SRC = loader.c ```
2. via `tools/makedep`-related skiplists (plain-text files, one file path per line) - `tools/makedep.lto-skip.any.list` (for all architectures) or `tools/makedep.lto-skip.${arch}.list`, e.g.
`tools/makedep.lto-skip.any.list`:
``` dlls/msvcrt/except_arm.c dlls/msvcrt/except_arm64.c dlls/msvcrt/except_arm64ec.c dlls/msvcrt/except_i386.c dlls/msvcrt/except_x86_64.c dlls/msvcrt/math.c ```
To build whole target without LTO, the one should add `LTO_SKIP` (for all architectures) or `${arch}_LTO_SKIP` boolean variable to target's `Makefile.in`, e.g.:
```diff --- a/programs/rundll32/Makefile.in +++ b/programs/rundll32/Makefile.in @@ -5,3 +5,5 @@ EXTRADLLFLAGS = -mwindows -municode
SOURCES = \ rundll32.c + +i386_LTO_SKIP = yes ```
My two cents: almost 3 months ago I've successfuly built Wine 9.20 with LTO using older version of this patchset.