diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c615a35..bc4508e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -248,6 +248,55 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # ── Job 2d: Windows x64 portable zip ────────────────────────────────────── + windows-x64: + name: Windows (x64) + needs: source-tarball + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Configure + run: cmake -B build -DCMAKE_BUILD_TYPE=Release -DHAWKEYE_VERSION=${{ needs.source-tarball.outputs.version }} + + - name: Build + run: cmake --build build --config Release + + - name: Stage release + shell: pwsh + run: | + $version = "${{ needs.source-tarball.outputs.version }}" + $stage = "hawkeye-$version-windows-x64" + New-Item -ItemType Directory -Path $stage | Out-Null + Copy-Item "build\Release\hawkeye.exe" $stage + Copy-Item -Recurse "build\Release\models" $stage + Copy-Item -Recurse "build\Release\shaders" $stage + Copy-Item -Recurse "build\Release\fonts" $stage + Copy-Item -Recurse "build\Release\textures" $stage + Copy-Item -Recurse "build\Release\themes" $stage + Copy-Item "LICENSE" $stage + Copy-Item "README.md" $stage + Compress-Archive -Path $stage -DestinationPath "$stage.zip" + + - name: Smoke test + shell: pwsh + run: | + $exe = "build\Release\hawkeye.exe" + if (-not (Test-Path $exe)) { throw "hawkeye.exe not produced" } + & $exe --help + if ($LASTEXITCODE -ne 0) { throw "hawkeye --help exited $LASTEXITCODE" } + + - name: Upload zip to release + shell: pwsh + run: | + $version = "${{ needs.source-tarball.outputs.version }}" + gh release upload ${{ github.ref_name }} "hawkeye-$version-windows-x64.zip" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # ── Job 3: Update Homebrew tap ───────────────────────────────────────────── update-tap: name: Update Homebrew tap diff --git a/README.md b/README.md index 5ccb397..e434e94 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,13 @@ Download the `.deb` from the [latest release](https://github.com/PX4/Hawkeye/rel sudo dpkg -i hawkeye-*.deb ``` -### Windows and source builds +### Windows + +Download `hawkeye--windows-x64.zip` from the [latest release](https://github.com/PX4/Hawkeye/releases/latest), extract it anywhere, and run `hawkeye.exe`. + +On first launch, Windows SmartScreen may warn that the binary is from an unknown publisher — click "More info" → "Run anyway". The ZIP is unsigned; we're working on winget distribution to remove this warning. + +### Source builds See [Building from source](https://px4.github.io/Hawkeye/developer/build) in the developer docs. diff --git a/docs/developer/build.md b/docs/developer/build.md index 7a054c0..d726236 100644 --- a/docs/developer/build.md +++ b/docs/developer/build.md @@ -1,7 +1,7 @@ # Building from source -You only need to build from source if you want to modify Hawkeye, run pre-release code, or target a platform without a package (currently Windows). -For everyday use, the Homebrew formula or `.deb` package described in [Installation](../installation.md) is the faster path. +You only need to build from source if you want to modify Hawkeye or run pre-release code. +For everyday use, the Homebrew formula, `.deb` package, or Windows ZIP described in [Installation](../installation.md) is the faster path. ::: info Clone with `--recursive`. diff --git a/docs/installation.md b/docs/installation.md index 288af9f..e70709f 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,7 +1,7 @@ # Installation -Hawkeye ships as a Homebrew formula on macOS and a `.deb` package on Debian/Ubuntu. -For Windows, or if you want the latest development build, see [Building from source](./developer/build.md). +Hawkeye ships as a Homebrew formula on macOS, a `.deb` package on Debian/Ubuntu, and a portable ZIP on Windows. +If you want the latest development build, see [Building from source](./developer/build.md). ## macOS (Homebrew) @@ -29,7 +29,15 @@ ARM64 builds (Raspberry Pi, Jetson, cloud ARM instances) are published in the sa ## Windows -No prebuilt Windows package yet. Follow [Building from source](./developer/build.md) for the full procedure (Visual Studio 2022 + CMake + Git). +Download `hawkeye--windows-x64.zip` from the [Hawkeye releases page](https://github.com/PX4/Hawkeye/releases/latest), extract it anywhere (e.g. `C:\Tools\hawkeye`), and double-click `hawkeye.exe`. + +The ZIP is self-contained — no Visual Studio or runtime installer required. User data (screenshots, markers) is written to `%APPDATA%\hawkeye`. + +::: info First-launch warning +Windows SmartScreen may warn that `hawkeye.exe` is from an unknown publisher. Click "More info" → "Run anyway". The binary is unsigned; signing and winget distribution are on the roadmap. +::: + +To launch from any terminal, add the extracted folder to your `PATH`. ## Verifying the install diff --git a/src/asset_path.c b/src/asset_path.c index 75577a6..dc3d35c 100644 --- a/src/asset_path.c +++ b/src/asset_path.c @@ -7,6 +7,7 @@ #ifdef _WIN32 #include +#include #define mkdir_p(path) _mkdir(path) #else #include @@ -65,7 +66,13 @@ void asset_path_init(void) { snprintf(s_user_data, sizeof(s_user_data), "%s/Library/Application Support/hawkeye", home); } -#elif !defined(_WIN32) +#elif defined(_WIN32) + const char *appdata = getenv("APPDATA"); + if (appdata && appdata[0]) { + snprintf(s_user_data, sizeof(s_user_data), + "%s\\hawkeye", appdata); + } +#else // Linux: XDG_DATA_HOME or ~/.local/share const char *xdg = getenv("XDG_DATA_HOME"); if (xdg && xdg[0]) { @@ -80,8 +87,20 @@ void asset_path_init(void) { } #endif - // Compile-time install prefix (set by CMake) -#ifdef HAWKEYE_INSTALL_DATADIR +#ifdef _WIN32 + // On Windows we ship a portable ZIP: assets live next to hawkeye.exe, + // so resolve the install dir from the running executable rather than a + // compile-time CMake path (which encodes a Unix-style /usr layout). + char exe_path[MAX_PATH]; + DWORD len = GetModuleFileNameA(NULL, exe_path, sizeof(exe_path)); + if (len > 0 && len < sizeof(exe_path)) { + char *last_sep = strrchr(exe_path, '\\'); + if (last_sep) { + *last_sep = '\0'; + snprintf(s_install_data, sizeof(s_install_data), "%s", exe_path); + } + } +#elif defined(HAWKEYE_INSTALL_DATADIR) snprintf(s_install_data, sizeof(s_install_data), "%s", HAWKEYE_INSTALL_DATADIR); #endif diff --git a/src/asset_path.h b/src/asset_path.h index 6adaec8..832d6c4 100644 --- a/src/asset_path.h +++ b/src/asset_path.h @@ -8,16 +8,19 @@ void asset_path_init(void); // Resolve an asset subpath (e.g. "models/px4_quadrotor.obj") to a full path. // Writes into caller-provided buffer. Search order: -// macOS: ~/Library/Application Support/hawkeye/ -// Linux: $XDG_DATA_HOME/hawkeye/ -// Then: HAWKEYE_INSTALL_DATADIR/ (compile-time install prefix) -// Then: ./ (dev/build fallback) +// macOS: ~/Library/Application Support/hawkeye/ +// Linux: $XDG_DATA_HOME/hawkeye/ +// Windows: %APPDATA%\hawkeye\ +// Then: HAWKEYE_INSTALL_DATADIR/ (Unix install prefix) +// or / (Windows portable layout) +// Then: ./ (dev/build fallback) void asset_path(const char *subpath, char *out, size_t out_size); // Get a writable path for an asset (for generated files like terrain texture). // Always returns the user data directory path, creating directories as needed. -// macOS: ~/Library/Application Support/hawkeye/ -// Linux: $XDG_DATA_HOME/hawkeye/ +// macOS: ~/Library/Application Support/hawkeye/ +// Linux: $XDG_DATA_HOME/hawkeye/ +// Windows: %APPDATA%\hawkeye\ void asset_write_path(const char *subpath, char *out, size_t out_size); #endif