234 lines
6.2 KiB
Markdown
234 lines
6.2 KiB
Markdown
# RFCP Native Backend Research
|
|
|
|
## Executive Summary
|
|
|
|
**Finding:** The production Electron app already supports native Windows operation without WSL2.
|
|
|
|
The production build uses PyInstaller to bundle the Python backend as a standalone Windows executable (`rfcp-server.exe`). WSL2 is only used during development. No migration is needed for end users.
|
|
|
|
---
|
|
|
|
## Current Architecture
|
|
|
|
### Development Mode
|
|
```
|
|
RFCP (Electron dev)
|
|
└── Spawns: python -m uvicorn app.main:app --host 127.0.0.1 --port 8090
|
|
└── Uses system Python (Windows or WSL2)
|
|
└── Requires venv with dependencies
|
|
```
|
|
|
|
### Production Mode (Already Implemented)
|
|
```
|
|
RFCP.exe (Electron packaged)
|
|
└── Spawns: rfcp-server.exe (bundled PyInstaller binary)
|
|
└── Self-contained Python + all dependencies
|
|
└── No WSL2 required
|
|
└── No system Python required
|
|
```
|
|
|
|
---
|
|
|
|
## Evidence from Codebase
|
|
|
|
### desktop/main.js (Lines 120-145)
|
|
|
|
```javascript
|
|
function startBackend() {
|
|
// Production: use bundled executable
|
|
if (isProduction) {
|
|
const serverPath = path.join(process.resourcesPath, 'rfcp-server.exe');
|
|
if (fs.existsSync(serverPath)) {
|
|
backendProcess = spawn(serverPath, [], { ... });
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Development: use system Python
|
|
backendProcess = spawn('python', ['-m', 'uvicorn', 'app.main:app', ...]);
|
|
}
|
|
```
|
|
|
|
### installer/rfcp-server.spec (PyInstaller Config)
|
|
|
|
```python
|
|
# Key configuration
|
|
a = Analysis(
|
|
['run_server.py'],
|
|
pathex=[backend_path],
|
|
binaries=[],
|
|
datas=[
|
|
('data/terrain', 'data/terrain'), # Terrain data bundled
|
|
],
|
|
hiddenimports=[
|
|
'uvicorn.logging', 'uvicorn.loops', 'uvicorn.protocols',
|
|
'motor', 'pymongo', 'numpy', 'scipy', 'shapely',
|
|
# Full list of dependencies
|
|
],
|
|
)
|
|
|
|
exe = EXE(
|
|
pyz,
|
|
a.scripts,
|
|
name='rfcp-server',
|
|
console=True, # Shows console for debugging
|
|
icon='rfcp.ico',
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## GPU Acceleration in Production
|
|
|
|
### Current Status
|
|
The PyInstaller bundle **does not include CuPy** by default because:
|
|
1. CuPy requires CUDA runtime (large, ~500MB)
|
|
2. Not all users have NVIDIA GPUs
|
|
3. Binary would be too large for distribution
|
|
|
|
### Solution Options
|
|
|
|
**Option A: Ship CPU-only (Current)**
|
|
- Production build uses NumPy (CPU) for calculations
|
|
- GPU acceleration available only in dev mode or manual install
|
|
- Smallest download size (~100MB)
|
|
|
|
**Option B: Separate GPU Installer**
|
|
- Main installer: CPU-only (~100MB)
|
|
- Optional GPU addon: Downloads CuPy + CUDA runtime (~600MB)
|
|
- Implemented via install_rfcp.py dependency installer
|
|
|
|
**Option C: CUDA Toolkit Detection**
|
|
- Detect if CUDA is already installed on user's system
|
|
- If yes, attempt to load CuPy dynamically
|
|
- Graceful fallback to NumPy if not available
|
|
|
|
### Recommendation
|
|
Keep Option A (CPU-only production) with Option B available for power users:
|
|
1. Default production build works everywhere
|
|
2. Users with NVIDIA GPUs can run `install_rfcp.py` to enable GPU acceleration
|
|
3. No WSL2 required for either path
|
|
|
|
---
|
|
|
|
## Terrain Data Handling
|
|
|
|
### Current Implementation
|
|
Terrain data (SRTM .hgt files) is bundled inside the PyInstaller executable:
|
|
|
|
```python
|
|
datas=[
|
|
('data/terrain', 'data/terrain'),
|
|
]
|
|
```
|
|
|
|
### Considerations
|
|
- Bundled terrain data increases exe size significantly
|
|
- Alternative: Download terrain on first use (like current region download system)
|
|
- For initial release, bundling common regions is acceptable
|
|
|
|
---
|
|
|
|
## Database (MongoDB)
|
|
|
|
### Production Architecture
|
|
The Electron app embeds MongoDB or requires MongoDB to be installed separately.
|
|
|
|
Options:
|
|
1. **Embedded MongoDB** - Ships mongod.exe with the app
|
|
2. **MongoDB Atlas** - Cloud database (requires internet)
|
|
3. **SQLite** - Switch to file-based database (significant refactor)
|
|
4. **In-memory + file persistence** - No MongoDB required (significant refactor)
|
|
|
|
Current implementation uses Motor (async MongoDB driver). For true standalone operation, consider SQLite migration in future iteration.
|
|
|
|
---
|
|
|
|
## Build Process
|
|
|
|
### Current Build Commands
|
|
|
|
```bash
|
|
# Build backend executable
|
|
cd /mnt/d/root/rfcp/backend
|
|
pyinstaller ../installer/rfcp-server.spec
|
|
|
|
# Build Electron app with bundled backend
|
|
cd /mnt/d/root/rfcp/installer
|
|
./build-win.sh
|
|
```
|
|
|
|
### Output
|
|
- `rfcp-server.exe` - Standalone backend (~80MB)
|
|
- `RFCP-Setup-{version}.exe` - Full installer with Electron + backend (~150MB)
|
|
|
|
---
|
|
|
|
## Testing Native Build
|
|
|
|
### Test Procedure
|
|
1. Build `rfcp-server.exe` via PyInstaller
|
|
2. Run directly: `./rfcp-server.exe`
|
|
3. Verify API responds: `curl http://localhost:8090/api/health`
|
|
4. Verify coverage calculation works
|
|
5. Check GPU detection in logs
|
|
|
|
### Known Issues
|
|
1. **First launch slow**: PyInstaller extracts on first run (~5-10 seconds)
|
|
2. **Antivirus false positives**: Some AV flags PyInstaller executables
|
|
3. **Console window**: Shows black console (use `console=False` for windowless)
|
|
|
|
---
|
|
|
|
## Conclusions
|
|
|
|
### No Migration Needed
|
|
The production Electron app already works without WSL2. The current architecture is:
|
|
- ✅ Native Windows executable
|
|
- ✅ No Python installation required
|
|
- ✅ No WSL2 required
|
|
- ✅ Self-contained dependencies
|
|
|
|
### Development vs Production
|
|
| Aspect | Development | Production |
|
|
|--------|-------------|------------|
|
|
| Python | System Python / venv | Bundled via PyInstaller |
|
|
| WSL2 | Optional (for testing) | Not required |
|
|
| GPU | CuPy if installed | CPU-only (NumPy) |
|
|
| MongoDB | Local instance | Embedded or Atlas |
|
|
| Terrain | Local data/ folder | Bundled in exe |
|
|
|
|
### Remaining Work
|
|
1. **GPU for production**: Implement Optional GPU addon installer
|
|
2. **Smaller package**: On-demand terrain download instead of bundling
|
|
3. **Database portability**: Consider SQLite migration for offline-first
|
|
4. **Installer polish**: Signed executables, auto-update support
|
|
|
|
---
|
|
|
|
## Appendix: Full PyInstaller Hidden Imports
|
|
|
|
From `installer/rfcp-server.spec`:
|
|
```python
|
|
hiddenimports=[
|
|
'uvicorn.logging',
|
|
'uvicorn.loops',
|
|
'uvicorn.loops.auto',
|
|
'uvicorn.protocols',
|
|
'uvicorn.protocols.http',
|
|
'uvicorn.protocols.http.auto',
|
|
'uvicorn.protocols.websockets',
|
|
'uvicorn.protocols.websockets.auto',
|
|
'uvicorn.lifespan',
|
|
'uvicorn.lifespan.on',
|
|
'motor',
|
|
'pymongo',
|
|
'numpy',
|
|
'scipy',
|
|
'shapely',
|
|
'shapely.geometry',
|
|
'shapely.ops',
|
|
# ... additional imports
|
|
]
|
|
```
|