Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions tools/windows/install-abacus.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
@echo off
setlocal EnableExtensions EnableDelayedExpansion
title ABACUS for Windows (WSL2) Installer

set "DISTRO=Ubuntu-22.04"
set "INSTALL_DIR=%LOCALAPPDATA%\ABACUS"
set "BIN_DIR=%INSTALL_DIR%\bin"

echo =========================================
echo ABACUS Windows Installer (WSL2)
echo =========================================
echo.

REM --- 1. Admin check ---
net session >nul 2>&1
if errorlevel 1 (
echo [!] Please right-click this script and choose "Run as administrator".
pause
exit /b 1
)

REM --- 2. Windows build check (WSL2 requires 19041+) ---
for /f "tokens=4-6 delims=. " %%a in ('ver') do set "BUILD=%%c"
if %BUILD% LSS 19041 (
echo [!] Windows build %BUILD% detected.
echo [!] WSL2 requires Windows 10 build 19041 or newer, or Windows 11.
pause
exit /b 1
)

REM --- 2b. Offer China mirror (TUNA) for faster downloads ---
if not defined ABACUS_CHINA_MIRROR (
set "ABACUS_CHINA_MIRROR=0"
set /p CHINA_INPUT="Use TUNA mirror for faster downloads (recommended inside Mainland China)? (y/N): "
if /i "!CHINA_INPUT!"=="y" set "ABACUS_CHINA_MIRROR=1"
)

REM --- 3. Ensure WSL itself is present ---
where wsl >nul 2>&1
if errorlevel 1 (
echo [*] WSL not found. Installing WSL2 runtime...
wsl --install --no-launch
if errorlevel 1 (
echo [!] WSL installation failed.
echo [!] Make sure virtualization is enabled in BIOS/UEFI.
pause & exit /b 1
)
echo.
echo [!] WSL was just installed. Please REBOOT Windows,
echo [!] then run this script again to continue.
pause
exit /b 0
)

REM --- 4. Ensure target distro registered ---
echo [*] Probing WSL state. First call may take 30-60s while WSL2 cold-starts...
wsl --set-default-version 2 >nul 2>&1

REM Probe: if `wsl -d DISTRO -- true` returns 0, the distro already exists.
REM This avoids parsing `wsl -l -q` (UTF-16 output trips findstr).
set "DISTRO_PREEXISTED=1"
wsl -d %DISTRO% -u root -- /bin/true >nul 2>&1
if errorlevel 1 (
set "DISTRO_PREEXISTED=0"
echo [*] Installing %DISTRO% into WSL ^(this may take a few minutes^)...
wsl --install -d %DISTRO% --no-launch
if errorlevel 1 (
echo [!] Failed to install %DISTRO%. Reboot and retry, or run
echo [!] wsl --install -d %DISTRO%
echo [!] manually and finish any setup prompt, then re-run this script.
pause & exit /b 1
)
REM Poke the distro once as root so any first-run steps complete without OOBE.
wsl -d %DISTRO% -u root -- /bin/true >nul 2>&1
)

REM --- 5. Run provisioning script inside the distro ---
echo [*] Provisioning ABACUS via conda-forge inside %DISTRO%.
echo This downloads ~400 MB and takes 5-15 minutes on first run.
echo.

echo [*] Translating script path into WSL...
set "WSL_SCRIPT="
for /f "usebackq delims=" %%i in (`wsl -d %DISTRO% wslpath "%~dp0provision.sh" 2^>nul`) do set "WSL_SCRIPT=%%i"
if not defined WSL_SCRIPT (
echo [!] Could not translate script path into WSL. Aborting.
pause & exit /b 1
)

wsl -d %DISTRO% -u root -- env ABACUS_CHINA_MIRROR=!ABACUS_CHINA_MIRROR! bash "!WSL_SCRIPT!"
if errorlevel 1 (
echo [!] Provisioning failed. See output above.
pause & exit /b 1
)

REM --- 6. Install Windows-side launchers ---
if not exist "%BIN_DIR%" mkdir "%BIN_DIR%"

> "%BIN_DIR%\abacus.cmd" echo @echo off
>> "%BIN_DIR%\abacus.cmd" echo wsl -d %DISTRO% --cd "%%CD%%" -- abacus %%*

