A desktop application for viewing and analyzing FlySight GPS data with advanced trajectory smoothing, interactive plots, and video synchronization.
- Quick Start
- Prerequisites
- Build Instructions
- Clean Targets
- Project Structure
- Deployment
- Troubleshooting
Windows:
cmake -G "Visual Studio 17 2022" -A x64 -B build -S . -DCMAKE_PREFIX_PATH="C:/Qt/6.9.3/msvc2022_64" -DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build build --config Release
cmake --install build --config Release --prefix distmacOS (MacPorts):
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/opt/local/libexec/qt6 \
-DPython_ROOT_DIR=/opt/local \
-DPython_EXECUTABLE=/opt/local/bin/python3.13 \
-DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build build
cmake --install build --prefix distLinux:
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build build
cmake --install build --prefix distThe install step produces a self-contained deployment (ZIP-ready directory on Windows, .app bundle on macOS, AppDir on Linux) with Qt libraries, third-party dependencies, and a bundled Python runtime all included.
| Software | Version | Windows | macOS | Linux |
|---|---|---|---|---|
| CMake | 3.18+ | cmake.org | brew install cmake |
apt install cmake |
| C++ Compiler | C++17 | Visual Studio 2022 | Xcode Command Line Tools | GCC 9+ or Clang 10+ |
| Ninja | (optional) | ninja-build.org | brew install ninja |
apt install ninja-build |
| Qt | 6.x | Qt Online Installer | Qt Online Installer | Qt Online Installer |
| Boost | 1.65+ | Prebuilt binaries | brew install boost |
apt install libboost-all-dev |
| Python | 3.10+ | python.org | port install python313 or brew install python |
apt install python3-dev |
| patchelf | (Linux only) | N/A | N/A | apt install patchelf |
On Windows, Visual Studio is required even when using Ninja as the generator, since MSVC provides the compiler toolchain. You can also use the Visual Studio generator directly (-G "Visual Studio 17 2022" -A x64) instead of Ninja.
The following Qt 6 components are required:
- Core, Widgets, PrintSupport
- QuickWidgets, Quick, Qml, QuickControls2
- WebEngineWidgets, WebChannel
- Multimedia, MultimediaWidgets
Qt is typically installed via the Qt Online Installer. Ensure the Qt installation is discoverable by CMake (either in your PATH or via CMAKE_PREFIX_PATH).
MacPorts (macOS): MacPorts installs Qt6 to /opt/local/libexec/qt6, which is not on CMake's default search path. You must pass the prefix explicitly:
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/opt/local/libexec/qt6This is forwarded automatically to third-party and application sub-builds.
Required Boost components: header-only (boost::geometry).
If Boost is not found automatically, set BOOST_ROOT:
# Windows (prebuilt binaries)
cmake ... -DBOOST_ROOT="C:/Program Files/Boost/boost_1_87_0"
# macOS (Homebrew)
cmake ... -DBOOST_ROOT=/opt/homebrew # Apple Silicon
cmake ... -DBOOST_ROOT=/usr/local # Intel
# Linux (apt)
cmake ... -DBOOST_ROOT=/usrPython 3.10+ with development headers is required for pybind11 embedding. The build downloads a matching python-build-standalone release to bundle with the application, so the build-time Python version must be available in that project's releases.
- Windows: Install from python.org. Check "Download debug binaries" during installation if you plan to build Debug configurations.
- macOS: The system Python (
/usr/bin/python3, typically 3.9.6) is too old — python-build-standalone no longer publishes 3.9.x builds. Install a modern Python via MacPorts (port install python313) or Homebrew (brew install python), then point CMake at it (see below). - Linux: System Python is usually sufficient. Ensure development headers are available (
Python.h).
MacPorts (macOS): MacPorts Python is not on CMake's default search path. You must tell CMake where to find it:
cmake ... -DPython_ROOT_DIR=/opt/local -DPython_EXECUTABLE=/opt/local/bin/python3.13These flags are forwarded automatically to sub-builds.
This is the default build mode that builds all third-party dependencies (GeographicLib, KDDockWidgets) and the main application.
Windows:
cmake -G "Visual Studio 17 2022" -A x64 -B build -S . -DCMAKE_PREFIX_PATH="C:/Qt/6.9.3/msvc2022_64" -DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build build --config ReleasemacOS (MacPorts):
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/opt/local/libexec/qt6 \
-DPython_ROOT_DIR=/opt/local \
-DPython_EXECUTABLE=/opt/local/bin/python3.13 \
-DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build buildLinux:
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build buildBuild only the third-party dependencies without building the application:
Windows:
cmake -G "Visual Studio 17 2022" -A x64 -B build -S . -DCMAKE_PREFIX_PATH="C:/Qt/6.9.3/msvc2022_64" -DFLYSIGHT_THIRD_PARTY_ONLY=ON
cmake --build build --config ReleasemacOS / Linux:
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DFLYSIGHT_THIRD_PARTY_ONLY=ON
cmake --build buildAlternatively, build from the third-party/ directory directly:
cd third-party
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build buildIf third-party dependencies are already built and installed in the third-party/*-install directories:
Windows:
cmake -G "Visual Studio 17 2022" -A x64 -B build -S . -DCMAKE_PREFIX_PATH="C:/Qt/6.9.3/msvc2022_64" -DGOOGLE_MAPS_API_KEY="your-api-key" -DFLYSIGHT_BUILD_THIRD_PARTY=OFF
cmake --build build --config ReleasemacOS / Linux:
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DGOOGLE_MAPS_API_KEY="your-api-key" -DFLYSIGHT_BUILD_THIRD_PARTY=OFF
cmake --build build| Option | Default | Description |
|---|---|---|
FLYSIGHT_BUILD_THIRD_PARTY |
ON |
Build third-party dependencies (GeographicLib, KDDockWidgets) |
FLYSIGHT_BUILD_APP |
ON |
Build the main FlySight Viewer application |
FLYSIGHT_THIRD_PARTY_ONLY |
OFF |
Build only third-party dependencies (automatically disables app build) |
GOOGLE_MAPS_API_KEY |
(none) | Google Maps JavaScript API key for the map view |
Path Variables:
| Variable | Default | Description |
|---|---|---|
THIRD_PARTY_DIR |
<project>/third-party |
Root directory for third-party dependencies |
GEOGRAPHIC_INSTALL_DIR |
<third-party>/GeographicLib-install |
GeographicLib installation directory |
KDDW_INSTALL_DIR |
<third-party>/KDDockWidgets-install |
KDDockWidgets installation directory |
BOOST_ROOT |
Platform-dependent | Boost root directory |
After a successful build:
| Component | Install Directory |
|---|---|
| GeographicLib | third-party/GeographicLib-install/ |
| KDDockWidgets | third-party/KDDockWidgets-install/ |
| Application | build/ (executables in build root) |
Clean individual third-party components:
cmake --build build --target clean-GeographicLib
cmake --build build --target clean-KDDockWidgets
cmake --build build --target clean-third-party # all third-partyWhen building from the third-party/ directory, clean-all is available as an alias for clean-third-party.
For a complete reset, delete the build and install directories:
Windows (PowerShell):
Remove-Item -Recurse -Force build
Remove-Item -Recurse -Force third-party\GeographicLib-build, third-party\GeographicLib-install
Remove-Item -Recurse -Force third-party\KDDockWidgets-build, third-party\KDDockWidgets-installmacOS / Linux:
rm -rf build
rm -rf third-party/{GeographicLib,KDDockWidgets}-{build,install}| Target | Description |
|---|---|
clean-GeographicLib |
Removes third-party/GeographicLib-build and third-party/GeographicLib-install |
clean-KDDockWidgets |
Removes third-party/KDDockWidgets-build and third-party/KDDockWidgets-install |
clean-third-party |
Cleans all third-party components |
flysight-viewer-2/
├── CMakeLists.txt # Root superbuild configuration
├── README.md # This file
├── cmake/
│ ├── ThirdPartySuperbuild.cmake # ExternalProject definitions for GeographicLib, KDDockWidgets
│ ├── BoostDiscovery.cmake # Cross-platform Boost discovery
│ ├── QtPathDiscovery.cmake # Finds Qt plugin/QML directories
│ ├── GenerateIcon.cmake # Application icon generation
│ ├── BundlePythonWindows.cmake # Downloads/installs Python embeddable package
│ ├── BundlePythonMacOS.cmake # Downloads/installs python-build-standalone
│ ├── BundlePythonLinux.cmake # Downloads/installs python-build-standalone
│ ├── DeployThirdPartyWindows.cmake # Copies GeographicLib/KDDW DLLs
│ ├── DeployThirdPartyMacOS.cmake # Copies dylibs to Frameworks, fixes paths
│ ├── DeployThirdPartyLinux.cmake # Copies .so files to AppDir, sets RPATH
│ ├── CreateAppDir.cmake # Creates Linux AppDir structure with AppRun
│ ├── CreateAppImage.cmake # Generates AppImage via appimagetool
│ ├── RunLinuxDeployQt.cmake # Optional linuxdeployqt integration
│ ├── fix_macos_rpaths.sh # Post-install rpath repair for macOS bundles
│ └── diagnose_macos_bundle.sh # Diagnostic tool for macOS bundle issues
├── src/
│ └── CMakeLists.txt # Main application build configuration
├── third-party/
│ ├── CMakeLists.txt # Standalone third-party build
│ ├── GeographicLib/ # GeographicLib source
│ ├── KDDockWidgets/ # KDDockWidgets submodule
│ ├── QCustomPlot/ # QCustomPlot library
│ └── pybind11/ # pybind11 submodule
├── third-party/GeographicLib-install/ # [Build artifact] GeographicLib installation
├── third-party/KDDockWidgets-install/ # [Build artifact] KDDockWidgets installation
└── build/ # [Build artifact] CMake build directory
FlySight Viewer deploys as a self-contained application with a bundled Python interpreter, requiring no user-installed dependencies. The cmake --install command handles all deployment steps automatically, including Qt library bundling, third-party library copying, Python bundling, and platform-specific path fixups.
cmake --install triggers platform-specific install rules that handle:
| Concern | Windows | macOS | Linux |
|---|---|---|---|
| Qt libraries & plugins | qt_generate_deploy_app_script |
qt_generate_deploy_app_script |
qt_generate_deploy_app_script |
| map.html (Google Maps) | Installed to resources/ |
Installed to Resources/resources/ |
Installed to usr/resources/ |
| Third-party libs (GeographicLib, KDDW) | DLLs copied to app root | dylibs copied to Frameworks/ |
.so files copied to usr/lib/ |
| Python runtime | Embeddable package downloaded | python-build-standalone downloaded | python-build-standalone downloaded |
| Library path fixups | N/A (flat DLL layout) | install_name_tool (automatic) |
patchelf (automatic) |
qt.conf |
Generated in app root | Generated in Resources/ |
Generated in usr/bin/ |
| AppDir + AppRun | N/A | N/A | Created automatically |
There is no need to manually run macdeployqt, windeployqt, copy libraries, or fix rpaths. The CMake install rules handle all of this.
# 1. Build
cmake -G "Visual Studio 17 2022" -A x64 -B build -S . -DCMAKE_PREFIX_PATH="C:/Qt/6.9.3/msvc2022_64" -DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build build --config Release
# 2. Install (creates self-contained deployment)
cmake --install build --config Release --prefix dist
# 3. Package (ZIP)
cpack --config build/FlySightViewer-build/CPackConfig.cmake -G ZIP -C ReleaseThe install step produces a flat directory with the executable, all DLLs, Qt plugins, QML modules, and the bundled Python runtime.
# 1. Build (MacPorts example — adjust Python path for Homebrew)
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/opt/local/libexec/qt6 \
-DPython_ROOT_DIR=/opt/local \
-DPython_EXECUTABLE=/opt/local/bin/python3.13 \
-DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build build
# 2. Install (creates .app bundle with Frameworks, Python, etc.)
# The install step automatically ad-hoc signs all binaries, so the
# app is immediately runnable for development and testing.
cmake --install build --prefix distDistribution builds require a Developer ID certificate. Pass your signing identity at configure time — the install step will sign everything with your certificate instead of ad-hoc, including --timestamp and --options runtime (required for notarization):
# Tip: Run `security find-identity -v -p codesigning` to list your
# installed certificates. The 10-character code in parentheses after
# "Developer ID Application: Name (XXXXXXXXXX)" is your team-id.
# 1. Configure with signing identity
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/opt/local/libexec/qt6 \
-DPython_ROOT_DIR=/opt/local \
-DPython_EXECUTABLE=/opt/local/bin/python3.13 \
-DGOOGLE_MAPS_API_KEY="your-api-key" \
-DFLYSIGHT_CODESIGN_IDENTITY="Developer ID Application: Your Name (XXXXXXXXXX)"
cmake --build build
# 2. Install (creates signed .app bundle)
cmake --install build --prefix dist
# 3. Create DMG
hdiutil create -volname "FlySight Viewer" \
-srcfolder "dist/FlySight Viewer.app" \
-ov -format UDZO FlySightViewer.dmg
# 4. Notarize
xcrun notarytool submit FlySightViewer.dmg \
--apple-id [email protected] \
--team-id XXXXXXXXXX \
--password @keychain:notary-password \
--wait
xcrun stapler staple FlySightViewer.dmg# 1. Build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DGOOGLE_MAPS_API_KEY="your-api-key"
cmake --build build
# 2. Install (creates AppDir with AppRun, libraries, Python, etc.)
cmake --install build --prefix dist
# 3. Create AppImage
cmake --build build --target appimageThe appimage target runs pre-flight verification (checks for all critical libraries, Qt plugins, Python bundle) before invoking appimagetool.
GitHub Actions (.github/workflows/build.yml) automates the full pipeline on all three platforms. The workflow:
- Caches third-party dependencies between runs
- Builds third-party deps (on cache miss) then the application
- Runs
cmake --installto trigger all deployment logic - Packages with CPack (ZIP on Windows, DMG on macOS, AppImage on Linux)
- Uploads artifacts and creates GitHub Releases on version tags
The CI workflow uses GitHub repository secrets to enable the Google Maps map view and macOS code signing/notarization. Without secrets (e.g. forks, PRs from external contributors), the map view is disabled and macOS builds fall back to ad-hoc signing.
To configure secrets, go to your repository on GitHub: Settings > Secrets and variables > Actions > New repository secret, and add the secrets listed below.
| Secret | Value |
|---|---|
GOOGLE_MAPS_API_KEY |
Your Google Maps JavaScript API key |
To obtain a key, create a project in the Google Cloud Console, enable the Maps JavaScript API, and create an API key under APIs & Services > Credentials. Since the key is embedded in the distributed application binary, it is recommended to restrict the key to the Maps JavaScript API only and set appropriate usage quotas and billing alerts.
To set up code signing, you need a Developer ID Application certificate installed on your Mac:
1. Find your signing identity:
security find-identity -v -p codesigningLook for the line containing Developer ID Application: Your Name (XXXXXXXXXX). The full string is your signing identity, and the 10-character code in parentheses is your team ID.
2. Export the certificate as a .p12 file:
Open Keychain Access (Applications > Utilities), select login in the left sidebar, then switch to the My Certificates tab across the top (not "Certificates" — only "My Certificates" shows certificates paired with their private keys). Find your "Developer ID Application" certificate, expand the disclosure triangle next to it, select the private key underneath, right-click it, and choose Export. Save as .p12 format and set a strong password.
3. Base64-encode the .p12 file:
base64 -i Certificates.p12 | pbcopyThis copies the base64 string to your clipboard.
4. Generate an app-specific password for notarization:
Go to appleid.apple.com > Sign-In and Security > App-Specific Passwords, and generate a new password for "FlySight Notarization" (or similar).
5. Add these secrets to the repository:
| Secret | Value |
|---|---|
MACOS_CERTIFICATE_P12_BASE64 |
The base64 string from step 3 |
MACOS_CERTIFICATE_PASSWORD |
The password you set when exporting the .p12 |
MACOS_CODESIGN_IDENTITY |
Full identity, e.g. Developer ID Application: Your Name (XXXXXXXXXX) |
MACOS_NOTARIZATION_APPLE_ID |
Your Apple ID email address |
MACOS_NOTARIZATION_PASSWORD |
The app-specific password from step 4 |
MACOS_NOTARIZATION_TEAM_ID |
Your 10-character team ID from step 1 |
Once configured, all macOS CI builds will be distribution-signed, and tag builds (v*) will additionally be notarized and stapled so end users can run the app without Gatekeeper warnings.
Windows:
FlySightViewer/
├── FlySightViewer.exe
├── flysight_cpp_bridge.pyd
├── Qt6Core.dll, Qt6Widgets.dll, ...
├── Geographic.dll, ...
├── qt.conf
├── plugins/
│ ├── platforms/
│ └── ...
├── qml/
│ └── ...
├── resources/
│ └── map.html
└── python/
├── python313.dll
├── python313.zip
└── Lib/site-packages/
macOS:
FlySightViewer.app/
└── Contents/
├── MacOS/FlySightViewer
├── Frameworks/
│ ├── QtCore.framework, ...
│ ├── libGeographic.dylib, ...
│ ├── libkddockwidgets-qt6.3.dylib
│ └── libpython3.XX.dylib
├── PlugIns/
│ ├── platforms/
│ └── ...
└── Resources/
├── qt.conf
├── qml/
│ └── ...
├── resources/
│ └── map.html
├── python/
│ └── lib/python3.XX/site-packages/
└── python_plugins/
Linux (AppImage contents):
FlySightViewer.AppDir/
├── AppRun
├── FlySightViewer.desktop
├── FlySightViewer.png
└── usr/
├── bin/
│ ├── FlySightViewer
│ └── qt.conf
├── lib/
│ ├── libQt6*.so.*, libGeographic.so.*, ...
│ └── libkddockwidgets-qt6.so.*
├── plugins/
│ ├── platforms/
│ └── ...
├── qml/
│ └── ...
├── resources/
│ └── map.html
└── share/
└── python/
├── bin/python3
└── lib/python3.XX/site-packages/
-
Python Version Matching: The bundled Python version must exactly match the version used to build the pybind11 bindings. A version mismatch will cause crashes at startup.
-
Package Sizes: Expect approximately 80-120 MB per platform (includes Qt, Python, and NumPy).
-
Testing: Always test the deployed package on a clean machine without development tools installed.
-
macOS Signing: The install step handles code signing automatically — ad-hoc by default, or with your Developer ID certificate if
FLYSIGHT_CODESIGN_IDENTITYis set at configure time. No manual signing step is needed.
Symptom: CMake error: Could not find a package configuration file provided by "Qt6" or a Qt6 sub-module like Qt6QuickControls2.
Solution:
- Ensure Qt 6 is installed with all required components (see Qt Components)
- Set
CMAKE_PREFIX_PATHto your Qt installation:# Windows cmake ... -DCMAKE_PREFIX_PATH="C:/Qt/6.7.3/msvc2019_64" # macOS (Homebrew Qt or Qt Online Installer) cmake ... -DCMAKE_PREFIX_PATH="$HOME/Qt/6.7.3/macos" # macOS (MacPorts) — required, see Prerequisites cmake ... -DCMAKE_PREFIX_PATH=/opt/local/libexec/qt6 # Linux cmake ... -DCMAKE_PREFIX_PATH="$HOME/Qt/6.7.3/gcc_64"
Symptom: CMake error: Could not find a configuration file for package "Boost".
Solution:
- Verify Boost is installed (header-only usage for boost::geometry)
- Set
BOOST_ROOTas shown in Prerequisites > Boost Components
Symptom: CMake error: Could not find a package configuration file provided by "Python" or missing Python.h.
Solution:
- Install Python 3.10+ with development headers
- On Windows, ensure "Download debug binaries" was checked during installation for Debug builds
- Verify Python is in your PATH:
python --version - If multiple Python versions are installed, set
Python_ROOT_DIR:cmake ... -DPython_ROOT_DIR="/path/to/python"
Symptom: CMake error: Failed to download after 3 attempts when downloading from python-build-standalone.
Cause: The build-time Python version doesn't exist in the python-build-standalone release. This commonly happens on macOS when CMake finds the system Python 3.9.6, which is too old to have a matching standalone build.
Solution:
- Install a modern Python (3.10+) via MacPorts or Homebrew
- Point CMake at it with
-DPython_ROOT_DIRand-DPython_EXECUTABLE(see Prerequisites > Python)
Symptom: KDDockWidgets build fails with Qt6 not found errors.
Solution:
- Ensure Qt6 is properly installed and discoverable
- The KDDockWidgets build uses
-DKDDockWidgets_QT6=ONto enable Qt6 support - Set
CMAKE_PREFIX_PATHif Qt is not in a standard location
Solution:
- Use Ninja for faster builds:
-G Ninja - Use parallel builds:
cmake --build build --parallel - After initial build, use
-DFLYSIGHT_BUILD_THIRD_PARTY=OFFto skip rebuilding dependencies
To reset all stored preferences for FlySight Viewer on macOS:
defaults delete com.flysight.ViewerTo reset all stored preferences for FlySight Viewer on Windows:
reg delete "HKEY_CURRENT_USER\Software\FlySight\FlySightViewer" /fTo also reset built-in profiles (so they are re-copied on next launch), delete the profiles directory:
del /q "%USERPROFILE%\Documents\FlySight Viewer\profiles\*.fvprofile"Symptom: The Visual Studio solution contains many projects (GeographicLib, KDDockWidgets targets).
Explanation: This is expected behavior for a superbuild. The solution includes ExternalProject targets for third-party dependencies, the main application targets, and clean targets.
Tip: Set FlySightViewer as the startup project for development.