mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Publish a Windows setup beside the AppImage and the disk image
The releases page had nothing for Windows, so the only way in was a checkout, a Python and a pip install. What goes out now is one setup program per release: PyInstaller's directory, the pinned ffmpeg the disk image already uses, and Inno Setup around both. It installs for the account alone, so no administrator is asked for. Two executables over the one program there, because a windowed one on Windows has no standard output at all: Dikte.exe for the Start Menu and dikte.exe for the terminal, sharing everything they carry. The icon is drawn by Dikte itself into an .ico, the way the Mac's .icns and Linux's PNGs already are, so there is still no image file in the repository. Starting at sign-in is a registry value rather than a Startup shortcut, which is what lets the setup program, the uninstaller and `dikte integrate` all mean the same thing: the wizard asks once, and typing the command changes the answer later. The three builds move into build.yml, which release.yml now calls instead of holding its own copy, and which a pull request touching the packaging runs on its own. A broken build is then a red pull request rather than a failed release.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# The Windows download: one setup program, carrying everything Dikte needs to
|
||||
# record and to be started again after a sign-in.
|
||||
#
|
||||
# Run from anywhere; it works in build\ at the top of the checkout and leaves
|
||||
# the finished .exe in dist\. x64 only, because that is what the PyQt6 wheel and
|
||||
# whisper.cpp both publish for Windows; a Windows on ARM machine runs it under
|
||||
# the emulation it runs everything else under.
|
||||
#
|
||||
# powershell -ExecutionPolicy Bypass -File packaging\build-windows.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$build = Join-Path $root "build"
|
||||
$out = Join-Path $root "dist"
|
||||
$dist = Join-Path $build "dist\dikte"
|
||||
|
||||
$env:PYTHONPATH = $root
|
||||
$version = & python -c "import dikte; print(dikte.__version__)"
|
||||
if ($LASTEXITCODE -ne 0) { throw "could not read the version out of dikte/__init__.py" }
|
||||
|
||||
# A pinned tag and a checksum rather than "whatever is newest": this binary goes
|
||||
# out inside something people run, so what it is has to be decided here and not
|
||||
# by whoever pushes to that repository next. The same release the disk image
|
||||
# takes its ffmpeg from, which is gyan.dev's essentials build repackaged, and
|
||||
# dshow is in it, which is the one part of ffmpeg recording here goes through.
|
||||
$ffmpegTag = "b6.1.1"
|
||||
$ffmpegAsset = "ffmpeg-win32-x64.gz"
|
||||
$ffmpegSha = "8883A3DFFBD0A16CF4EF95206EA05283F78908DBFB118F73C83F4951DCC06D77"
|
||||
|
||||
if (Test-Path $build) { Remove-Item $build -Recurse -Force }
|
||||
if (Test-Path $out) { Remove-Item $out -Recurse -Force }
|
||||
New-Item -ItemType Directory -Path $build, $out | Out-Null
|
||||
|
||||
# 1. The icon ---------------------------------------------------------------
|
||||
# Drawn by Dikte itself, offscreen, which is why there is no image file in the
|
||||
# repository. Before the application, because PyInstaller writes it into the
|
||||
# executable rather than beside it, and the setup program uses the same file.
|
||||
$icon = Join-Path $build "Dikte.ico"
|
||||
$env:QT_QPA_PLATFORM = "offscreen"
|
||||
& python -m dikte.trayicon --ico $icon
|
||||
if ($LASTEXITCODE -ne 0) { throw "the icon would not draw" }
|
||||
Remove-Item Env:\QT_QPA_PLATFORM
|
||||
$env:DIKTE_ICO = $icon
|
||||
|
||||
# 2. The application --------------------------------------------------------
|
||||
# Two executables in the one directory: Dikte.exe, which is windowed and is
|
||||
# what a shortcut starts, and dikte.exe, which has a console and is what the
|
||||
# `dikte` command runs.
|
||||
& python -m PyInstaller (Join-Path $root "packaging\dikte.spec") `
|
||||
--distpath (Join-Path $build "dist") --workpath (Join-Path $build "work") `
|
||||
--noconfirm --clean
|
||||
if ($LASTEXITCODE -ne 0) { throw "PyInstaller failed" }
|
||||
|
||||
# 3. ffmpeg -----------------------------------------------------------------
|
||||
# Recording on Windows goes through ffmpeg's DirectShow input, and Windows
|
||||
# ships nothing like it, so without this the download would be an application
|
||||
# that cannot record until the person who downloaded it installs one. bin\
|
||||
# beside the executables, because integrate.py puts that directory in front of
|
||||
# PATH at startup and everything reaching for ffmpeg goes through shutil.which.
|
||||
$archive = Join-Path $build $ffmpegAsset
|
||||
Invoke-WebRequest -UseBasicParsing -OutFile $archive `
|
||||
"https://github.com/eugeneware/ffmpeg-static/releases/download/$ffmpegTag/$ffmpegAsset"
|
||||
$got = (Get-FileHash $archive -Algorithm SHA256).Hash
|
||||
if ($got -ne $ffmpegSha) { throw "ffmpeg checksum: expected $ffmpegSha, got $got" }
|
||||
|
||||
$bin = Join-Path $dist "bin"
|
||||
New-Item -ItemType Directory -Path $bin | Out-Null
|
||||
$compressed = [System.IO.File]::OpenRead($archive)
|
||||
$stream = New-Object System.IO.Compression.GzipStream(
|
||||
$compressed, [System.IO.Compression.CompressionMode]::Decompress)
|
||||
$binary = [System.IO.File]::Create((Join-Path $bin "ffmpeg.exe"))
|
||||
try { $stream.CopyTo($binary) } finally { $binary.Dispose(); $stream.Dispose(); $compressed.Dispose() }
|
||||
|
||||
# 4. The setup program ------------------------------------------------------
|
||||
# Inno Setup comes with the GitHub runner. On a machine that has not got it:
|
||||
# winget install JRSoftware.InnoSetup
|
||||
$iscc = (Get-Command iscc -ErrorAction SilentlyContinue).Source
|
||||
if (-not $iscc) {
|
||||
$iscc = Join-Path ${env:ProgramFiles(x86)} "Inno Setup 6\ISCC.exe"
|
||||
}
|
||||
if (-not (Test-Path $iscc)) {
|
||||
throw "no Inno Setup found. Install it with: winget install JRSoftware.InnoSetup"
|
||||
}
|
||||
& $iscc "/DVersion=$version" "/DSource=$dist" "/DIcon=$icon" `
|
||||
(Join-Path $root "packaging\dikte.iss")
|
||||
if ($LASTEXITCODE -ne 0) { throw "Inno Setup failed" }
|
||||
|
||||
Write-Host "dist\Dikte-$version-x64-setup.exe"
|
||||
Reference in New Issue
Block a user