mirror of
https://github.com/logos-co/logos-logoscore-cli.git
synced 2026-08-30 20:31:09 +00:00
feat(windows): build and publish Windows bundles for logoscore and logosctl (#88)
* feat(windows): build and publish Windows bundles for logoscore and logosctl Neither tool had a downloadable Windows artifact. A release/* push produced AppImage tarballs per Linux arch and a macOS bundle per tool, and nothing a Windows user could open. `build-windows-bundle` is one more leg of the shape build-macos-bundle already uses -- the same two tools, the same cli-bundle-dir / ctl-bundle-dir outputs, both verified to resolve for x86_64-windows. It cross-builds on ubuntu-latest, because nix does not run on Windows. NO SMOKE TEST HERE, deliberately: a Linux runner cannot execute a PE. Running the binary is what logos-windows-ci's native-smoke leg does on a real windows-latest runner. Asserting `--help` under wine would be a weaker claim wearing the same clothes. The packaging step asserts instead of trusting its exit code. The bundles' DLLs are symlinks into the nix store, and an archive of dangling links extracts to a tree that cannot start -- nix-bundle-lgx shipped exactly that, losing 75% of a payload while exiting 0. So it copies with -L, compares the zip's entry count against the bundle's file count and fails on a shortfall, and refuses a bundle with no .exe. The comparison is `<` rather than `!=` because a zip counts directory entries too, so a healthy bundle yields MORE entries than files (measured on a real bundle: 1677 files -> 1768 entries). One YAML trap worth recording: `files:` in the release job is a LITERAL block scalar, so every line is a glob handed to the action and a '#' line would be passed as a pattern rather than ignored. The commentary sits above the key. * ci: take Nix and the cache from setup-nix-cache-action, drop the disk reclaim The Windows legs failed after 27 minutes rebuilding boost, libpng, sqlite and Qt from source. They were not slow -- they were reading the wrong cache. This file pointed at the `logos-co` CACHIX cache, while the mingw closure is primed in the Logos ATTIC cache. Measured on the failed run: 0 paths from cache.nix.logos.co, 9 from cachix, 612 from cache.nixos.org. All three build jobs now use logos-co/setup-nix-cache-action@v1, which replaces three different setups (install-nix-action@v27, DeterminateSystems, and cachix-action). Verified the closure this repo resolves is the one that is primed: logos-nix 6e0f4a71 and nixpkgs e9f00bd8 are identical to logos-basecamp, whose Windows job is green off this cache, and the two paths that mattered resolve to attic/ci HTTP 200: boost-x86_64-w64-mingw32-1.89.0 <- the derivation that actually failed qtbase-x86_64-w64-mingw32-6.11.1 Reading needs no credentials -- both Attic caches are public to read and the action configures the substituters unconditionally. Publishing stays inactive until this repo gets ATTIC_TOKEN_CI; the action skips an empty token rather than failing. The disk reclaim is removed as unnecessary rather than kept as insurance. Its justification cited "~14 GiB free", which is stale -- a real run reports `/dev/root 145G 37G used 108G avail`. It was deleting ~10 GiB from a disk with 108 GiB spare, and with the cache substituting instead of building, the build-time store pressure drops further. Also documents the Windows leg in the header, which was missed when the job was added. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(windows): stage bundled modules through the install bundler The shipped Windows bundle declared **Qt6Core.dll** as capability_module's entry point: "main": { "windows-x86_64-dev": "Qt6Core.dll", ... } That is not cosmetic. The module scanner is manifest-driven -- it resolves exactly ONE path per module, the one `main` names -- so it opened Qt6Core.dll because the manifest told it to, failed to parse metadata, and returned before inserting into the registry. capability_module, the auth handshake every client needs, was silently dead in every bundle we have shipped. ROOT CAUSE, and it was upstream of this repo. mkBinWindows hand-copied `${liblogos}/modules`, whose generator (logos-liblogos/nix/modules.nix) carries two Unix-shaped assumptions that only combine into a defect on Windows: * it globs `${capabilityModule}/lib/*.dll` -- on Unix `*.so`/`*.dylib` match only the plugin, but on Windows linkDLLsInfolder has already staged 14 dependency DLLs into that same lib/ dir, so all 15 were copied; * it then picks the entry point by taking the FIRST regular file in the directory, which alphabetically is Qt6Core.dll. Neither is visible natively and the build succeeded either way. THE FIX is to stop hand-copying and use the mechanism the native builds and logos-basecamp already use -- installPortable -> nix-bundle-lgx, which derives `main` from the module's authored metadata.json rather than a directory listing, and strips the host-provided runtime DLLs that bin/ already ships. mkBinWindows gains `withPkgModules` to match mkBin/mkBinPortable. That also ships package_manager and package_downloader on Windows, which the comment here documented as blocked. The blocker was real and has cleared upstream: logos-package-downloader-module gained packages.x86_64-windows when it bumped logos-module-builder 8e4ea1c -> 9d3b7cc. This flake was 3 commits behind; a single-input re-lock was the whole fix. The comment's stated reason for not shipping half was also wrong, and is corrected in place. MEASURED on the builder, x86_64-windows ctl-bundle-dir, now byte-for-byte the shape logos-basecamp produces: modules/capability_module 15 entries, main=Qt6Core.dll -> 3 entries, main=capability_module_plugin.dll modules-pkg/package_manager absent -> 7 entries modules-pkg/package_downloader absent -> 19 entries (its libcurl closure) A build-time guard now asserts every manifest's `main` names <module>_plugin.*, because every structural check we had -- file counts, PE counts, zip entry counts -- passed on the broken bundle. Verified both ways: it rejects the exact manifest that shipped and accepts the corrected one, and appears in the real derivation closure rather than being decorative. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(windows): build the PORTABLE logosctl, matching the portable modules The previous commit moved the bundled modules onto the install bundler, which installs them as variant `windows-x86_64`. The binary was still the dev build, and a dev build accepts only `-dev` variants -- so all three modules were refused at startup: module 'capability_module' ... was installed for variant 'windows-x86_64' which is not supported on this platform and will not be loadable: supported variants [windows-x86_64-dev]. That skew was introduced by the previous commit: before it, hand-copied dev modules happened to match a dev binary (while carrying the broken manifest). `portable` is not only a LAYOUT distinction, which is what the comment in this file previously claimed when it called portable "redundant" on Windows. It is also a COMPILE-TIME one: LGPM_PORTABLE_BUILD (logos-package-manager CMakeLists.txt:58) decides what platformVariantsToTry() returns, appending "-dev" when absent (package_manager_lib.cpp:1005-1008). The old reasoning was right that a PE has no rpath and needs no @rpath/$ORIGIN variant, and wrong to conclude from that that portable had nothing left to mean here. mkBinWindows now builds from buildPortable/liblogosPortable. buildPortable needed the two Windows fixes `build` already carried: the Qt host-tool cmakeFlags, and the !isWindows guard on wrapQtAppsNoGuiHook (which cannot evaluate for a mingw host). Also escaped a `${liblogos}` that sat inside a shell COMMENT in a Nix '' string, where it is still interpolated -- it was pulling the dev liblogos into the portable bundle's build closure. MEASURED on the builder: * all three modules declare variant `windows-x86_64` (was: refused) * the shipped bin/libpackage_manager_lib.dll is byte-identical to the copy in logos-liblogos-portable, and DIFFERS from the dev lib output * dev liblogos paths in the bundle closure: 0 Two probes were discarded as unsound before landing this, both returning a zero that meant "cannot see" rather than "not present": `strings | grep windows-x86_64-dev` reports 0 for dev AND portable builds, because the suffix is constructed at runtime and never stored; and grepping the derivation closure for LGPM_PORTABLE_BUILD=ON matches in both cases, because the portable MODULE is present either way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1a4f56fe2b
commit
cbd4c0967b
@@ -24,6 +24,27 @@ name: Build & Release
|
||||
# macOS (aarch64): build the portable bundle dir (bin/ + lib/),
|
||||
# strip the Gatekeeper quarantine flag the way
|
||||
# Homebrew handles casks, wrap in a tar.gz.
|
||||
# Windows (x86_64): cross-build the bundle dir on a Linux runner and
|
||||
# zip it. Nix does not run on Windows, so there is
|
||||
# no native leg here at all.
|
||||
#
|
||||
# Nix and the binary cache come from logos-co/setup-nix-cache-action, replacing
|
||||
# three different setups this file used to carry (install-nix-action@v27,
|
||||
# DeterminateSystems, and cachix/cachix-action pointed at the `logos-co` cachix).
|
||||
#
|
||||
# The swap is what makes the Windows leg viable, and it was measured rather than
|
||||
# assumed. The mingw Qt/boost closure is primed in the Logos Attic cache
|
||||
# (cache.nix.logos.co), NOT in cachix, so the first Windows run substituted
|
||||
# nothing from it -- 0 paths from Attic against 612 from cache.nixos.org -- and
|
||||
# spent 27 minutes rebuilding boost, libpng, sqlite and Qt from source before
|
||||
# falling over inside boost.
|
||||
#
|
||||
# Reading needs no credentials: both Attic caches are public to read, and the
|
||||
# action configures them as substituters unconditionally, so fork PRs pull too.
|
||||
# PUBLISHING is separate and currently inactive here -- this repo has neither
|
||||
# ATTIC_TOKEN_CI nor the public-cache environment that carries
|
||||
# ATTIC_TOKEN_PUBLIC, and the action skips the push on an empty token rather
|
||||
# than failing. Adding the repo secret turns publishing on with no edit here.
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -51,15 +72,9 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: cachix/install-nix-action@v27
|
||||
- uses: logos-co/setup-nix-cache-action@v1
|
||||
with:
|
||||
extra_nix_config: |
|
||||
experimental-features = nix-command flakes
|
||||
|
||||
- uses: cachix/cachix-action@v15
|
||||
with:
|
||||
name: logos-co
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
attic-token-ci: ${{ secrets.ATTIC_TOKEN_CI }}
|
||||
|
||||
- name: Build ${{ matrix.tool.output }}
|
||||
run: nix build .#${{ matrix.tool.output }} -L
|
||||
@@ -98,12 +113,9 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: DeterminateSystems/nix-installer-action@main
|
||||
|
||||
- uses: cachix/cachix-action@v15
|
||||
- uses: logos-co/setup-nix-cache-action@v1
|
||||
with:
|
||||
name: logos-co
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
attic-token-ci: ${{ secrets.ATTIC_TOKEN_CI }}
|
||||
|
||||
- name: Build ${{ matrix.tool.output }}
|
||||
run: nix build .#${{ matrix.tool.output }} -L
|
||||
@@ -133,9 +145,72 @@ jobs:
|
||||
name: macos-${{ matrix.tool.bin }}-aarch64-darwin
|
||||
path: ${{ matrix.tool.bin }}-aarch64-macos.tar.gz
|
||||
|
||||
# ────────────────────────────────────────────────────────────────────────
|
||||
# Windows. A CROSS build on a Linux runner -- nix does not run on Windows, so
|
||||
# there is no windows-latest runner here. Executing the result on real Windows
|
||||
# is covered separately by logos-windows-ci.
|
||||
#
|
||||
# Same two tools and the same bundle-dir outputs the macOS job packages, so
|
||||
# this is one more leg of an established shape rather than a new one.
|
||||
build-windows-bundle:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
tool:
|
||||
- { bin: logoscore, output: cli-bundle-dir }
|
||||
- { bin: logosctl, output: ctl-bundle-dir }
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: logos-co/setup-nix-cache-action@v1
|
||||
with:
|
||||
attic-token-ci: ${{ secrets.ATTIC_TOKEN_CI }}
|
||||
|
||||
- name: Build ${{ matrix.tool.output }} for Windows
|
||||
run: nix build .#packages.x86_64-windows.${{ matrix.tool.output }} -L
|
||||
|
||||
# NO smoke test here, and that is deliberate rather than an omission: this
|
||||
# runner cannot execute a PE. Running the binary is what logos-windows-ci's
|
||||
# native-smoke leg does, on a real windows-latest runner. Asserting
|
||||
# `--help` under wine would be a weaker claim dressed as the same one.
|
||||
- name: Package bundle as a zip
|
||||
run: |
|
||||
set -euo pipefail
|
||||
dst="${{ matrix.tool.bin }}-x86_64-windows"
|
||||
src=$(readlink -f result)
|
||||
staged=$(find -L "$src" -type f | wc -l | tr -d ' ')
|
||||
[ "$staged" -gt 0 ] || { echo "::error::the bundle is empty"; exit 1; }
|
||||
# -L DEREFERENCES. The bundle's DLLs are symlinks into the nix store,
|
||||
# and an archive of dangling links extracts to a tree that cannot
|
||||
# start. nix-bundle-lgx shipped exactly that: `cp -a` implied
|
||||
# --no-dereference, the payload lost 75% of its files, and the step
|
||||
# exited 0. The count check below is why that cannot recur quietly.
|
||||
rm -rf "$dst" && mkdir "$dst"
|
||||
cp -rL "$src"/. "$dst/"
|
||||
chmod -R u+w "$dst"
|
||||
zip -qr "$dst.zip" "$dst"
|
||||
zipped=$(unzip -l "$dst.zip" | tail -1 | awk '{print $2}')
|
||||
echo "bundle $staged file(s) -> zip $zipped entr(ies)"
|
||||
if [ "$zipped" -lt "$staged" ]; then
|
||||
echo "::error::the zip holds $zipped entries but the bundle has $staged files."
|
||||
echo "::error::Something was not dereferenced; the extracted tree would be"
|
||||
echo "::error::missing DLLs and could not start."
|
||||
exit 1
|
||||
fi
|
||||
n_exe=$(find "$dst" -name '*.exe' | wc -l | tr -d ' ')
|
||||
[ "$n_exe" -gt 0 ] || { echo "::error::no .exe in the bundle"; exit 1; }
|
||||
echo "exe(s): $n_exe"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-${{ matrix.tool.bin }}-x86_64
|
||||
path: ${{ matrix.tool.bin }}-x86_64-windows.zip
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/')
|
||||
needs: [build-appimage, build-macos-bundle]
|
||||
needs: [build-appimage, build-macos-bundle, build-windows-bundle]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -201,5 +276,13 @@ jobs:
|
||||
```
|
||||
|
||||
Now `logoscore` runs from anywhere.
|
||||
# NOTE: `files:` below is a LITERAL block scalar -- every line in it is
|
||||
# a glob handed to the action, and a '#' line would be passed as a
|
||||
# pattern rather than ignored. Commentary belongs out here.
|
||||
#
|
||||
# The Windows bundles are .zip because Explorer opens one and nothing
|
||||
# on Windows opens a .tar.gz. `merge-multiple: true` above flattens
|
||||
# every artifact into artifacts/, so a depth-1 glob reaches them.
|
||||
files: |
|
||||
artifacts/*.tar.gz
|
||||
artifacts/*-windows.zip
|
||||
|
||||
Generated
+83371
-53351
File diff suppressed because it is too large
Load Diff
@@ -380,7 +380,7 @@
|
||||
# unset, every objdump call fails, and the hook reports "Created 0
|
||||
# DLL link(s)" -- a silent no-op that only shows up as an .exe that
|
||||
# will not start on the target machine.
|
||||
mkBinWindows = { binName }: pkgs.stdenv.mkDerivation {
|
||||
mkBinWindows = { binName, withPkgModules }: pkgs.stdenv.mkDerivation {
|
||||
pname = "${pname}-${binName}";
|
||||
inherit version meta;
|
||||
|
||||
@@ -393,8 +393,8 @@
|
||||
# a PE, in opposite directions:
|
||||
#
|
||||
# extraDirs: the bundler carries bin/ and lib/ and nothing else
|
||||
# unless a directory is named here. modules/ is the built-in
|
||||
# module tree this package stages by hand a few lines down; without
|
||||
# unless a directory is named here. modules/ (and modules-pkg/ for
|
||||
# logosctl) is the built-in module tree staged below; without
|
||||
# this line the bundle is a STRICT SUBSET of the derivation it
|
||||
# bundles -- no modules/, no message saying so, and a logosctl.exe
|
||||
# that starts and then reports no modules.
|
||||
@@ -410,7 +410,7 @@
|
||||
# the cost is an unused closure path and if it is necessary the
|
||||
# build says so instead of shipping an .exe that will not start.
|
||||
passthru = {
|
||||
extraDirs = [ "modules" ];
|
||||
extraDirs = [ "modules" ] ++ pkgs.lib.optional withPkgModules "modules-pkg";
|
||||
# qtbase + qtremoteobjects are what the CLI itself links. The
|
||||
# other two come from Qt PLUGINS that qtCliApp stages anyway:
|
||||
# `guiApp = false` suppresses the LAUNCHER, not the plugin scan,
|
||||
@@ -451,10 +451,10 @@
|
||||
|
||||
mkdir -p $out/bin $out/modules
|
||||
|
||||
exe="${build}/bin/${binName}${exeExt}"
|
||||
exe="${buildPortable}/bin/${binName}${exeExt}"
|
||||
if [ ! -f "$exe" ]; then
|
||||
echo "Error: $exe not found" >&2
|
||||
ls -la ${build}/bin >&2 || true
|
||||
ls -la ${buildPortable}/bin >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
cp "$exe" $out/bin/
|
||||
@@ -473,14 +473,14 @@
|
||||
# interpolated literal path survives into the array and the guard
|
||||
# passes vacuously.
|
||||
staged=0
|
||||
for dll in ${liblogosLib}/lib/*.dll; do
|
||||
for dll in ${liblogosPortable}/lib/*.dll; do
|
||||
[ -f "$dll" ] || continue
|
||||
cp -L "$dll" $out/bin/
|
||||
staged=$((staged + 1))
|
||||
done
|
||||
if [ "$staged" -eq 0 ]; then
|
||||
echo "Error: no DLLs under ${liblogosLib}/lib; ${binName}${exeExt} would start with no output" >&2
|
||||
ls -la ${liblogosLib}/lib >&2 || true
|
||||
echo "Error: no DLLs under ${liblogosPortable}/lib; ${binName}${exeExt} would start with no output" >&2
|
||||
ls -la ${liblogosPortable}/lib >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -489,27 +489,82 @@
|
||||
# script; there is no wrapper on a PE, so the host has to sit
|
||||
# beside the CLI where the default lookup finds it.
|
||||
hosts=0
|
||||
for host in ${liblogos}/bin/*.exe; do
|
||||
for host in ${liblogosPortable}/bin/*.exe; do
|
||||
[ -f "$host" ] || continue
|
||||
cp -L "$host" $out/bin/
|
||||
hosts=$((hosts + 1))
|
||||
done
|
||||
if [ "$hosts" -eq 0 ]; then
|
||||
echo "Error: no module-host .exe under ${liblogos}/bin" >&2
|
||||
ls -la ${liblogos}/bin >&2 || true
|
||||
echo "Error: no module-host .exe under ${liblogosPortable}/bin" >&2
|
||||
ls -la ${liblogosPortable}/bin >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
chmod -R +w $out/bin
|
||||
|
||||
# Built-in modules. ${liblogos}/modules already carries
|
||||
# capability_module with a windows-x86_64-dev manifest key (see
|
||||
# logos-liblogos/nix/modules.nix, which keys off the TARGET
|
||||
# platform rather than uname), so this is the same tree the
|
||||
# native builds get -- no lgx bundling involved.
|
||||
if [ -d ${liblogos}/modules ]; then
|
||||
cp -r ${liblogos}/modules/. $out/modules/
|
||||
chmod -R +w $out/modules
|
||||
# Built-in modules, from the SAME install-bundler path the native
|
||||
# builds use (installPortable -> nix-bundle-lgx), NOT a hand copy.
|
||||
#
|
||||
# This used to be `cp -r ''${liblogos}/modules/.`, and that is where
|
||||
# the first shipped Windows bundle got a capability_module whose
|
||||
# manifest named **Qt6Core.dll** as the plugin. Two Unix-shaped
|
||||
# assumptions in logos-liblogos/nix/modules.nix combine: it globs
|
||||
# `lib/*.dll` -- which matches only the plugin on Unix, but on
|
||||
# Windows linkDLLsInfolder has staged 14 dependency DLLs beside it
|
||||
# -- and then picks the entry point by taking the FIRST file in
|
||||
# the directory, alphabetically Qt6Core.dll. Neither is visible
|
||||
# natively, and the build succeeded either way.
|
||||
#
|
||||
# Going through the bundler fixes both at once and is what
|
||||
# logos-basecamp already does (binBundleDir = dirBundler
|
||||
# appDistributed -> installPortable): the manifest comes from the
|
||||
# module's own metadata rather than a directory listing, and
|
||||
# nix-bundle-lgx's mkWindowsPayload strips the host-provided
|
||||
# runtime DLLs that bin/ already ships.
|
||||
modcount=0
|
||||
for m in ${modulesPortable}/modules/*; do
|
||||
[ -d "$m" ] || continue
|
||||
cp -r "$m" $out/modules/
|
||||
modcount=$((modcount + 1))
|
||||
done
|
||||
if [ "$modcount" -eq 0 ]; then
|
||||
echo "Error: no modules under ${modulesPortable}/modules" >&2
|
||||
ls -laR ${modulesPortable} >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
${pkgs.lib.optionalString withPkgModules ''
|
||||
mkdir -p $out/modules-pkg
|
||||
pkgcount=0
|
||||
for m in ${modulesPortable}/modules-pkg/*; do
|
||||
[ -d "$m" ] || continue
|
||||
cp -r "$m" $out/modules-pkg/
|
||||
pkgcount=$((pkgcount + 1))
|
||||
done
|
||||
if [ "$pkgcount" -eq 0 ]; then
|
||||
echo "Error: no modules under ${modulesPortable}/modules-pkg;" >&2
|
||||
echo " ${binName}${exeExt} would start with no package backend" >&2
|
||||
exit 1
|
||||
fi
|
||||
''}
|
||||
chmod -R +w $out/modules ${pkgs.lib.optionalString withPkgModules "$out/modules-pkg"}
|
||||
|
||||
# Guard the defect class the change above removes: a manifest
|
||||
# whose "main" names something that is not that module's plugin.
|
||||
# The convention is modules/<name>/<name>_plugin.<ext>, so any
|
||||
# other value is wrong by construction. This fails the BUILD
|
||||
# rather than shipping a bundle that starts and then cannot load
|
||||
# -- which is exactly what happened, because every structural
|
||||
# check (file counts, PE counts, zip entries) passed on it.
|
||||
for man in $out/modules/*/manifest.json ${pkgs.lib.optionalString withPkgModules "$out/modules-pkg/*/manifest.json"}; do
|
||||
[ -f "$man" ] || continue
|
||||
mod=$(basename "$(dirname "$man")")
|
||||
bad=$(${pkgs.buildPackages.jq}/bin/jq -r '.main | if type=="object" then to_entries[].value else . end' "$man" \
|
||||
| sort -u | grep -v "^''${mod}_plugin\." || true)
|
||||
if [ -n "$bad" ]; then
|
||||
echo "Error: $man declares an entry point that is not $mod's plugin:" >&2
|
||||
echo "$bad" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
@@ -639,8 +694,12 @@
|
||||
pkgs.cmake
|
||||
pkgs.ninja
|
||||
pkgs.pkg-config
|
||||
pkgs.qt6.wrapQtAppsNoGuiHook
|
||||
];
|
||||
]
|
||||
# Same two-part guard as `build`: the Qt wrapper hooks cannot even
|
||||
# evaluate for a mingw host and would skip a PE anyway, and dropping
|
||||
# the hook alone makes qtbase's setup hook error with "depends on
|
||||
# qtbase, but no wrapping behavior was specified".
|
||||
++ pkgs.lib.optional (!isWindows) pkgs.qt6.wrapQtAppsNoGuiHook;
|
||||
|
||||
buildInputs = [
|
||||
# cppSdk propagates Boost, OpenSSL, nlohmann_json (but
|
||||
@@ -659,7 +718,7 @@
|
||||
pkgs.spdlog
|
||||
];
|
||||
|
||||
cmakeFlags = [
|
||||
cmakeFlags = (pkgs.logosQtCrossCmakeFlags or [ ]) ++ [
|
||||
"-GNinja"
|
||||
"-DLOGOS_LIBLOGOS_ROOT=${liblogosPortable}"
|
||||
"-DLOGOS_CPP_SDK_ROOT=${cppSdk}"
|
||||
@@ -733,65 +792,68 @@
|
||||
logoscoreCli = pkgs.symlinkJoin { name = pname; paths = [ binLegacy ]; };
|
||||
logosctlCli = pkgs.symlinkJoin { name = "${pname}-ctl"; paths = [ binCtl ]; };
|
||||
|
||||
binLegacyWin = mkBinWindows { binName = "logoscore"; };
|
||||
binCtlWin = mkBinWindows { binName = "logosctl"; };
|
||||
binLegacyWin = mkBinWindows { binName = "logoscore"; withPkgModules = false; };
|
||||
binCtlWin = mkBinWindows { binName = "logosctl"; withPkgModules = true; };
|
||||
in
|
||||
if isWindows then {
|
||||
# Windows ships the two binaries plus a bundled directory for each.
|
||||
#
|
||||
# STILL LEFT OUT, and why. Each reason below was re-checked by eval
|
||||
# against the revs this flake locks, because the list this replaces
|
||||
# had two entries whose stated reason had expired:
|
||||
# against the revs this flake locks.
|
||||
#
|
||||
# * modules-pkg/ (package_manager + package_downloader), so
|
||||
# `logosctl package ...` still has no backend on Windows.
|
||||
# ONE blocker, not the four the old comment implied. Measured:
|
||||
# - logos-package-manager-module packages.x86_64-windows.lib
|
||||
# and .lib-portable -- PRESENT
|
||||
# - logos-capability-module packages.x86_64-windows.lib
|
||||
# -- PRESENT
|
||||
# - nix-bundle-logos-module-install
|
||||
# bundlers.x86_64-windows.{dev,portable} -- PRESENT (it
|
||||
# takes lgpm from the BUILD system and passes
|
||||
# `--platform windows-x86_64`, so the cross case is handled)
|
||||
# - logos-package-downloader-module
|
||||
# packages.x86_64-windows -- ABSENT
|
||||
# Root cause of the one that is missing, and it is not in that
|
||||
# repo's own sources: logos-module-builder gates the
|
||||
# x86_64-windows target on its `logos-nix` input, and
|
||||
# package-downloader-module still pins module-builder 8e4ea1c,
|
||||
# whose lib/common.nix does not mention x86_64-windows at all.
|
||||
# package-manager-module and capability-module pin 9d3b7cc, which
|
||||
# does. So the fix is a pin bump in THAT repo, followed by a
|
||||
# re-lock here.
|
||||
# modules-pkg/ USED TO BE LISTED HERE and no longer is: package_manager
|
||||
# and package_downloader now ship on Windows. The blocker was real but
|
||||
# cleared upstream -- logos-package-downloader-module gained
|
||||
# packages.x86_64-windows when it bumped logos-module-builder
|
||||
# 8e4ea1c -> 9d3b7cc (that file's systems list is a hardcoded 4-element
|
||||
# array with no x86_64-windows at the older rev). This flake was simply
|
||||
# 3 commits behind; a single-input re-lock was the whole fix.
|
||||
#
|
||||
# Why not ship the half that exists. Shipping package_manager
|
||||
# alone would be worse than shipping neither, not merely
|
||||
# incomplete: src/daemon/daemon.cpp:241 loads the two names in a
|
||||
# loop and `return`s on the first failure -- BEFORE the
|
||||
# setEmbeddedModulesDirectory / setUserModulesDirectory /
|
||||
# setKeyringDirectory calls below it. package_manager would come
|
||||
# up loaded but unconfigured, and installs would land wherever its
|
||||
# unset defaults point, after one warning on stderr.
|
||||
# Two things the old entry got WRONG, recorded because both were
|
||||
# believed and acted on:
|
||||
#
|
||||
# What package_downloader's arrival does NOT settle: that the
|
||||
# daemon LOADS either module on Windows (never run anywhere), and
|
||||
# the size of what it installs -- the modules-pkg path goes
|
||||
# through .lgx, which has no host-runtime strip on the PE path
|
||||
# yet, so both packages would carry their own copy of the Qt,
|
||||
# OpenSSL and libstdc++ DLLs that sit beside logosctl.exe already.
|
||||
# * Its stated consequence of shipping package_manager alone --
|
||||
# "installs would land wherever its unset defaults point" -- is
|
||||
# FALSE. Every one of those directories fails closed when unset.
|
||||
# The real hazard is narrower and worse: a configured
|
||||
# `signature_policy: require` is read and then silently DISARMED
|
||||
# in the half-configured state.
|
||||
#
|
||||
# * It framed daemon.cpp's first-failure `return` as a reason not to
|
||||
# ship half. It is not a Windows fact at all -- the same early
|
||||
# return leaves the daemon half-configured on every platform, and
|
||||
# because package_manager is first in the list, its failure means
|
||||
# package_downloader is never attempted even when it would load.
|
||||
# That is a product defect with its own fix, not a packaging
|
||||
# constraint, and it is tracked separately.
|
||||
#
|
||||
# * *-appimage. An AppImage is a Linux ELF runtime concatenated with
|
||||
# a squashfs image; there is no Windows analogue. Confirmed rather
|
||||
# than assumed: nix-bundle-appimage exposes `lib` for
|
||||
# aarch64-linux and x86_64-linux only. Do not force this one.
|
||||
#
|
||||
# * portable. Not blocked -- redundant. mkBinWindows IS the portable
|
||||
# shape: win-dll-link.sh stages every dependency beside the .exe
|
||||
# because a PE import table carries base names and no rpath, so
|
||||
# there is no @rpath/$ORIGIN variant for a `portable` output to
|
||||
# differ from. This is the one entry the old comment got right,
|
||||
# though it gave the reason under the wrong heading.
|
||||
# * portable. NO LONGER LEFT OUT, and the reason it was is worth
|
||||
# keeping because it was wrong in an instructive way. The old
|
||||
# entry argued portable was "redundant" on Windows: a PE import
|
||||
# table carries base names and no rpath, win-dll-link.sh stages
|
||||
# every dependency beside the .exe, so there is no @rpath/$ORIGIN
|
||||
# variant for a portable output to differ from.
|
||||
#
|
||||
# All of that is true and none of it is the whole story. `portable`
|
||||
# is not only a LAYOUT distinction -- it is a compile-time one.
|
||||
# LGPM_PORTABLE_BUILD (logos-package-manager/CMakeLists.txt:58)
|
||||
# decides what platformVariantsToTry() returns: without it, the
|
||||
# binary appends "-dev" and accepts ONLY dev variants
|
||||
# (package_manager_lib.cpp:1005-1008). So a dev-built logosctl.exe
|
||||
# beside modules installed as `windows-x86_64` refuses all three
|
||||
# with "installed for variant 'windows-x86_64' which is not
|
||||
# supported on this platform". mkBinWindows therefore builds from
|
||||
# buildPortable/liblogosPortable, matching the installPortable
|
||||
# modules it stages.
|
||||
#
|
||||
# buildPortable needed two Windows fixes to be usable here, both
|
||||
# of which `build` already had: the Qt host-tool cmakeFlags, and
|
||||
# the !isWindows guard on wrapQtAppsNoGuiHook.
|
||||
#
|
||||
# * tests. Verified here rather than inherited from the old comment.
|
||||
# CMakeLists.txt:277 skips the whole test block under WIN32, and
|
||||
|
||||
Reference in New Issue
Block a user