first commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# Sensor Bench EXE Build
|
||||
|
||||
This folder contains the Windows PyInstaller build setup for Sensor Bench.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Windows x64
|
||||
- Anaconda or Miniconda available as `conda`
|
||||
- Python 3.10 build environment
|
||||
- Internet access to install `orisys` from PyPI
|
||||
|
||||
The build installs `orisys` from PyPI. Do not use `PYTHONPATH` or an editable `orisys-sdk` checkout for release builds.
|
||||
|
||||
## Build
|
||||
|
||||
From the repository root (cmd or PowerShell):
|
||||
|
||||
```bat
|
||||
.\build\create_env.bat
|
||||
.\build\build_exe.bat
|
||||
```
|
||||
|
||||
The `.bat` wrappers bypass the local PowerShell execution policy. If you prefer calling PowerShell directly:
|
||||
|
||||
```bat
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File .\build\create_env.ps1
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File .\build\build_exe.ps1
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```text
|
||||
dist/SensorBench/SensorBench.exe
|
||||
```
|
||||
|
||||
The build is `onedir` rather than `onefile` so startup is faster and bundled DLL/resource issues are easier to diagnose.
|
||||
|
||||
## Validation
|
||||
|
||||
The build script runs:
|
||||
|
||||
```powershell
|
||||
python tests/test_smoke.py
|
||||
python build/verify_dist.py
|
||||
```
|
||||
|
||||
Manual hardware check:
|
||||
|
||||
1. Run `dist\SensorBench\SensorBench.exe`.
|
||||
2. Confirm the UI opens without setting `PYTHONPATH`.
|
||||
3. Confirm the UI defaults to Simplified Chinese and can switch to English.
|
||||
4. Confirm Orisys status is available and fixed mode shows DDJX01.
|
||||
5. Use Next / Revert / New Sample Reset on the left workflow panel.
|
||||
6. Start preview with camera index `0`.
|
||||
7. Confirm raw preview and processed preview update.
|
||||
8. Record a short clip and verify it appears under `dist\SensorBench\recordings`.
|
||||
|
||||
Locale files are bundled under `_internal/config/locales/` (and can also be placed beside the EXE under `config/locales/` for overrides). Edit those JSON files to change operator-facing text without rebuilding.
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
cd /d "%~dp0.."
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0build_exe.ps1" %*
|
||||
@@ -0,0 +1,42 @@
|
||||
param(
|
||||
[string]$EnvName = "sensor-bench-build-py310"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
|
||||
$DistDir = Join-Path $RepoRoot "dist"
|
||||
$WorkDir = Join-Path $RepoRoot "build\pyinstaller_work"
|
||||
$SpecPath = Join-Path $PSScriptRoot "sensor_bench.spec"
|
||||
|
||||
if (-not (Get-Command conda -ErrorAction SilentlyContinue)) {
|
||||
throw "conda was not found on PATH. Open an Anaconda Prompt or initialize conda for PowerShell."
|
||||
}
|
||||
|
||||
Push-Location $RepoRoot
|
||||
try {
|
||||
conda run -n $EnvName python -m pip install --upgrade pip
|
||||
conda run -n $EnvName python -m pip install -e ".[pack]"
|
||||
conda run -n $EnvName python -m pip install --upgrade orisys
|
||||
|
||||
conda run -n $EnvName python tests/test_smoke.py
|
||||
|
||||
if (Test-Path $WorkDir) {
|
||||
Remove-Item -Recurse -Force $WorkDir
|
||||
}
|
||||
if (Test-Path (Join-Path $DistDir "SensorBench")) {
|
||||
Remove-Item -Recurse -Force (Join-Path $DistDir "SensorBench")
|
||||
}
|
||||
|
||||
conda run -n $EnvName python -m PyInstaller --noconfirm --clean --distpath "$DistDir" --workpath "$WorkDir" "$SpecPath"
|
||||
|
||||
Copy-Item -Recurse -Force (Join-Path $RepoRoot "config") (Join-Path $DistDir "SensorBench")
|
||||
Copy-Item -Recurse -Force (Join-Path $RepoRoot "steps") (Join-Path $DistDir "SensorBench")
|
||||
conda run -n $EnvName python build/verify_dist.py
|
||||
|
||||
Write-Host "Build complete: dist\SensorBench\SensorBench.exe"
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
cd /d "%~dp0.."
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0create_env.ps1" %*
|
||||
@@ -0,0 +1,30 @@
|
||||
param(
|
||||
[string]$EnvName = "sensor-bench-build-py310",
|
||||
[string]$PythonVersion = "3.10"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$RepoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
|
||||
|
||||
if (-not (Get-Command conda -ErrorAction SilentlyContinue)) {
|
||||
throw "conda was not found on PATH. Open an Anaconda Prompt or initialize conda for PowerShell."
|
||||
}
|
||||
|
||||
$envList = conda env list | Out-String
|
||||
if ($envList -notmatch "(?m)^\s*$([regex]::Escape($EnvName))\s") {
|
||||
conda create -y -n $EnvName python=$PythonVersion
|
||||
}
|
||||
|
||||
conda run -n $EnvName python -m pip install --upgrade pip
|
||||
Push-Location $RepoRoot
|
||||
try {
|
||||
conda run -n $EnvName python -m pip install -e ".[pack]"
|
||||
}
|
||||
finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Write-Host "Build environment ready: $EnvName"
|
||||
Write-Host "Orisys will be installed from PyPI by build_exe.ps1."
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from PyInstaller.utils.hooks import collect_all, collect_submodules
|
||||
|
||||
|
||||
repo_root = Path.cwd()
|
||||
src_dir = repo_root / "src"
|
||||
work_dir = repo_root / "build" / "pyinstaller_work"
|
||||
|
||||
datas = [
|
||||
(str(repo_root / "config"), "config"),
|
||||
(str(repo_root / "steps"), "steps"),
|
||||
]
|
||||
binaries = []
|
||||
hiddenimports = [
|
||||
"sensor_bench.main",
|
||||
"sensor_bench.app",
|
||||
"sensor_bench.acquisition",
|
||||
"sensor_bench.config_loader",
|
||||
"sensor_bench.i18n",
|
||||
"sensor_bench.paths",
|
||||
"sensor_bench.plot_history",
|
||||
"sensor_bench.recorder",
|
||||
"orisys",
|
||||
"orisys_blend",
|
||||
"scipy.fft",
|
||||
"scipy.ndimage",
|
||||
"scipy.sparse.linalg",
|
||||
"numba",
|
||||
"llvmlite",
|
||||
]
|
||||
|
||||
for package in ("PyQt5", "pyqtgraph", "cv2", "orisys", "orisys_blend", "numba", "llvmlite"):
|
||||
pkg_datas, pkg_binaries, pkg_hidden = collect_all(package)
|
||||
datas += pkg_datas
|
||||
binaries += pkg_binaries
|
||||
hiddenimports += pkg_hidden
|
||||
|
||||
hiddenimports += collect_submodules("orisys_blend")
|
||||
|
||||
excludes = [
|
||||
"cupy",
|
||||
"cupyx",
|
||||
"pyopencl",
|
||||
"open3d",
|
||||
"matplotlib",
|
||||
"tkinter",
|
||||
"pytest",
|
||||
"pip",
|
||||
"wheel",
|
||||
]
|
||||
|
||||
a = Analysis(
|
||||
[str(repo_root / "run.py")],
|
||||
pathex=[str(repo_root), str(src_dir)],
|
||||
binaries=binaries,
|
||||
datas=datas,
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=excludes,
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name="SensorBench",
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name="SensorBench",
|
||||
)
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,31 @@
|
||||
"""Verify the PyInstaller onedir output has the expected portable layout."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DIST = ROOT / "dist" / "SensorBench"
|
||||
|
||||
|
||||
def require(path: Path) -> None:
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Missing build artifact: {path}")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
require(DIST / "SensorBench.exe")
|
||||
require(DIST / "config" / "options.json")
|
||||
require(DIST / "config" / "locales" / "zh_CN.json")
|
||||
require(DIST / "config" / "locales" / "en_US.json")
|
||||
require(DIST / "steps" / "default.json")
|
||||
require(DIST / "_internal")
|
||||
print(f"Verified SensorBench dist layout: {DIST}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
||||
Reference in New Issue
Block a user