fix: keep resource folders external alongside EXE instead of embedding
This commit is contained in:
parent
9b7933d2a0
commit
9ea3c32c64
17
BUILD_EXE.md
17
BUILD_EXE.md
@ -32,6 +32,7 @@ python -m pip install -r requirements-build.txt
|
||||
Скрипт автоматически:
|
||||
- очищает `build/`, `dist/`, `__pycache__/`
|
||||
- запускает PyInstaller по `plate_config_app.spec`
|
||||
- копирует папки `light_modes/`, `input_mappings/`, `commands/` в `dist/`
|
||||
- выводит путь и размер готового EXE
|
||||
|
||||
### 3. Только очистка (без сборки)
|
||||
@ -59,9 +60,19 @@ python -m pip install -r requirements-build.txt
|
||||
|
||||
| Ресурс | Описание |
|
||||
|----------------------|---------------------------------|
|
||||
| `light_modes/` | Файлы режимов подсветки (.lm) |
|
||||
| `input_mappings/` | Маппинги входов (.mapping) |
|
||||
| `commands/` | Наборы команд (.csv) |
|
||||
| `qtawesome/` | Шрифты и charmap иконок |
|
||||
|
||||
Hidden imports: `qtawesome`, `Crypto.Cipher._raw_aes`, `Crypto.Util._raw_api`
|
||||
|
||||
## Ресурсы рядом с EXE
|
||||
|
||||
Скрипт `build_exe.ps1` после сборки копирует папки в `dist/`:
|
||||
|
||||
| Папка | Описание |
|
||||
|--------------------|---------------------------------|
|
||||
| `light_modes/` | Файлы режимов подсветки (.lm) |
|
||||
| `input_mappings/` | Маппинги входов (.mapping) |
|
||||
| `commands/` | Наборы команд (.csv) |
|
||||
|
||||
Эти файлы можно редактировать без пересборки — достаточно изменить их
|
||||
рядом с EXE и перезапустить приложение.
|
||||
|
||||
@ -172,9 +172,10 @@ health-check) вынесены в `QThread`-подклассы. Связь с UI
|
||||
Создайте `.mapping` файл в `input_mappings/` в формате TOML.
|
||||
Структура описана в `app/services/input_mappings_service.py`.
|
||||
|
||||
После добавления файлов они подхватятся при следующем запуске из исходников.
|
||||
Для EXE-сборки необходимо пересобрать приложение (папки автоматически
|
||||
включаются через `plate_config_app.spec`).
|
||||
После добавления файлов они подхватятся при следующем запуске.
|
||||
При сборке EXE папки автоматически копируются рядом с исполняемым файлом
|
||||
скриптом `build_exe.ps1`. Пересборка для обновления конфигураций **не нужна** —
|
||||
достаточно отредактировать файлы рядом с EXE и перезапустить приложение.
|
||||
|
||||
---
|
||||
|
||||
@ -189,4 +190,5 @@ health-check) вынесены в `QThread`-подклассы. Связь с UI
|
||||
.\build_exe.ps1 -InstallBuildDeps
|
||||
```
|
||||
|
||||
Результат: `dist\plate_config_app.exe`.
|
||||
Результат: `dist\plate_config_app.exe` + папки `dist\light_modes\`,
|
||||
`dist\input_mappings\`, `dist\commands\`.
|
||||
|
||||
@ -111,8 +111,10 @@
|
||||
| `input_mappings/` | `.mapping` | Маппинги входов по играм (формат TOML) |
|
||||
| `commands/` | `.csv` | Наборы команд платы (разделитель `;`) |
|
||||
|
||||
Эти файлы встраиваются внутрь EXE при сборке. Для обновления конфигураций
|
||||
необходима пересборка.
|
||||
Эти файлы располагаются рядом с EXE (или в корне проекта при запуске из
|
||||
исходников). При сборке они автоматически копируются в папку `dist/` рядом с
|
||||
EXE. Можно редактировать файлы конфигураций без пересборки — достаточно
|
||||
изменить нужный файл и перезапустить приложение.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -32,11 +32,11 @@ class CommandSet:
|
||||
def _get_commands_dir() -> Path:
|
||||
"""Определить путь к папке commands/.
|
||||
|
||||
При запуске из .exe (PyInstaller onefile) — в распакованном каталоге _MEIPASS.
|
||||
При запуске из .exe (PyInstaller) — рядом с exe-файлом.
|
||||
При запуске из исходников — рядом с корнем проекта.
|
||||
"""
|
||||
if getattr(sys, "frozen", False):
|
||||
base = Path(getattr(sys, "_MEIPASS", Path(sys.executable).parent))
|
||||
base = Path(sys.executable).parent
|
||||
else:
|
||||
base = Path(__file__).resolve().parent.parent.parent
|
||||
return base / "commands"
|
||||
|
||||
@ -41,11 +41,11 @@ class InputMapping:
|
||||
def _get_input_mappings_dir() -> Path:
|
||||
"""Определить путь к папке input_mappings/.
|
||||
|
||||
При запуске из .exe (PyInstaller onefile) — в распакованном каталоге _MEIPASS.
|
||||
При запуске из .exe (PyInstaller) — рядом с exe-файлом.
|
||||
При запуске из исходников — рядом с корнем проекта.
|
||||
"""
|
||||
if getattr(sys, "frozen", False):
|
||||
base = Path(getattr(sys, "_MEIPASS", Path(sys.executable).parent))
|
||||
base = Path(sys.executable).parent
|
||||
else:
|
||||
base = Path(__file__).resolve().parent.parent.parent
|
||||
return base / "input_mappings"
|
||||
|
||||
@ -34,13 +34,12 @@ class LightMode:
|
||||
def _get_light_modes_dir() -> Path:
|
||||
"""Определить путь к папке light_modes/.
|
||||
|
||||
При запуске из .exe (PyInstaller onefile) — в распакованном каталоге _MEIPASS.
|
||||
При запуске из .exe (PyInstaller) — рядом с exe-файлом.
|
||||
При запуске из исходников — рядом с корнем проекта.
|
||||
"""
|
||||
if getattr(sys, "frozen", False):
|
||||
base = Path(getattr(sys, "_MEIPASS", Path(sys.executable).parent))
|
||||
base = Path(sys.executable).parent
|
||||
else:
|
||||
# Разработка: корень проекта (где лежит main.py)
|
||||
base = Path(__file__).resolve().parent.parent.parent
|
||||
return base / "light_modes"
|
||||
|
||||
|
||||
@ -58,10 +58,25 @@ if ($LASTEXITCODE -ne 0) {
|
||||
}
|
||||
|
||||
$exe = Join-Path $projectRoot "dist\plate_config_app.exe"
|
||||
if (Test-Path $exe) {
|
||||
$size = [math]::Round((Get-Item $exe).Length / 1MB, 1)
|
||||
Write-Host ""
|
||||
Write-Host "Сборка завершена: $exe ($size MB)"
|
||||
} else {
|
||||
if (-not (Test-Path $exe)) {
|
||||
throw "EXE не найден после сборки."
|
||||
}
|
||||
|
||||
# ── Копирование ресурсных папок рядом с EXE ───────────────────────
|
||||
Write-Host ""
|
||||
Write-Host "=== Копирование ресурсов ==="
|
||||
$resourceFolders = @("light_modes", "input_mappings", "commands")
|
||||
foreach ($folder in $resourceFolders) {
|
||||
$src = Join-Path $projectRoot $folder
|
||||
$dst = Join-Path $projectRoot "dist\$folder"
|
||||
if (Test-Path $src) {
|
||||
Copy-Item $src -Destination $dst -Recurse -Force
|
||||
Write-Host " Скопировано: $folder"
|
||||
} else {
|
||||
Write-Host " Пропущено (не найдено): $folder" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
$size = [math]::Round((Get-Item $exe).Length / 1MB, 1)
|
||||
Write-Host ""
|
||||
Write-Host "Сборка завершена: $exe ($size MB)"
|
||||
|
||||
@ -11,9 +11,6 @@ a = Analysis(
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('light_modes', 'light_modes'),
|
||||
('input_mappings', 'input_mappings'),
|
||||
('commands', 'commands'),
|
||||
(_qta_dir, 'qtawesome'),
|
||||
],
|
||||
hiddenimports=[
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user