-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild_deploy.ps1
More file actions
220 lines (207 loc) · 10.5 KB
/
Copy pathbuild_deploy.ps1
File metadata and controls
220 lines (207 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# ============================================================================
# LayerCam - unified single-command automation pipeline (spec S3.2)
#
# Primary implementation: native C++ built with Visual Studio 2019 (v142).
#
# .\build_deploy.ps1 # sdk (if needed) + build + selftest + deploy
# .\build_deploy.ps1 -Task sdk # extract C++ SDKs from offline-sdk\_downloads
# .\build_deploy.ps1 -Task build # configure + compile (VS2019, x64 Release)
# .\build_deploy.ps1 -Task run # launch the built app
# .\build_deploy.ps1 -Task py-run # Python reference implementation (dev)
# .\build_deploy.ps1 -Task py-build # Python reference -> PyInstaller bundle
#
# Fully OFFLINE once offline-sdk\ is populated: toolchain aside (VS2019),
# every dependency is housed inside .\offline-sdk\.
# ============================================================================
param(
[ValidateSet("all", "sdk", "build", "run", "selftest", "py-setup", "py-run", "py-build")]
[string]$Task = "all"
)
# NOTE: keep "Continue" - with "Stop", Windows PowerShell 5.1 turns any native
# stderr line into a terminating error. Failures are detected via $LASTEXITCODE.
$ErrorActionPreference = "Continue"
$Root = Split-Path -Parent $MyInvocation.MyCommand.Path
Set-Location $Root
function Fail($msg) { Write-Host "ERROR: $msg" -ForegroundColor Red; exit 1 }
function Step($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }
# ============================================================================
# C++ toolchain (Visual Studio 2019)
# ============================================================================
$Vs2019 = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise"
function Resolve-CMake {
$cands = @(
"cmake",
(Join-Path $Root "..\..\cmake-3.31.12-windows-x86_64\bin\cmake.exe"),
"$Vs2019\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe"
)
foreach ($c in $cands) {
try {
& $c --version *> $null
if ($LASTEXITCODE -eq 0) { return $c }
} catch { }
}
Fail "cmake not found."
}
function Ensure-Sdk {
$dl = "offline-sdk\_downloads"
# nlohmann json
if (-not (Test-Path "offline-sdk\third_party\nlohmann\json.hpp")) {
Step "Staging nlohmann/json..."
if (-not (Test-Path "$dl\json.hpp")) { Fail "$dl\json.hpp missing - download it first." }
New-Item -ItemType Directory -Force "offline-sdk\third_party\nlohmann" | Out-Null
Copy-Item "$dl\json.hpp" "offline-sdk\third_party\nlohmann\json.hpp" -Force
}
# Dear ImGui
if (-not (Test-Path "offline-sdk\imgui\imgui.cpp")) {
Step "Extracting Dear ImGui..."
if (-not (Test-Path "$dl\imgui-1.90.9.zip")) { Fail "$dl\imgui-1.90.9.zip missing." }
Expand-Archive "$dl\imgui-1.90.9.zip" "offline-sdk\_tmp_imgui" -Force
$inner = Get-ChildItem "offline-sdk\_tmp_imgui" -Directory | Select-Object -First 1
Move-Item $inner.FullName "offline-sdk\imgui"
Remove-Item "offline-sdk\_tmp_imgui" -Recurse -Force
}
# ONNX Runtime (DirectML build) - nupkg is a zip
if (-not (Test-Path "offline-sdk\onnxruntime\build\native\include\onnxruntime_cxx_api.h")) {
Step "Extracting ONNX Runtime (DirectML)..."
if (-not (Test-Path "$dl\onnxruntime-directml-1.18.1.nupkg")) { Fail "$dl\onnxruntime nupkg missing." }
Copy-Item "$dl\onnxruntime-directml-1.18.1.nupkg" "$dl\ort.zip" -Force
Expand-Archive "$dl\ort.zip" "offline-sdk\onnxruntime" -Force
Remove-Item "$dl\ort.zip"
}
# DirectML redistributable
if (-not (Test-Path "offline-sdk\directml\DirectML.dll")) {
Step "Extracting DirectML..."
if (-not (Test-Path "$dl\directml-1.15.0.nupkg")) { Fail "$dl\directml nupkg missing." }
Copy-Item "$dl\directml-1.15.0.nupkg" "$dl\dml.zip" -Force
Expand-Archive "$dl\dml.zip" "offline-sdk\_tmp_dml" -Force
New-Item -ItemType Directory -Force "offline-sdk\directml" | Out-Null
$dll = Get-ChildItem "offline-sdk\_tmp_dml" -Recurse -Filter "DirectML.dll" |
Where-Object { $_.FullName -match "x64" } | Select-Object -First 1
if ($null -eq $dll) { Fail "DirectML.dll (x64) not found in nupkg." }
Copy-Item $dll.FullName "offline-sdk\directml\DirectML.dll" -Force
Remove-Item "offline-sdk\_tmp_dml" -Recurse -Force
}
# OpenCV prebuilt (7z self-extractor: -o<dir> -y)
if (-not (Test-Path "offline-sdk\opencv\build\OpenCVConfig.cmake")) {
Step "Extracting OpenCV (this takes a minute)..."
if (-not (Test-Path "$dl\opencv-4.10.0-windows.exe")) { Fail "$dl\opencv exe missing." }
$p = Start-Process -Wait -PassThru "$dl\opencv-4.10.0-windows.exe" `
-ArgumentList "-o`"$Root\offline-sdk\_tmp_cv`"", "-y"
if ($p.ExitCode -ne 0) { Fail "OpenCV self-extraction failed ($($p.ExitCode))." }
Move-Item "$Root\offline-sdk\_tmp_cv\opencv" "$Root\offline-sdk\opencv"
Remove-Item "$Root\offline-sdk\_tmp_cv" -Recurse -Force
}
Step "SDK ready."
}
function Build-Cpp {
$cmake = Resolve-CMake
Step "Configuring (Visual Studio 16 2019, x64)..."
& $cmake -S vs -B build\cmake -G "Visual Studio 16 2019" -A x64
if ($LASTEXITCODE -ne 0) { Fail "CMake configure failed." }
Step "Compiling (Release)..."
& $cmake --build build\cmake --config Release --parallel
if ($LASTEXITCODE -ne 0) { Fail "Build failed." }
}
function Selftest-Cpp {
Step "Running self test..."
& "build\cmake\Release\LayerCam.exe" --selftest
if ($LASTEXITCODE -ne 0) { Fail "Self test failed." }
}
function Deploy-Cpp {
Step "Deploying to apps\LayerCam ..."
$dest = "apps\LayerCam"
if (Test-Path $dest) { Remove-Item $dest -Recurse -Force }
New-Item -ItemType Directory -Force "$dest\models", "$dest\ffmpeg", "$dest\config" | Out-Null
Copy-Item "build\cmake\Release\LayerCam.exe" $dest
Copy-Item "build\cmake\Release\*.dll" $dest
Copy-Item "offline-sdk\models\rvm_mobilenetv3.onnx" "$dest\models\"
Copy-Item "offline-sdk\ffmpeg\ffmpeg.exe" "$dest\ffmpeg\"
Copy-Item "config\encoder_profiles.json" "$dest\config\"
# newest VC++ runtime from the system so onnxruntime initialises cleanly
foreach ($f in "vcruntime140.dll","vcruntime140_1.dll","msvcp140.dll","msvcp140_1.dll","msvcp140_2.dll") {
$srcDll = "$env:WINDIR\System32\$f"
if (Test-Path $srcDll) { Copy-Item $srcDll "$dest\$f" -Force }
}
Write-Host ""
Write-Host "Build complete: apps\LayerCam\LayerCam.exe" -ForegroundColor Green
}
# ============================================================================
# Python reference implementation (kept runnable)
# ============================================================================
function Resolve-Python {
$portable = Join-Path $Root "offline-sdk\python-portable\python.exe"
if (Test-Path $portable) { return $portable }
$venv = Join-Path $Root "build\venv\Scripts\python.exe"
if (Test-Path $venv) { return $venv }
$inst = Join-Path $Root "offline-sdk\python\python-3.10.0-amd64.exe"
try { & py -3.10 --version *> $null } catch { }
if ($LASTEXITCODE -ne 0) {
if (-not (Test-Path $inst)) { Fail "No Python runtime and offline installer missing." }
Step "Installing Python 3.10 from the bundled offline installer..."
Start-Process -Wait $inst -ArgumentList "/passive","InstallAllUsers=0","PrependPath=1","Include_test=0","Include_pip=1"
}
Step "Creating virtual environment (build\venv)..."
& py -3.10 -m venv (Join-Path $Root "build\venv")
if ($LASTEXITCODE -ne 0) { Fail "venv creation failed." }
return $venv
}
function Ensure-PyDeps([string]$py) {
for ($i = 0; $i -lt 3; $i++) {
$null = & $py -c "import PyQt5, cv2, numpy, onnxruntime, sounddevice, soundfile" 2>&1
if ($LASTEXITCODE -eq 0) { return }
Start-Sleep -Milliseconds 700
}
Step "Installing dependencies from offline-sdk\wheels (no network)..."
& $py -m pip install --no-index --find-links "offline-sdk\wheels" `
--no-warn-script-location -r python\requirements.txt pyinstaller
if ($LASTEXITCODE -ne 0) {
$pipWhl = Get-ChildItem "offline-sdk\wheels\pip-*.whl" | Select-Object -First 1
if ($null -eq $pipWhl) { Fail "offline install failed and no pip wheel found." }
& $py "$($pipWhl.FullName)\pip" install --no-index --find-links "offline-sdk\wheels" `
--no-warn-script-location -r python\requirements.txt pyinstaller
if ($LASTEXITCODE -ne 0) { Fail "Offline dependency install failed." }
}
}
function Verify-Py([string]$py) {
Step "Verifying Python environment..."
& $py -X utf8 python\tests\smoke_test.py
if ($LASTEXITCODE -ne 0) { Fail "Python smoke test failed." }
}
function Build-Py([string]$py) {
Step "Building Python bundle with PyInstaller..."
Push-Location python
& $py -m PyInstaller --noconfirm --clean LayerCam.spec `
--workpath "..\build\pyinstaller" --distpath "..\build\dist"
$code = $LASTEXITCODE
Pop-Location
if ($code -ne 0) { Fail "PyInstaller build failed." }
$sysDir = "$env:WINDIR\System32"
foreach ($t in "build\dist\LayerCam\_internal", "build\dist\LayerCam\_internal\PyQt5\Qt5\bin") {
if (-not (Test-Path $t)) { continue }
foreach ($f in "vcruntime140.dll","vcruntime140_1.dll","msvcp140.dll","msvcp140_1.dll","msvcp140_2.dll") {
$srcDll = Join-Path $sysDir $f
if (Test-Path $srcDll) { Copy-Item $srcDll (Join-Path $t $f) -Force }
}
}
$dest = "apps\LayerCam-py"
if (Test-Path $dest) { Remove-Item $dest -Recurse -Force }
Copy-Item "build\dist\LayerCam" $dest -Recurse
New-Item -ItemType Directory -Force "$dest\config" | Out-Null
Copy-Item "config\encoder_profiles.json" "$dest\config\" -Force
Write-Host "Python bundle: apps\LayerCam-py\LayerCam.exe" -ForegroundColor Green
}
# ============================================================================
switch ($Task) {
"sdk" { Ensure-Sdk }
"build" { Ensure-Sdk; Build-Cpp }
"selftest" { Selftest-Cpp }
"run" {
if (-not (Test-Path "build\cmake\Release\LayerCam.exe")) { Ensure-Sdk; Build-Cpp }
Step "Launching LayerCam..."
& "build\cmake\Release\LayerCam.exe"
}
"all" { Ensure-Sdk; Build-Cpp; Selftest-Cpp; Deploy-Cpp }
"py-setup" { $py = Resolve-Python; Ensure-PyDeps $py; Verify-Py $py }
"py-run" { $py = Resolve-Python; Ensure-PyDeps $py; & $py "python\src\main.py" }
"py-build" { $py = Resolve-Python; Ensure-PyDeps $py; Verify-Py $py; Build-Py $py }
}