Add Linux x64 support (net8.0)#2
Merged
Merged
Conversation
Add cross-platform native build and packaging so the bindings run on
Linux x64 alongside the existing Windows x64 support, without changing
the target framework (stays net8.0).
Native build & CI
- build/native-linux.sh: compile the CycloneDDS submodule + idlc on
Linux, stage libddsc/libcycloneddsidl* .so and idlc into
artifacts/native/linux-x64, and rewrite RPATH to $ORIGIN via patchelf
so the flat NuGet tools/ layout resolves its .so dependencies.
- CI: add a linux-build job that builds the native libs, then builds the
managed solution (exercising build-time idlc codegen on Linux) and runs
the runtime tests; the Windows job downloads the linux-x64 native
artifacts and packs a cross-platform NuGet via the existing pack.ps1.
- .gitignore: ignore build/native-linux/.
Cross-platform code generator
- IdlcRunner.FindIdlc/RunIdlc are now platform-aware: try idlc/idlc.exe
and the win-x64/linux-x64 RID folders, set LD_LIBRARY_PATH to the idlc
directory on Linux, and restore the Unix execute bit (NuGet does not
preserve it) before launching idlc.
Packaging & project files
- Runtime.csproj: ship libddsc.so under runtimes/linux-x64/native and
idlc + its .so deps under tools/ (Exists-guarded so a Windows-only pack
still succeeds); update the package description.
- Core.csproj and the native-consuming test projects + FeatureDemo:
OS-guard the win-x64 native copy and add a linux-x64 copy via
MSBuild IsOSPlatform conditions.
Tests
- ErrorHandlingTests: resolve the idlc path by RID/OS at runtime.
- IdlcRunnerTests: use the platform idlc name and skip the Windows
batch-file plumbing test on non-Windows.
Native fork must be built from the pjanec/cyclonedds submodule; DllImport
("ddsc") resolves to libddsc.so on Linux with no source change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
Found by building and running the full test suite on Linux with the .NET SDK (net8.0 target, .NET 10 SDK toolchain). Case-sensitive project references - Four ProjectReference paths used "..\..\Src\..." (capital S). Windows' case-insensitive filesystem hid this; on Linux the references failed and CycloneDDS.CodeGen/Schema.Tests could not resolve their dependencies. Corrected to lowercase "src". Listener callback ABI (the real fix) - DdsOnPublicationMatched / DdsOnSubscriptionMatched passed the 24-byte status struct by `ref`. That matches the Windows x64 ABI (>16-byte structs passed by implicit pointer) but not the Linux System V ABI (passed by value on the stack), which shifted `arg` into the wrong register — GCHandle.FromIntPtr then threw and the callback was silently dropped. As a result PublicationMatched/SubscriptionMatched events and WaitForReaderAsync never fired on Linux. Declaring the status by value lets the .NET marshaller emit the correct per-platform ABI; the matching handler signatures in DdsWriter/DdsReader are updated to match. CI toolchain - The code uses C# 13 features (ref structs in async methods) that require the .NET 10 SDK compiler, so CI now installs both the 8.0 and 10.0 SDKs (10.0 builds, 8.0 runs the net8.0 tests) instead of pinning 8.0.x. Cleanup - Guard the idlc chmod with OperatingSystem.IsWindows() to silence CA1416. Verified on Linux: native build, full managed build, and tests all green — Runtime 145/1 skip, CodeGen 199, Core 19, Schema 12, IdlImporter 28, Compiler.Common 8. The two FeatureDemo example-test failures are pre-existing and environmental (Spectre.Console needs a TTY; the StockPublisher timing test the upstream author already ignores in CI) and are not run by the pack/CI pipeline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
Adding a new supported platform (Linux x64) is a feature, and the listener-callback ABI fix changes a public interop delegate signature, so under SemVer (pre-1.0) this is a minor bump. Nerdbank.GitVersioning derives the patch component from git height automatically. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
Matches the Nerdbank.GitVersioning output on main after a squash merge (single 0.3 commit -> git height 1 -> 0.3.1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
The DdsMonitor tool bundled its native ddsc library only via the transitive
Content copy from CycloneDDS.Core, which is OS-guarded — so a tool packed on
Windows (as CI does) carried only ddsc.dll and threw DllNotFoundException when
installed on Linux (and vice-versa).
Bundle BOTH platforms' runtime native into the tool payload: the transitive
copy still provides the pack host's native, and new Exists/OS-guarded Content
items add the other platform's (linux-x64 libddsc.so when packing on Windows,
win-x64 ddsc.dll when packing on Linux). Native libs sit flat in the tool's
app-base dir, so DllImport("ddsc") resolves the right file per OS. Pack="false"
keeps them in the tool payload (via CopyToOutputDirectory) without duplicating
them into content/ and contentFiles/.
Verified by packing on Linux with a win-x64 stub: the tool payload contains
both tools/net8.0/any/ddsc.dll and tools/net8.0/any/libddsc.so(.0), and a normal
Linux build (no other-platform native present) is unaffected. IdlImporter was
already cross-platform via the package's tools/ idlc; confirmed by importing IDL
to C# end-to-end on Linux.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
The ddsmonitor global tool gained a new supported platform (Linux) — a feature — so bump its independent version line (tools/DdsMonitor/version.json) from 1.0 to 1.1. Nerdbank.GitVersioning derives the patch from git height, so after a squash merge to main the tool publishes as 1.1.1 (the main CycloneDDS.NET package remains 0.3.1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
- Installation: note native assets ship for both Windows x64 and Linux x64, and add a Supported platforms table (VC++ redist on Windows; glibc on Linux). - Build from source: add the Linux native build path (build/native-linux.sh) alongside native-win.ps1, and a cross-platform build/test snippet. - Requirements: clarify the target is net8.0 but building needs the .NET 10 SDK (C# 13 features), plus the Linux toolchain (cmake/build-essential/patchelf). - Dependencies: list the Linux native asset names next to the Windows ones. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds cross-platform native build & packaging so the bindings run on Linux x64 alongside Windows x64, keeping
net8.0as the target framework. Inspired by the earlier (closed) PR #1, but decoupled from that PR'snet8.0 → net10.0bump and verified end-to-end on Linux.What's included
Linux native build & packaging
build/native-linux.sh— compiles the CycloneDDS submodule +idlc, stageslibddsc/libcycloneddsidl*.soandidlcintoartifacts/native/linux-x64/, and rewrites RPATH to$ORIGIN(viapatchelf) so the flat NuGettools/layout resolves its.sodependencies.CycloneDDS.Runtime.csprojpackslibddsc.sounderruntimes/linux-x64/nativeandidlc+.sodeps undertools/(Exists-guarded so a Windows-only local pack still succeeds).Core.csprojand the native-consuming test/example projects OS-guard the native-asset copy viaIsOSPlatform.[DllImport("ddsc")]resolves tolibddsc.soautomatically.Cross-platform code generator
IdlcRunneris now platform-aware: locatesidlc/idlc.exeunder the correct RID, setsLD_LIBRARY_PATH, and restores the Unix execute bit NuGet drops.Bugs found by actually building/testing on Linux
ref, which matches the Windows x64 ABI but not Linux System V (>16-byte structs passed by value on the stack) —argwas read from the wrong register,GCHandle.FromIntPtrthrew, and the callback was silently swallowed. Now passed by value so the marshaller emits the correct ABI on both platforms.PublicationMatched/SubscriptionMatched/WaitForReaderAsyncnow work on Linux...\..\Src\project references that only resolved on case-insensitive (Windows) filesystems — corrected tosrc.CI
linux-buildjob builds the native libs, thendotnet builds the solution (exercising Linuxidlccodegen) and runs the runtime tests; the Windows job runs the existingpack.ps1after downloading the Linux native artifacts to produce a single cross-platform package.net8.0.Versioning
version.jsonminor to0.3(new platform + a public interop signature change). Nerdbank.GitVersioning derives the patch from git height.Verified on Linux (net8.0)
Native build ✅, full managed build ✅ (0 errors), tests: Runtime 145 pass / 1 pre-existing skip, CodeGen 199, Core 19, Schema 12, IdlImporter 28, Compiler.Common 8 — all green. NuGet pack produces
runtimes/linux-x64/native/libddsc.so+tools/idlcalongside the win-x64 assets.The two FeatureDemo example-test failures are pre-existing and environmental (Spectre.Console needs a TTY; the
StockPublishertiming test the upstream author already ignores in CI) and are not run by the pack/CI pipeline.🤖 Generated with Claude Code
https://claude.ai/code/session_01N7RoW2a2tBB2T8tDbNHB11
Generated by Claude Code