> "%BIN_DIR%\abacus-mpi.cmd" echo @echo off
>> "%BIN_DIR%\abacus-mpi.cmd" echo wsl -d %DISTRO% --cd "%%CD%%" -- abacus-mpi %%*

REM Record install state so the uninstaller knows whether we added the distro.
> "%INSTALL_DIR%\install-state.txt" echo distro=%DISTRO%
>> "%INSTALL_DIR%\install-state.txt" echo distro_preexisted=!DISTRO_PREEXISTED!

REM --- 7. Add BIN_DIR to user PATH (idempotent, no 1024-char truncation) ---
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$b='%BIN_DIR%'; $p=[Environment]::GetEnvironmentVariable('PATH','User'); if([string]::IsNullOrEmpty($p)){[Environment]::SetEnvironmentVariable('PATH',$b,'User')} elseif(($p -split ';') -notcontains $b){[Environment]::SetEnvironmentVariable('PATH',$p.TrimEnd(';')+';'+$b,'User')}"

echo.
echo =========================================
echo Installation complete!
echo =========================================
echo.
echo Open a NEW terminal window, cd into a case directory, then run:
echo abacus
echo.
echo For parallel execution with N processes:
echo abacus-mpi -n 4
echo.
echo To enter the Linux shell for advanced use:
echo wsl -d %DISTRO%
echo.
pause
exit /b 0
100 changes: 100 additions & 0 deletions tools/windows/provision.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env bash
# Provisions ABACUS inside a WSL2 Ubuntu distribution.
# Expected to run as root (installer invokes `wsl -u root`).

set -euo pipefail

MINIFORGE_DIR="/opt/abacus-miniforge"
ENV_NAME="abacus_env"
ENV_BIN="$MINIFORGE_DIR/envs/$ENV_NAME/bin"
CHINA_MIRROR="${ABACUS_CHINA_MIRROR:-0}"

if [ "$CHINA_MIRROR" = "1" ]; then
MINIFORGE_URL="https://mirrors.tuna.tsinghua.edu.cn/github-release/conda-forge/miniforge/LatestRelease/Miniforge3-Linux-x86_64.sh"
CONDA_FORGE_CHANNEL="https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge"
else
MINIFORGE_URL="https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh"
CONDA_FORGE_CHANNEL="conda-forge"
fi

log() { printf '[provision] %s\n' "$*"; }

if [ "$(id -u)" -ne 0 ]; then
echo "[provision] Must run as root." >&2
exit 1
fi

if [ "$CHINA_MIRROR" = "1" ]; then
log "China mirror mode: using TUNA (Tsinghua) for apt / Miniforge / conda-forge."
if [ -f /etc/apt/sources.list ] && grep -qE 'archive\.ubuntu\.com|security\.ubuntu\.com' /etc/apt/sources.list; then
log "Rewriting /etc/apt/sources.list to TUNA (backup at sources.list.orig)..."
cp -n /etc/apt/sources.list /etc/apt/sources.list.orig
sed -i \
-e 's|http://archive.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g' \
-e 's|http://security.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g' \
/etc/apt/sources.list
fi
fi

log "Installing apt prerequisites (apt-get update + curl/ca-certs/bzip2)..."
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y --no-install-recommends curl ca-certificates bzip2

if [ ! -x "$MINIFORGE_DIR/bin/conda" ]; then
log "Downloading Miniforge installer (~80 MB)..."
tmp="$(mktemp --suffix=.sh)"
trap 'rm -f "$tmp"' EXIT
curl -fL --progress-bar -o "$tmp" "$MINIFORGE_URL"
log "Installing Miniforge into $MINIFORGE_DIR..."
# Run the installer via its own shebang (dash on Ubuntu) rather than
# `bash installer.sh`. Some Miniforge builds have a sourced-check that
# misfires under bash and aborts with "Please run using bash/dash/...".
chmod +x "$tmp"
"$tmp" -b -p "$MINIFORGE_DIR"
rm -f "$tmp"
trap - EXIT
else
log "Miniforge already present at $MINIFORGE_DIR."
fi

# shellcheck disable=SC1091
source "$MINIFORGE_DIR/etc/profile.d/conda.sh"

