anchor.diff:  REM Build deps
   :BUILD_DEPS
   SET EXIT_STATUS=3
  -IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY deps\build
  +SET PS_CURRENT_STEP=deps
  +IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY deps\build "%PS_DEPS_PATH_FILE_NAME%"
   cd deps\build || GOTO :END
  -IF "%PS_STEPS_DIRTY%" EQU "" cmake.exe .. -DDESTDIR="%PS_DESTDIR%" || GOTO :END
  +cmake.exe .. -DDESTDIR="%PS_DESTDIR%" || GOTO :END
   (echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE%"
   msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% || GOTO :END
   cd ..\..
  -IF /I "%PS_STEPS:~0,4%" EQU "deps" GOTO :PROLOGUE
  +IF /I "%PS_STEPS:~0,4%" EQU "deps" GOTO :RUN_APP
   
   REM Build app
   :BUILD_APP
   SET EXIT_STATUS=4
  -IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY build
  +SET PS_CURRENT_STEP=app
  +IF "%PS_STEPS_DIRTY%" EQU "" CALL :MAKE_OR_CLEAN_DIRECTORY build "%PS_CUSTOM_RUN_FILE%"
   cd build || GOTO :END
  -IF "%PS_STEPS_DIRTY%" EQU "" cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" || GOTO :END
  -msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% || GOTO :END
  +REM Make sure we have a custom batch file skeleton for the run stage
  +set PS_CUSTOM_BAT=%PS_CUSTOM_RUN_FILE%
  +CALL :CANONICALIZE_PATH PS_CUSTOM_BAT
  +IF NOT EXIST %PS_CUSTOM_BAT% CALL :WRITE_CUSTOM_SCRIPT_SKELETON %PS_CUSTOM_BAT%
  +SET PS_PROJECT_IS_OPEN=
  +FOR /F "tokens=2 delims=," %%I in (
  +    'tasklist /V /FI "IMAGENAME eq devenv.exe " /NH /FO CSV ^| find "%PS_SOLUTION_NAME%"'
  +) do SET PS_PROJECT_IS_OPEN=%%~I
  +cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" -DCMAKE_CONFIGURATION_TYPES=%PS_CONFIG_LIST% || GOTO :END
  +REM Skip the build step if we're using the undocumented app-cmake to regenerate the full config from inside devenv
  +IF "%PS_STEPS%" NEQ "app-cmake" msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% || GOTO :END
  +(echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE_FOR_CONFIG%"
  +
  +REM Run app
  +:RUN_APP
  +REM All build steps complete.
  +CALL :DIFF_TIME ELAPSED_TIME %START_TIME% %TIME%
  +IF "%PS_CURRENT_STEP%" NEQ "arguments" (
  +    @ECHO.
  +    @ECHO Total Build Time Elapsed %ELAPSED_TIME%
  +)
  +SET EXIT_STATUS=5
  +SET PS_CURRENT_STEP=run
  +cd src\%PS_CONFIG% || GOTO :END
  +IF "%PS_RUN%" EQU "none" GOTO :PROLOGUE
  +SET PS_PROJECT_IS_OPEN=
  +FOR /F "tokens=2 delims=," %%I in (
  +    'tasklist /V /FI "IMAGENAME eq devenv.exe " /NH /FO CSV ^| find "%PS_SOLUTION_NAME%"'
  +) do SET PS_PROJECT_IS_OPEN=%%~I
  +@ECHO.
  +@ECHO Running %PS_RUN% application...
  +@REM icacls below is just a hack for file-not-found error handling
  +IF "%PS_RUN%" EQU "console" (
  +    icacls prusa-slicer-console.exe >nul || GOTO :END
  +    start /wait /b prusa-slicer-console.exe
  +) ELSE IF "%PS_RUN%" EQU "window" (
  +    icacls prusa-slicer.exe >nul || GOTO :END
  +    start prusa-slicer.exe
  +) ELSE IF "%PS_RUN%" EQU "viewer" (
  +    icacls prusa-gcodeviewer.exe >nul || GOTO :END
  +    start prusa-gcodeviewer.exe
  +) ELSE IF "%PS_RUN%" EQU "custom" (
  +    icacls %PS_CUSTOM_BAT% >nul || GOTO :END
  +    CALL %PS_CUSTOM_BAT%
  +) ELSE IF "%PS_RUN%" EQU "ide" (
  +    IF "%PS_PROJECT_IS_OPEN%" NEQ "" (
  +        @ECHO WARNING: Solution is already open in Visual Studio. Skipping ide run step. 1>&2
  +    ) ELSE (
  +        @ECHO Preparing to run Visual Studio...
  +        cd ..\.. || GOTO :END
  +        REM This hack generates a single config for MSVS, guaranteeing it gets set as the active config.
  +        cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" -DCMAKE_CONFIGURATION_TYPES=%PS_CONFIG% > nul 2> nul || GOTO :END
  +        REM Now launch devenv with the single config (setting it active) and a /command switch to re-run cmake and generate the full config list
  +        start devenv.exe %PS_SOLUTION_NAME%.sln /command ^"shell /o ^^^"%~f0^^^" -d ^^^"%PS_DESTDIR%^^^" -c %PS_CONFIG% -a %PS_ARCH% -r none -s app-cmake^"
  +        REM If devenv fails to launch just directly regenerate the full config list.
  +        IF %ERRORLEVEL% NEQ 0 (
  +            cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" -DCMAKE_CONFIGURATION_TYPES=%PS_CONFIG_LIST% 2> nul 1> nul || GOTO :END
  +        )
  +    )
  +)
  +
  +@REM **********    DON'T ADD ANY CODE BETWEEN THESE TWO SECTIONS    **********
  +@REM RUN_APP may hand off control, so let exit codes fall through to PROLOGUE.
   
   :PROLOGUE
   SET EXIT_STATUS=%ERRORLEVEL%
   :END
   @IF "%PS_ECHO_ON%%PS_DRY_RUN_ONLY%" NEQ "" (
  -    @ECHO Script Parameters:
  +    @ECHO **********************************************************************
  +    @ECHO ** Script Parameters:
  +    @ECHO **********************************************************************
       @SET PS_
   )
  -@ECHO Script started at %START_TIME% and completed at %TIME%.
  +IF "%EXIT_STATUS%" NEQ "0" (
  +    IF "%PS_CURRENT_STEP%" NEQ "arguments" (
  +        @ECHO.
  +        @ECHO ERROR: *** Build process failed at %PS_CURRENT_STEP% step. *** 1>&2
  +    )
  +) ELSE (
  +    @ECHO All steps completed successfully.
  +)
   popd
   exit /B %EXIT_STATUS%
   
   GOTO :EOF
   REM Functions and stubs start here.
  +
  +:RESOLVE_DESTDIR_CACHE
  +@REM Resolves all DESTDIR cache values and sets PS_STEPS_DEFAULT
  +@REM Note: This just sets global variableq, so it doesn't use setlocal.
  +SET PS_DEPS_PATH_FILE_FOR_CONFIG=%~dp0build\%PS_ARCH%\%PS_CONFIG%\%PS_DEPS_PATH_FILE_NAME%
  +CALL :CANONICALIZE_PATH PS_DEPS_PATH_FILE_FOR_CONFIG
  +IF EXIST "%PS_DEPS_PATH_FILE_FOR_CONFIG%" (
  +    FOR /F "tokens=* USEBACKQ" %%I IN ("%PS_DEPS_PATH_FILE_FOR_CONFIG%") DO (
  +        SET PS_DESTDIR_CACHED=%%I
  +        SET PS_DESTDIR_DEFAULT_MSG=%%I
  +    )
  +    SET PS_STEPS_DEFAULT=app-dirty
  +) ELSE IF EXIST "%PS_DEPS_PATH_FILE%" (
  +    FOR /F "tokens=* USEBACKQ" %%I IN ("%PS_DEPS_PATH_FILE%") DO (
  +        SET PS_DESTDIR_CACHED=%%I
  +        SET PS_DESTDIR_DEFAULT_MSG=%%I
  +    )
  +    SET PS_STEPS_DEFAULT=app
  +) ELSE (
  +    SET PS_DESTDIR_CACHED=
  +    SET PS_DESTDIR_DEFAULT_MSG=Cache missing. Argument required.
  +    SET PS_STEPS_DEFAULT=all
  +)
  +GOTO :EOF
   
   :PARSE_OPTION
   @REM Argument parser called for each argument
  
positive.code: )
  @(echo %OPTION_NAME%)| findstr /R /C:".[ ][ ]*.">nul && GOTO :PARSE_OPTION_NAME_FAIL
  @(echo  %~1 )| findstr /I /C:" %OPTION_NAME% ">nul || GOTO :PARSE_OPTION_NAME_FAIL
  endlocal & SET %~2=%OPTION_NAME%
  GOTO :EOF
  :PARSE_OPTION_NAME_FAIL
  
negative.code: @IF "%PS_ECHO_ON%" NEQ "" (echo on) ELSE (echo off)
  @GOTO :MAIN
  :HELP
  @ECHO.
  @ECHO Performs initial build or rebuild of the app (build) and deps (build/deps).
  @ECHO Default options are determined from build directories and system state.
  @ECHO.
  @ECHO Usage: build_win [-ARCH ^<arch^>] [-CONFIG ^<config^>] [-DESTDIR ^<directory^>]
  @ECHO                  [-STEPS ^<all^|all-dirty^|app^|app-dirty^|deps^|deps-dirty^>]
  @ECHO                  [-RUN ^<console^|custom^|none^|viewer^|window^>]
  @ECHO.
  @ECHO  -a -ARCH      Target processor architecture
  @ECHO                Default: %PS_ARCH_HOST%
  @ECHO  -c -CONFIG    MSVC project config
  @ECHO                Default: %PS_CONFIG_DEFAULT%
  @ECHO  -s -STEPS     Performs only the specified build steps:
  @ECHO                  all - clean and build deps and app
  @ECHO                  all-dirty - build deps and app without cleaning
  @ECHO                  app - clean and build main applications
  @ECHO                  app-dirty - build main applications without cleaning
  @ECHO                  deps - clean and build deps
  @ECHO                  deps-dirty - build deps without cleaning
  @ECHO                Default: %PS_STEPS_DEFAULT%
  @ECHO  -r -RUN       Specifies what to perform at the run step:
  @ECHO                  console - run and wait on prusa-slicer-console.exe
  @ECHO                  custom - run and wait on your custom build/%PS_CUSTOM_RUN_FILE%
  @ECHO                  ide - open project in Visual Studio if not open (no wait)
  @ECHO                  none - run step does nothing
  @ECHO                  viewer - run prusa-gcodeviewer.exe (no wait)
  @ECHO                  window - run prusa-slicer.exe (no wait)
  @ECHO                Default: none
  @ECHO  -d -DESTDIR   Deps destination directory
  @ECHO                Warning: Changing destdir path will not delete the old destdir.
  @ECHO                Default: %PS_DESTDIR_DEFAULT_MSG%
  @ECHO.
  @ECHO  Examples:
  @ECHO.
  @ECHO  Initial build:           build_win -d "c:\src\PrusaSlicer-deps"
  @ECHO  Build post deps change:  build_win -s all
  @ECHO  App dirty build:         build_win
  @ECHO  App dirty build ^& run:   build_win -r console
  @ECHO  All clean build ^& run:   build_win -s all -r console -d "deps\build\out_deps"
  @ECHO.
  GOTO :END
  
  :MAIN
  REM Script constants
  SET START_TIME=%TIME%
  SET PS_START_DIR=%CD%
  SET PS_SOLUTION_NAME=PrusaSlicer
  SET PS_CHOICE_TIMEOUT=30
  SET PS_CUSTOM_RUN_FILE=custom_run.bat
  SET PS_DEPS_PATH_FILE_NAME=.DEPS_PATH.txt
  SET PS_DEPS_PATH_FILE=%~dp0deps\build\%PS_DEPS_PATH_FILE_NAME%
  SET PS_CONFIG_LIST="Debug;MinSizeRel;Release;RelWithDebInfo"
  
  REM Probe build directories and system state for reasonable default arguments
  pushd %~dp0
  SET PS_CONFIG=RelWithDebInfo
  SET PS_ARCH=%PROCESSOR_ARCHITECTURE:amd64=x64%
  CALL :TOLOWER PS_ARCH
  SET PS_RUN=none
  SET PS_DESTDIR=
  CALL :RESOLVE_DESTDIR_CACHE
  
  REM Set up parameters used by help menu
  SET PS_CONFIG_DEFAULT=%PS_CONFIG%
  SET PS_ARCH_HOST=%PS_ARCH%
  (echo " -help /help -h /h -? /? ")| findstr /I /C:" %~1 ">nul && GOTO :HELP
  
  REM Parse arguments
  SET EXIT_STATUS=1
  SET PS_CURRENT_STEP=arguments
  SET PARSER_STATE=
  SET PARSER_FAIL=
  FOR %%I in (%*) DO CALL :PARSE_OPTION "ARCH CONFIG DESTDIR STEPS RUN" PARSER_STATE "%%~I"
  IF "%PARSER_FAIL%" NEQ "" (
      @ECHO ERROR: Invalid switch: %PARSER_FAIL% 1>&2
      GOTO :HELP
  