Skip to content

ci(cpp): cross-compile matrix + static binary packaging for C++ agents (#1094)#1406

Merged
kovtcharov-amd merged 2 commits into
mainfrom
claudia/task-dd5c5c4a
Jun 4, 2026
Merged

ci(cpp): cross-compile matrix + static binary packaging for C++ agents (#1094)#1406
kovtcharov-amd merged 2 commits into
mainfrom
claudia/task-dd5c5c4a

Conversation

@kovtcharov-amd

Copy link
Copy Markdown
Collaborator

Why this matters

Before: the C++ agents in cpp/ (health, wifi, process, vlm, security-demo) had no distribution path — build_cpp.yml only compiled and tested the library, so there was no self-contained binary anyone could download and run, and no dist/ artifact for the Agent Hub to publish. After: every agent is built as a static, cross-platform binary (no runtime DLL/.so dependency) and packaged with its gaia-agent.yaml + checksum, on Windows, Linux, and macOS. This is the packaging half of Agent Hub Phase 2B (issue #1094).

build_agents.yml adds the cross-compile matrix — win-x64 (MSVC), linux-x64 (GCC), darwin-arm64 (Clang) — building with BUILD_SHARED_LIBS=OFF, vcpkg *-static triplets, and the static MSVC runtime. cpp/packaging/package_agents.py then emits dist/<id>/ with the renamed binary, the agent's manifest, and checksums.sha256. On a v* tag a release job consolidates all platforms into one bundle; actual R2/PyPI publishing is handled by other Agent Hub issues.

Windows-only agents (health/wifi/process) build on the win-x64 leg only; security-demo and vlm are portable and prove the Linux/macOS legs. Manifests validate against the gaia-agent.yaml parser from #1091.

Isolated from the #1102 Python restructure — touches only .github/workflows/, cpp/, and a packaging script. No src/gaia/ changes.

Spec: docs/spec/agent-hub-restructure.mdx (Step 9 — CI/CD; cpp.binaries/static_linked).

Test plan

  • python -c "import yaml; yaml.safe_load(open('.github/workflows/build_agents.yml'))" — workflow is valid YAML
  • All five cpp/agents/*/gaia-agent.yaml parse via gaia.hub.manifest.parse (cpp, static_linked, correct platforms)
  • package_agents.py smoke-tested with synthetic build trees for win-x64 (5 agents) and linux-x64 (2 agents): correct dist/<id>/ layout, stale Debug copies skipped, checksums written, fails loudly on missing binary
  • release-bundle merge logic tested locally — preserves all platforms' binaries per agent and regenerates complete checksums (no per-leg collision)
  • python util/lint.py --black --isort passes
  • CI matrix green on all three legs (relies on the runners — no local C++ toolchain available to smoke-build)

#1094)

C++ agents had no cross-platform binary distribution path: the existing
build_cpp.yml only compiled and tested the library, leaving the example
agents (health, wifi, process, vlm, security-demo) with no shippable,
self-contained artifact. This adds the packaging half of Agent Hub Phase 2B.

build_agents.yml builds each agent with static linking (BUILD_SHARED_LIBS=OFF,
vcpkg *-static triplets, static MSVC runtime) across win-x64 (MSVC),
linux-x64 (GCC), and darwin-arm64 (Clang), so the binaries carry no runtime
DLL/.so dependency. package_agents.py then emits dist/<id>/ with the renamed
binary, its gaia-agent.yaml, and checksums.sha256; on a v* tag a release job
consolidates every platform into one bundle for downstream publishing
(R2/PyPI live in other issues).

Isolated from the #1102 Python restructure — touches only cpp/ and CI.
@github-actions github-actions Bot added devops DevOps/infrastructure changes cpp labels Jun 4, 2026
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Clean, well-scoped packaging PR — it gives the cpp/ agents an actual distribution path (static cross-platform binaries + gaia-agent.yaml + checksums) without touching src/gaia/. The pieces line up: the five manifests parse against the gaia.hub.manifest schema (valid language: cpp, cpp.binaries, permission domains, platform triples), TARGET_BY_ID matches the real CMake targets, and the Windows-only agents are correctly gated to the win-x64 leg both in the manifests and in cpp/CMakeLists.txt (GAIA_BUILD_EXAMPLES AND WIN32). The packaging script follows GAIA's fail-loudly rule properly — manifest/binary-name mismatches and missing binaries raise actionable PackagingErrors rather than silently skipping.

The one thing worth addressing: package_agents.py ships with real, edge-case-heavy logic (name-mismatch detection, stale-Debug skipping, fail-on-missing-binary) but no committed tests, despite the test plan describing exactly those scenarios being smoke-tested by hand.

Issues Found

🟡 Important

No unit tests for package_agents.py (cpp/packaging/package_agents.py)
The test plan says the script was smoke-tested with synthetic build trees (win-x64 5 agents, linux-x64 2 agents, stale-Debug skip, fail-on-missing) — that's precisely the behavior CLAUDE.md wants locked into tests/. The logic is pure Python and trivially unit-testable: point package_agent at a tmp dir with a fake binary + manifest and assert the dist/<id>/ layout, the checksum line, the PackagingError on a binaries/derived-name mismatch, and that _find_binary picks the newest mtime. A small tests/unit/test_package_agents.py would prevent a silent packaging regression from reaching the Hub. Not strictly blocking for a CI-only helper that was manually verified, but it's the highest-value follow-up here.

🟢 Minor

static_linked: true overstates macOS reality (cpp/agents/{security-demo,vlm}/gaia-agent.yaml)
Apple doesn't support fully static binaries — the arm64-osx-static triplet statically links third-party deps (OpenSSL) and BUILD_SHARED_LIBS=OFF drops the dylib, but the binary still dynamically links libSystem. The flag reads as "zero dynamic deps," which is true on Windows/Linux but not darwin. Worth a one-line note in the manifest comment or cpp/agents/README.md so a downstream consumer doesn't assume a fully static Mach-O.

vcpkg cache key tracks the wrong file (.github/workflows/build_agents.yml:91)
The install step runs classic-mode vcpkg install openssl:<triplet> with VCPKG_MANIFEST_MODE=OFF, so cpp/vcpkg.json doesn't drive what's installed — yet the cache key is hashFiles('cpp/vcpkg.json'). Harmless (cache still works), just keyed on a file the install doesn't read. Keying on the workflow file itself, or a literal version bump, would be more honest.

Strengths

  • Genuinely isolated — only .github/workflows/, cpp/, and the packaging script; the claim of no src/gaia/ blast radius holds, and the manifests are verified against the existing #1091 parser rather than inventing a schema.
  • Fail-loudly done right — every skip is either an intentional "agent doesn't target this platform → return None" or an actionable raise; yaml.safe_load, if-no-files-found: error, and the explicit VCPKG_INSTALLATION_ROOT guard all match GAIA conventions.
  • The release-bundle checksum-collision handling is careful — dropping the colliding per-leg checksums.sha256 and regenerating complete per-agent + aggregate checksums from the merged binaries is the right call, and it's commented well enough to survive future edits.

Verdict

Approve with suggestions. No blocking or security issues; the build/packaging wiring is consistent with the manifest schema and CMake targets. I'd like to see tests/unit/test_package_agents.py land (ideally in this PR, otherwise as an immediate follow-up) to satisfy GAIA's testing requirement for the new logic; the two minor notes are optional polish.

The runners' vcpkg has no built-in x64-linux-static or arm64-osx-static
triplet (only Windows ships *-static variants), so the Linux and macOS
Package legs failed at the vcpkg install step with 'Invalid triplet'.
Provide them as overlay triplets in cpp/triplets/ and pass
--overlay-triplets / VCPKG_OVERLAY_TRIPLETS so the names resolve on every
platform. Windows keeps using its built-in x64-windows-static (already green).
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

🟡 build_agents.yml:153/170upload-artifact@v7 + download-artifact@v8 version mismatch will break the release job on a tag push.

The build job uploads with actions/upload-artifact@v7, but release-bundle downloads with actions/download-artifact@v8. These two actions use a shared artifact format; mixing major versions is unsupported and will cause the download step to fail (or silently produce an empty bundle). They must be pinned to the same major version.

        uses: actions/download-artifact@v7

(or bump both to v8 — whichever versions actually exist on the runners.)

@kovtcharov-amd

Copy link
Copy Markdown
Collaborator Author

CI status after the overlay-triplet fix

All three Package legs are green on the latest run, and artifacts upload on every platform:

Platform Result Agents packaged Artifact
win-x64 health, wifi, process, security-demo, vlm 10.2 MB
linux-x64 security-demo, vlm 3.5 MB
darwin-arm64 security-demo, vlm 3.1 MB

Root cause of the earlier linux/macOS failures: the runners' vcpkg has no built-in x64-linux-static / arm64-osx-static triplet (only Windows ships -static variants), so vcpkg install failed with Invalid triplet. Fixed by adding overlay triplets in cpp/triplets/ and passing --overlay-triplets / VCPKG_OVERLAY_TRIPLETS. Windows keeps its built-in x64-windows-static.

On C++ Integration Tests (STX): unrelated to this PR. It fails in the "Start Lemonade Server and run integration tests" runtime step (self-hosted STX hardware + Lemonade), not the build — the C++ (ubuntu-latest) and C++ (windows-latest) build jobs in that same workflow pass with the CMakeLists change here, and build_cpp.yml is independently flaky on main. That workflow already treats STX integration as non-blocking (warn-only). No change needed from this PR.

@kovtcharov-amd kovtcharov-amd merged commit 0993838 into main Jun 4, 2026
37 of 38 checks passed
@kovtcharov-amd kovtcharov-amd deleted the claudia/task-dd5c5c4a branch June 4, 2026 05:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cpp devops DevOps/infrastructure changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant