diff --git a/premake4.lua b/premake4.lua index 05b45b1ae..cb4c14dbe 100644 --- a/premake4.lua +++ b/premake4.lua @@ -43,6 +43,10 @@ function newclangtoolchain(toolchain) } end +function is_clang() + return _OPTIONS.platform == "clang" or os.is_real("macosx") or os.is_real("ios") +end + newplatform { name = "clang", description = "Clang", @@ -182,6 +186,7 @@ newoption { description = "Set the shared data directory (default: /usr/share/ecode)", } newoption { trigger = "with-static-cpp", description = "Builds statically libstdc++" } +newoption { trigger = "with-lto", description = "Enables Link-Time Optimization for release builds." } function explode(div,str) if (div=='') then return false end @@ -747,6 +752,23 @@ function parse_args() if _OPTIONS["time-trace"] then buildoptions { "-ftime-trace" } end + + if _OPTIONS["with-lto"] and not os.is_real("emscripten") then + configuration "release" + + if is_vs() then + buildoptions { "/GL" } + linkoptions { "/LTCG" } + elseif is_clang() then + buildoptions { "-flto=thin" } + linkoptions { "-flto=thin" } + else + buildoptions { "-flto=auto" } + linkoptions { "-flto=auto" } + end + + configuration {} + end end function add_static_links() diff --git a/premake5.lua b/premake5.lua index ebca58aa2..86a7534b3 100644 --- a/premake5.lua +++ b/premake5.lua @@ -51,6 +51,7 @@ newoption { description = "Set the shared data directory", } newoption { trigger = "with-static-cpp", description = "Builds statically libstdc++" } +newoption { trigger = "with-lto", description = "Enables Link-Time Optimization for release builds." } function is_arm64_arch() local arch = _OPTIONS["arch"] @@ -714,6 +715,21 @@ function parse_args() if _OPTIONS["time-trace"] then buildoptions { "-ftime-trace" } end + + if _OPTIONS["with-lto"] then + filter { "configurations:release*", "toolset:gcc", "not system:emscripten" } + buildoptions { "-flto=auto" } + linkoptions { "-flto=auto" } + + filter { "configurations:release*", "toolset:clang", "not system:emscripten" } + buildoptions { "-flto=thin" } + linkoptions { "-flto=thin" } + + filter { "configurations:release*", "toolset:msc" } + linktimeoptimization "On" + + filter {} + end end function add_static_links() diff --git a/src/eepp/window/backend/SDL2/clipboardsdl2.cpp b/src/eepp/window/backend/SDL2/clipboardsdl2.cpp index 123ff5f42..885e8c16b 100644 --- a/src/eepp/window/backend/SDL2/clipboardsdl2.cpp +++ b/src/eepp/window/backend/SDL2/clipboardsdl2.cpp @@ -33,6 +33,17 @@ void ClipboardSDL::setText( const std::string& text ) { #if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN sContent = text; emscripten_browser_clipboard::copy( text ); +#elif EE_PLATFORM == EE_PLATFORM_WIN + // SDL2's Windows backend retries reads when another process owns the clipboard, but not + // writes. Clipboard ownership is transient, so mirror the read-side retry policy here. + static constexpr int MAX_ATTEMPTS = 3; + for ( int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt ) { + if ( SDL_SetClipboardText( text.c_str() ) == 0 ) + return; + if ( attempt + 1 < MAX_ATTEMPTS ) + SDL_Delay( 10 ); + } + Log::warning( "Failed to set clipboard text: %s", SDL_GetError() ); #else SDL_SetClipboardText( text.c_str() ); #endif diff --git a/src/tests/unit_tests/uimergeview_tests.cpp b/src/tests/unit_tests/uimergeview_tests.cpp index b32d7b3d7..4b12e4e85 100644 --- a/src/tests/unit_tests/uimergeview_tests.cpp +++ b/src/tests/unit_tests/uimergeview_tests.cpp @@ -2,7 +2,6 @@ #include #include #include -#include using namespace EE; using namespace EE::UI; @@ -82,9 +81,12 @@ UTEST( UIMergeView, UsesSharedResultDocumentAndAcceptIsUndoable ) { EXPECT_TRUE( view->isToolbarVisible() ); EXPECT_TRUE( view->hasCommand( "merge-accept-left" ) ); auto* leftEditor = view->getLeftEditor(); - leftEditor->getDocument().setSelection( { { 0, 0 }, { 0, 4 } } ); - leftEditor->getDocument().execute( "copy", leftEditor ); - EXPECT_STREQ( "left", app.getWindow()->getClipboard()->getText().c_str() ); + auto& leftDocument = leftEditor->getDocument(); + // Keep this hermetic: the Windows system clipboard can be temporarily owned by another + // process. The regression is that replacement side documents must retain the copy command. + EXPECT_TRUE( leftDocument.hasCommand( "copy" ) ); + leftDocument.setSelection( { { 0, 0 }, { 0, 4 } } ); + EXPECT_TRUE( leftDocument.getAllSelectedText() == "left" ); view->setToolbarVisible( false ); EXPECT_FALSE( view->isToolbarVisible() ); view->setToolbarVisible( true );