if conda env list | awk 'NF && $1 !~ /^#/ {print $1}' | grep -qx "$ENV_NAME"; then
log "Updating existing env '$ENV_NAME' (channel: $CONDA_FORGE_CHANNEL)..."
conda install -n "$ENV_NAME" -y --override-channels -c "$CONDA_FORGE_CHANNEL" abacus
else
log "Creating env '$ENV_NAME' (channel: $CONDA_FORGE_CHANNEL)..."
conda create -n "$ENV_NAME" -y --override-channels -c "$CONDA_FORGE_CHANNEL" abacus
fi

log "Installing system launchers..."

cat > /usr/local/bin/abacus <<EOF
#!/usr/bin/env bash
source "$MINIFORGE_DIR/etc/profile.d/conda.sh"
conda activate "$ENV_NAME"
exec "$ENV_BIN/abacus" "\$@"
EOF
chmod +x /usr/local/bin/abacus

cat > /usr/local/bin/abacus-mpi <<EOF
#!/usr/bin/env bash
source "$MINIFORGE_DIR/etc/profile.d/conda.sh"
conda activate "$ENV_NAME"
exec mpirun "\$@" "$ENV_BIN/abacus"
EOF
chmod +x /usr/local/bin/abacus-mpi

log "Verifying..."
if /usr/local/bin/abacus --version >/dev/null 2>&1; then
/usr/local/bin/abacus --version || true
elif [ -x "$ENV_BIN/abacus" ]; then
log "abacus binary present at $ENV_BIN/abacus (no --version flag)."
else
log "WARNING: abacus binary not found after install."
exit 1
fi

log "Done."
70 changes: 70 additions & 0 deletions tools/windows/uninstall-abacus.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
@echo off
setlocal EnableExtensions EnableDelayedExpansion
title ABACUS Uninstaller

set "DISTRO=Ubuntu-22.04"
set "INSTALL_DIR=%LOCALAPPDATA%\ABACUS"
set "BIN_DIR=%INSTALL_DIR%\bin"
set "STATE_FILE=%INSTALL_DIR%\install-state.txt"

REM --- Read state file to learn whether the installer added the distro ---
set "DISTRO_PREEXISTED=1"
if exist "%STATE_FILE%" (
for /f "usebackq tokens=1,2 delims==" %%a in ("%STATE_FILE%") do (
if /i "%%a"=="distro_preexisted" set "DISTRO_PREEXISTED=%%b"
)
)

echo This will remove:
echo - Launchers under %BIN_DIR%
echo - %BIN_DIR% from your user PATH
if "!DISTRO_PREEXISTED!"=="0" (
echo.
echo The installer added the '%DISTRO%' WSL distribution.
echo You can either remove the whole distribution, or just remove the
echo ABACUS files inside it and keep the Linux environment.
) else (
echo - /opt/abacus-miniforge inside WSL ^(%DISTRO%^)
echo.
echo The %DISTRO% distribution existed before installation and will NOT be removed.
)
echo.

set /p CONFIRM="Continue? (y/N): "
if /i not "!CONFIRM!"=="y" (
echo Aborted.
exit /b 0
)

set "REMOVED_DISTRO=0"
if "!DISTRO_PREEXISTED!"=="0" (
echo.
set /p REMOVE_DISTRO="Remove the entire '%DISTRO%' WSL distribution? This wipes all files inside it. (y/N): "
if /i "!REMOVE_DISTRO!"=="y" (
echo [*] Unregistering %DISTRO%...
wsl --unregister %DISTRO%
if not errorlevel 1 set "REMOVED_DISTRO=1"
)
)

if "!REMOVED_DISTRO!"=="0" (
where wsl >nul 2>&1
if not errorlevel 1 (
wsl -d %DISTRO% -u root -- /bin/true >nul 2>&1
if not errorlevel 1 (
echo [*] Removing conda env and launchers inside %DISTRO%...
wsl -d %DISTRO% -u root -- bash -c "rm -rf /opt/abacus-miniforge /usr/local/bin/abacus /usr/local/bin/abacus-mpi"
)
)
)

if exist "%BIN_DIR%" rd /s /q "%BIN_DIR%"
if exist "%INSTALL_DIR%" rd /s /q "%INSTALL_DIR%"

powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$b='%BIN_DIR%'; $p=[Environment]::GetEnvironmentVariable('PATH','User'); if($p){$n=(($p -split ';') | Where-Object { $_ -and ($_ -ne $b) }) -join ';'; [Environment]::SetEnvironmentVariable('PATH',$n,'User')}"

echo.
echo Uninstall complete.
pause
exit /b 0
Loading