initial commit, functinal software
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
setlocal EnableExtensions
|
||||
REM Build Orisys Customer EXE. Works from any cwd; forwards args to build.ps1
|
||||
REM Examples:
|
||||
REM build.bat
|
||||
REM build.bat -Clean
|
||||
REM build.bat -SkipInstall
|
||||
REM build.bat -Clean -SkipInstall
|
||||
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
set "PS1=%SCRIPT_DIR%build.ps1"
|
||||
|
||||
if not exist "%PS1%" (
|
||||
echo ERROR: build.ps1 not found at "%PS1%"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%PS1%" %*
|
||||
set "ERR=%ERRORLEVEL%"
|
||||
exit /b %ERR%
|
||||
@@ -0,0 +1,116 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Build Orisys Customer Windows onedir EXE with PyInstaller.
|
||||
|
||||
.PARAMETER Clean
|
||||
Pass --clean to PyInstaller (slower; use when deps/spec change).
|
||||
|
||||
.PARAMETER SkipInstall
|
||||
Skip pip install steps (reuse existing .venv-build packages).
|
||||
#>
|
||||
param(
|
||||
[switch]$Clean,
|
||||
[switch]$SkipInstall
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
|
||||
$VenvDir = Join-Path $RepoRoot ".venv-build"
|
||||
$Python = Join-Path $VenvDir "Scripts\python.exe"
|
||||
$Spec = Join-Path $PSScriptRoot "orisys-customer.spec"
|
||||
$WorkPath = Join-Path $RepoRoot "build\_pyinstaller"
|
||||
$DistPath = Join-Path $RepoRoot "dist"
|
||||
|
||||
Write-Host "Repo: $RepoRoot"
|
||||
|
||||
if (-not (Test-Path $Python)) {
|
||||
Write-Host "Creating build venv at $VenvDir"
|
||||
python -m venv $VenvDir
|
||||
}
|
||||
|
||||
if (-not $SkipInstall) {
|
||||
Write-Host "Installing build dependencies (editable shared + customer + orisys + pyinstaller)…"
|
||||
& $Python -m pip install --upgrade pip
|
||||
& $Python -m pip install "pyinstaller>=6.0"
|
||||
& $Python -m pip install -e (Join-Path $RepoRoot "shared")
|
||||
& $Python -m pip install -e (Join-Path $RepoRoot "apps\customer")
|
||||
# orisys may already be installed; ensure present without [gui]/open3d
|
||||
& $Python -m pip install "orisys>=0.5"
|
||||
|
||||
Write-Host "Forcing opencv-python-headless 4.x (orisys may have pulled opencv-python; 5.x can be broken)…"
|
||||
& $Python -m pip uninstall -y opencv-python opencv-python-headless 2>$null
|
||||
& $Python -m pip install "opencv-python-headless>=4.10.0.84,<5"
|
||||
& $Python -c "import cv2; print('cv2 OK', cv2.__version__)"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "cv2 import failed after installing opencv-python-headless"
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
# Guard: Open3D must not be present in the build env
|
||||
$hasOpen3d = & $Python -c "import importlib.util; print(importlib.util.find_spec('open3d') is not None)"
|
||||
if ($hasOpen3d -eq "True") {
|
||||
Write-Host "Uninstalling open3d from build venv…"
|
||||
& $Python -m pip uninstall -y open3d
|
||||
}
|
||||
}
|
||||
|
||||
$pyiArgs = @(
|
||||
"--noconfirm",
|
||||
"--distpath", $DistPath,
|
||||
"--workpath", $WorkPath,
|
||||
$Spec
|
||||
)
|
||||
if ($Clean) {
|
||||
$pyiArgs = @("--clean") + $pyiArgs
|
||||
}
|
||||
|
||||
Write-Host "Running PyInstaller…"
|
||||
& $Python -m PyInstaller @pyiArgs
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "PyInstaller failed with exit code $LASTEXITCODE"
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
$OutDir = Join-Path $DistPath "OrisysCustomer"
|
||||
Write-Host ""
|
||||
Write-Host "Build complete: $OutDir"
|
||||
|
||||
# Lean config beside EXE (exclude finger visualization assets)
|
||||
$ConfigSrc = Join-Path $RepoRoot "apps\customer\config"
|
||||
$ConfigDst = Join-Path $OutDir "config"
|
||||
if (Test-Path $ConfigSrc) {
|
||||
Write-Host "Copying lean config to $ConfigDst …"
|
||||
if (Test-Path $ConfigDst) {
|
||||
Remove-Item $ConfigDst -Recurse -Force
|
||||
}
|
||||
New-Item -ItemType Directory -Path $ConfigDst -Force | Out-Null
|
||||
Get-ChildItem $ConfigSrc -Force | ForEach-Object {
|
||||
Copy-Item $_.FullName -Destination $ConfigDst -Recurse -Force
|
||||
}
|
||||
$viz = Join-Path $ConfigDst "sensors\finger\assets\visualization"
|
||||
if (Test-Path $viz) {
|
||||
Remove-Item $viz -Recurse -Force
|
||||
Write-Host "Excluded sensors/finger/assets/visualization"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Launch: $(Join-Path $OutDir 'OrisysCustomer.exe')"
|
||||
|
||||
# Size summary
|
||||
if (Test-Path $OutDir) {
|
||||
$bytes = (Get-ChildItem $OutDir -Recurse -File -ErrorAction SilentlyContinue |
|
||||
Measure-Object -Property Length -Sum).Sum
|
||||
$mb = [math]::Round($bytes / 1MB, 1)
|
||||
Write-Host ("Output size: {0} MB" -f $mb)
|
||||
|
||||
$o3dHits = Get-ChildItem $OutDir -Recurse -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -match 'open3d' }
|
||||
if ($o3dHits) {
|
||||
Write-Warning "Open3D-related files found under dist (should be empty):"
|
||||
$o3dHits | ForEach-Object { Write-Warning $_.FullName }
|
||||
} else {
|
||||
Write-Host "Open3D check: none found under dist."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
"""Frozen entry for Orisys Customer (no source-tree chdir)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from orisys_customer.main import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,131 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
"""PyInstaller onedir spec for Orisys Customer (Windows)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from PyInstaller.building.api import COLLECT, EXE, PYZ
|
||||
from PyInstaller.building.build_main import Analysis
|
||||
from PyInstaller.utils.hooks import collect_all, collect_data_files
|
||||
|
||||
SPEC_DIR = Path(SPECPATH).resolve()
|
||||
REPO_ROOT = SPEC_DIR.parents[1]
|
||||
BRANDING_DIR = REPO_ROOT / "shared" / "resources" / "branding"
|
||||
ENTRY = SPEC_DIR / "entry.py"
|
||||
|
||||
|
||||
def _branding_datas() -> list[tuple[str, str]]:
|
||||
datas: list[tuple[str, str]] = []
|
||||
if not BRANDING_DIR.is_dir():
|
||||
return datas
|
||||
for path in BRANDING_DIR.rglob("*"):
|
||||
if path.is_file():
|
||||
datas.append((str(path), "branding"))
|
||||
return datas
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
# Config is copied beside the EXE by build.ps1 (writable / editable).
|
||||
# Branding + package data go into _internal via Analysis datas.
|
||||
datas = _branding_datas()
|
||||
binaries: list = []
|
||||
hiddenimports = [
|
||||
"cv2",
|
||||
"PyQt5.sip",
|
||||
"pyqtgraph.graphicsItems",
|
||||
"scipy.signal",
|
||||
"numba",
|
||||
]
|
||||
datas += collect_data_files("orisys_app_shared", includes=["theme/*.json"])
|
||||
try:
|
||||
datas += collect_data_files("orisys")
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
cv2_datas, cv2_binaries, cv2_hidden = collect_all("cv2")
|
||||
datas += cv2_datas
|
||||
binaries += cv2_binaries
|
||||
hiddenimports += list(cv2_hidden)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
icon_path = BRANDING_DIR / "logo.ico"
|
||||
icon = str(icon_path) if icon_path.is_file() else None
|
||||
|
||||
a = Analysis(
|
||||
[str(ENTRY)],
|
||||
pathex=[
|
||||
str(REPO_ROOT / "apps" / "customer" / "src"),
|
||||
str(REPO_ROOT / "shared" / "src"),
|
||||
],
|
||||
binaries=binaries,
|
||||
datas=datas,
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[
|
||||
"open3d",
|
||||
"orisys.finger.viewer",
|
||||
"tkinter",
|
||||
"matplotlib",
|
||||
"IPython",
|
||||
"jupyter",
|
||||
"notebook",
|
||||
"pytest",
|
||||
"PyQt5.QtBluetooth",
|
||||
"PyQt5.QtNfc",
|
||||
"PyQt5.QtPositioning",
|
||||
"PyQt5.QtLocation",
|
||||
"PyQt5.QtMultimedia",
|
||||
"PyQt5.QtMultimediaWidgets",
|
||||
"PyQt5.QtSensors",
|
||||
"PyQt5.QtSerialPort",
|
||||
"PyQt5.QtWebChannel",
|
||||
"PyQt5.QtWebEngine",
|
||||
"PyQt5.QtWebEngineCore",
|
||||
"PyQt5.QtWebEngineWidgets",
|
||||
"PyQt5.QtWebSockets",
|
||||
"PySide2",
|
||||
"PySide6",
|
||||
"PyQt6",
|
||||
],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name="OrisysCustomer",
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=False,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
icon=icon,
|
||||
)
|
||||
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=False,
|
||||
upx_exclude=[],
|
||||
name="OrisysCustomer",
|
||||
)
|
||||
Reference in New Issue
Block a user