6.2 KiB
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)
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)
# 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:
- CuPy requires CUDA runtime (large, ~500MB)
- Not all users have NVIDIA GPUs
- 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:
- Default production build works everywhere
- Users with NVIDIA GPUs can run
install_rfcp.pyto enable GPU acceleration - No WSL2 required for either path
Terrain Data Handling
Current Implementation
Terrain data (SRTM .hgt files) is bundled inside the PyInstaller executable:
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:
- Embedded MongoDB - Ships mongod.exe with the app
- MongoDB Atlas - Cloud database (requires internet)
- SQLite - Switch to file-based database (significant refactor)
- 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
# 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
- Build
rfcp-server.exevia PyInstaller - Run directly:
./rfcp-server.exe - Verify API responds:
curl http://localhost:8090/api/health - Verify coverage calculation works
- Check GPU detection in logs
Known Issues
- First launch slow: PyInstaller extracts on first run (~5-10 seconds)
- Antivirus false positives: Some AV flags PyInstaller executables
- Console window: Shows black console (use
console=Falsefor 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
- GPU for production: Implement Optional GPU addon installer
- Smaller package: On-demand terrain download instead of bundling
- Database portability: Consider SQLite migration for offline-first
- Installer polish: Signed executables, auto-update support
Appendix: Full PyInstaller Hidden Imports
From installer/rfcp-server.spec:
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
]