Windows installer

This commit is contained in:
2026-08-24 14:47:14 +03:00
Unverified
parent d25cb7e57a
commit 529e090b25
61 changed files with 7395 additions and 49 deletions
+53
View File
@@ -0,0 +1,53 @@
@echo off
setlocal EnableExtensions
if /I "%1"=="sync" (
call "%~dp0sync-windows-vm.cmd" %2
exit /b %ERRORLEVEL%
)
call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" arm64
if errorlevel 1 exit /b 1
set "JAVA_HOME_17=C:\Program Files\Eclipse Adoptium\jdk-17.0.20.8-hotspot"
set "JAVA_HOME_21=C:\Program Files\Eclipse Adoptium\jdk-21.0.10.7-hotspot"
for /d %%D in ("C:\Program Files\Eclipse Adoptium\jdk-17*") do set "JAVA_HOME_17=%%D"
for /d %%D in ("C:\Program Files\Eclipse Adoptium\jdk-21*") do set "JAVA_HOME_21=%%D"
set "JAVA_HOME=%JAVA_HOME_21%"
set "FROMCHAT_PACKAGING_JDK=%JAVA_HOME_17%"
set "PATH=%JAVA_HOME%\bin;C:\WINDOWS\system32\config\systemprofile\.cargo\bin;%PATH%"
cd /d C:\FromChat\app
if exist gradle\gradle-daemon-jvm.properties del /f gradle\gradle-daemon-jvm.properties
if /I "%1"=="rust" (
call "%~dp0sync-windows-vm.cmd" rust
if errorlevel 1 exit /b 1
cd app\desktop\windows-setup
cargo build --release --workspace
exit /b %ERRORLEVEL%
)
if /I "%1"=="pack" (
call "%~dp0sync-windows-vm.cmd" rust
if errorlevel 1 exit /b 1
if exist gradle\gradle-daemon-jvm.properties del /f gradle\gradle-daemon-jvm.properties
gradlew.bat :app:desktop:packSetupOnly --no-daemon
if errorlevel 1 exit /b 1
call "%~dp0copy-installers-to-desktop.cmd"
exit /b %ERRORLEVEL%
)
if /I "%1"=="gradle" (
call "%~dp0sync-windows-vm.cmd" gradle
if errorlevel 1 exit /b 1
if exist gradle\gradle-daemon-jvm.properties del /f gradle\gradle-daemon-jvm.properties
gradlew.bat :app:desktop:packageReleaseWindows --no-daemon
if errorlevel 1 exit /b 1
call "%~dp0copy-installers-to-desktop.cmd"
exit /b %ERRORLEVEL%
)
echo Usage: build-windows-vm.cmd sync [all^|rust^|scripts^|gradle]
echo build-windows-vm.cmd rust ^(sync windows-setup, then cargo build^)
echo build-windows-vm.cmd pack ^(sync, rust, packSetupOnly — fast UI loop^)
echo build-windows-vm.cmd gradle ^(sync, full packageReleaseWindows, copy to Desktop^)
exit /b 1
+83
View File
@@ -0,0 +1,83 @@
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Copy packaged Windows installer to the logged-in user's Desktop.
rem prlctl exec runs as SYSTEM, so do not rely on %%USERPROFILE%%.
set "DIST=C:\FromChat\app\app\desktop\build\distributions\release"
set "WIN_DESKTOP="
set "COPIED=0"
if not exist "%DIST%\" (
echo WARNING: Release output folder missing: %DIST%
exit /b 0
)
for /f "skip=1 tokens=1" %%U in ('query user 2^>nul') do (
if not defined LOGON set "LOGON=%%U"
)
if defined LOGON set "WIN_DESKTOP=C:\Users\%LOGON%\Desktop"
if not exist "%WIN_DESKTOP%\" (
for /d %%D in ("C:\Users\*") do (
if not defined WIN_DESKTOP (
echo %%~nxD | findstr /i /x "Public Default DefaultAccount WsiAccount" >nul
if errorlevel 1 if exist "%%D\Desktop\" set "WIN_DESKTOP=%%D\Desktop"
)
)
)
if not defined WIN_DESKTOP (
echo ERROR: Could not resolve Windows user Desktop path
exit /b 1
)
call :kill_running_installers
for %%F in ("%DIST%\FromChat-Portable-*.exe") do (
if exist "%%F" (
del /F /Q "%%F" >nul 2>&1
echo Removed stale portable build output: %%~nxF
)
)
for %%F in ("%WIN_DESKTOP%\FromChat-Portable-*.exe") do (
if exist "%%F" (
del /F /Q "%%F" >nul 2>&1
echo Removed stale portable artifact: %%~nxF
)
)
for %%F in ("%DIST%\FromChat-Setup-*.exe") do (
if exist "%%F" (
call :copy_installer "%%~fF" "%WIN_DESKTOP%"
if errorlevel 1 exit /b 1
set "COPIED=1"
)
)
if "!COPIED!"=="0" (
echo WARNING: No FromChat-Setup-*.exe found in %DIST%
)
exit /b 0
:kill_running_installers
echo Stopping running FromChat installer processes...
powershell -NoProfile -Command ^
"$names = @('fromchat-setup','FromChat-Setup*','FromChat-Portable*');" ^
"foreach ($n in $names) { Get-Process -Name $n -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue }" ^
2>nul
ping -n 2 127.0.0.1 >nul
exit /b 0
:copy_installer
set "SRC=%~1"
set "DEST_DIR=%~2"
copy /Y "%SRC%" "%DEST_DIR%\" >nul 2>&1
if errorlevel 1 (
echo ERROR: Failed to copy %~nx1 to %DEST_DIR% — close the running installer and retry
exit /b 1
)
echo Copied %~nx1 -^> %DEST_DIR%
exit /b 0
+99
View File
@@ -0,0 +1,99 @@
$ErrorActionPreference = "Stop"
function Ensure-Jdk17 {
$adoptium = "C:\Program Files\Eclipse Adoptium"
$jdkHome = Get-ChildItem $adoptium -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like "jdk-17*" } |
Sort-Object Name -Descending |
Select-Object -First 1
if ($jdkHome) { return $jdkHome.FullName }
Write-Host "Downloading Temurin JDK 17..."
$msi = Join-Path $env:TEMP "temurin-jdk17.msi"
Invoke-WebRequest `
-Uri "https://api.adoptium.net/v3/installer/latest/17/ga/windows/x64/jdk/hotspot/normal/eclipse?project=jdk" `
-OutFile $msi `
-UseBasicParsing
Write-Host "Installing Temurin JDK 17..."
$args = @("/i", $msi, "/qn", "ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome")
$p = Start-Process msiexec.exe -ArgumentList $args -Wait -PassThru
if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) { throw "JDK 17 installer exit code $($p.ExitCode)" }
$jdkHome = Get-ChildItem $adoptium -Directory | Where-Object { $_.Name -like "jdk-17*" } | Sort-Object Name -Descending | Select-Object -First 1
if (-not $jdkHome) { throw "JDK 17 install failed" }
return $jdkHome.FullName
}
function Ensure-Jdk21 {
$adoptium = "C:\Program Files\Eclipse Adoptium"
$jdkHome = Get-ChildItem $adoptium -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like "jdk-21*" } |
Sort-Object Name -Descending |
Select-Object -First 1
if ($jdkHome) { return $jdkHome.FullName }
Write-Host "Downloading Temurin JDK 21..."
$msi = Join-Path $env:TEMP "temurin-jdk21.msi"
Invoke-WebRequest `
-Uri "https://api.adoptium.net/v3/installer/latest/21/ga/windows/x64/jdk/hotspot/normal/eclipse?project=jdk" `
-OutFile $msi `
-UseBasicParsing
Write-Host "Installing Temurin JDK 21..."
$args = @("/i", $msi, "/qn", "ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome")
$p = Start-Process msiexec.exe -ArgumentList $args -Wait -PassThru
if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) { throw "JDK 21 installer exit code $($p.ExitCode)" }
$jdkHome = Get-ChildItem $adoptium -Directory | Where-Object { $_.Name -like "jdk-21*" } | Sort-Object Name -Descending | Select-Object -First 1
if (-not $jdkHome) { throw "JDK 21 install failed" }
return $jdkHome.FullName
}
function Ensure-Rust {
$cargo = Join-Path $env:USERPROFILE ".cargo\bin\cargo.exe"
if (Test-Path $cargo) { return $cargo }
Write-Host "Downloading rustup..."
$rustup = Join-Path $env:TEMP "rustup-init.exe"
Invoke-WebRequest -Uri "https://win.rustup.rs/x86_64" -OutFile $rustup -UseBasicParsing
Write-Host "Installing Rust..."
$p = Start-Process $rustup -ArgumentList @("-y", "--default-toolchain", "stable", "--profile", "minimal") -Wait -PassThru
if ($p.ExitCode -ne 0) { throw "rustup exit code $($p.ExitCode)" }
if (-not (Test-Path $cargo)) { throw "cargo not found after rustup" }
return $cargo
}
function Ensure-VsBuildTools {
$link = Get-Command link.exe -ErrorAction SilentlyContinue
if ($link) { return $link.Source }
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
if (Test-Path $vswhere) {
$installPath = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath 2>$null
if ($installPath) {
$candidate = Join-Path $installPath "VC\Tools\MSVC"
if (Test-Path $candidate) { return $installPath }
}
}
Write-Host "Downloading VS Build Tools..."
$bootstrapper = Join-Path $env:TEMP "vs_BuildTools.exe"
Invoke-WebRequest -Uri "https://aka.ms/vs/17/release/vs_BuildTools.exe" -OutFile $bootstrapper -UseBasicParsing
Write-Host "Installing VS Build Tools (this may take several minutes)..."
$args = @(
"--quiet", "--wait", "--norestart",
"--add", "Microsoft.VisualStudio.Workload.VCTools",
"--includeRecommended"
)
$p = Start-Process $bootstrapper -ArgumentList $args -Wait -PassThru
if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) {
throw "VS Build Tools exit code $($p.ExitCode)"
}
$link = Get-Command link.exe -ErrorAction SilentlyContinue
if (-not $link) {
throw "link.exe still not found after VS Build Tools install"
}
return $link.Source
}
$javaHome17 = Ensure-Jdk17
Write-Host "JAVA_HOME_17=$javaHome17"
$javaHome21 = Ensure-Jdk21
Write-Host "JAVA_HOME_21=$javaHome21"
$cargo = Ensure-Rust
Write-Host "CARGO=$cargo"
$link = Ensure-VsBuildTools
Write-Host "LINK=$link"
Write-Host "OK"
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
VM_NAME="${FROMCHAT_WINDOWS_VM:-Windows 11}"
SCOPE="${1:-all}"
if ! command -v prlctl >/dev/null 2>&1; then
echo "prlctl not found — run sync-windows-vm.cmd inside the VM instead" >&2
exit 1
fi
prlctl exec "$VM_NAME" cmd /c "C:\\FromChat\\app\\scripts\\sync-windows-vm.cmd ${SCOPE}"
+51
View File
@@ -0,0 +1,51 @@
@echo off
setlocal EnableExtensions
rem Sync Mac workspace share -> local VM copy.
rem Uses /E (not /MIR) so VM-only build caches (target, build, .gradle) are never deleted.
set "SRC=C:\Mac\Home\Desktop\FromChat\app"
set "DEST=C:\FromChat\app"
if not exist "%SRC%\" (
echo ERROR: Mac share not found at %SRC%
echo Enable Parallels shared folders or adjust SRC in sync-windows-vm.cmd
exit /b 1
)
if not exist "%DEST%\" mkdir "%DEST%"
set "OPTS=/E /R:2 /W:2 /NP /NFL /NDL"
set "CACHE=/XD target build .gradle node_modules .git"
set "SKIP=/XF gradle-daemon-jvm.properties"
if /I "%~1"=="rust" (
echo Syncing app\desktop\windows-setup ^(keeping target\^)...
robocopy "%SRC%\app\desktop\windows-setup" "%DEST%\app\desktop\windows-setup" %OPTS% /XD target
goto :finish
)
if /I "%~1"=="scripts" (
echo Syncing scripts...
robocopy "%SRC%\scripts" "%DEST%\scripts" %OPTS%
goto :finish
)
if /I "%~1"=="gradle" (
echo Syncing app tree for Gradle ^(keeping build caches^)...
robocopy "%SRC%" "%DEST%" %OPTS% %CACHE% %SKIP%
goto :finish
)
echo Syncing full app tree ^(preserving target, build, .gradle^)...
robocopy "%SRC%" "%DEST%" %OPTS% %CACHE% %SKIP%
goto :finish
:finish
set "RC=%ERRORLEVEL%"
rem Robocopy: 0-7 = success (0 = nothing to copy, 1+ = copied files)
if %RC% GEQ 8 (
echo robocopy failed with exit code %RC%
exit /b %RC%
)
exit /b 0