diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3b066dd..3c88042 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,32 +9,99 @@ on:
workflow_dispatch:
jobs:
- build:
+ # ── Windows: full build, test, and managed code compilation ──────────
+ windows-build:
runs-on: windows-latest
-
env:
- # This ensures the build script can find CMake if not in default path (though it usually is on runners)
- CMAKE_GENERATOR: "Visual Studio 17 2022"
-
+ CMAKE_GENERATOR: "Visual Studio 18 2026"
steps:
- uses: actions/checkout@v3
with:
- fetch-depth: 0 # Required for Nerdbank.GitVersioning to determine version
+ fetch-depth: 0
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: 8.0.x
+ dotnet-version: 10.0.x
- name: Display Tools Versions
run: |
dotnet --version
cmake --version
- - name: Build, Test, and Pack
+ - name: Build Native (win-x64)
+ shell: pwsh
+ run: .\build\native-win.ps1
+
+ - name: Build Managed Code
+ shell: pwsh
+ run: dotnet build CycloneDDS.NET.Core.slnf -c Release
+
+ - name: Run Tests
+ shell: pwsh
+ run: dotnet test CycloneDDS.NET.Core.slnf -c Release --no-build --verbosity normal
+
+ - name: Upload win-x64 Native Artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: native-win-x64
+ path: artifacts/native/win-x64/*
+
+ # ── Linux: native compilation only ───────────────────────────────────
+ linux-build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ submodules: recursive
+
+ - name: Build Native (linux-x64)
+ shell: bash
+ run: |
+ chmod +x build/native-linux.sh
+ build/native-linux.sh Release
+
+ - name: Upload linux-x64 Native Artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: native-linux-x64
+ path: artifacts/native/linux-x64/*
+
+ # ── Pack: combine native artifacts and create NuGet package ──────────
+ pack:
+ runs-on: windows-latest
+ needs: [windows-build, linux-build]
+
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ submodules: recursive
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: 10.0.x
+
+ - name: Download win-x64 Native Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: native-win-x64
+ path: artifacts/native/win-x64/
+
+ - name: Download linux-x64 Native Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: native-linux-x64
+ path: artifacts/native/linux-x64/
+
+ - name: Build and Pack
shell: pwsh
- run: .\build\pack.ps1
+ run: |
+ dotnet build CycloneDDS.NET.Core.slnf -c Release
+ dotnet pack src/CycloneDDS.Runtime/CycloneDDS.Runtime.csproj -c Release --no-build -o artifacts/nuget
- name: Upload NuGet Packages
uses: actions/upload-artifact@v4
@@ -50,4 +117,4 @@ jobs:
with:
name: symbol-packages
path: artifacts/nuget/*.snupkg
- if-no-files-found: warn
+ if-no-files-found: warn
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 738e33f..ebc21e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ nunit-*.xml
cyclone-compiled/
cyclone-compiled-debug/
build/native/
+build/native-linux/
test-extract/
test-output/
**/Generated/*
diff --git a/Directory.Build.props b/Directory.Build.props
index c5f4167..74e32f0 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -21,7 +21,7 @@
-
-
+
+
diff --git a/build/native-linux.sh b/build/native-linux.sh
new file mode 100644
index 0000000..3dee53f
--- /dev/null
+++ b/build/native-linux.sh
@@ -0,0 +1,116 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# ===================================================================================
+# build/native-linux.sh
+#
+# PURPOSE:
+# Compiles the native (C/C++) Cyclone DDS submodule for Linux and copies the
+# resulting binaries to the local 'artifacts' directory.
+# This is a prerequisite for packing the NuGet package with linux-x64 support.
+#
+# USAGE:
+# ./build/native-linux.sh [Release|Debug]
+# Default: Release
+# ===================================================================================
+
+CONFIG="${1:-Release}"
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+REPO_ROOT="$(dirname "$SCRIPT_DIR")"
+SOURCE_DIR="$REPO_ROOT/cyclonedds"
+BUILD_DIR="$REPO_ROOT/build/native-linux"
+INSTALL_DIR="$REPO_ROOT/artifacts/native-install"
+ARTIFACTS_DIR="$REPO_ROOT/artifacts/native/linux-x64"
+
+echo "============================================================"
+echo " Building Native CycloneDDS for Linux ($CONFIG)"
+echo "============================================================"
+
+# Check prerequisites
+if ! command -v cmake &> /dev/null; then
+ echo "ERROR: cmake is not installed or not in PATH." >&2
+ exit 1
+fi
+
+if ! command -v gcc &> /dev/null; then
+ echo "ERROR: gcc is not installed or not in PATH." >&2
+ exit 1
+fi
+
+if [ ! -d "$SOURCE_DIR" ]; then
+ echo "ERROR: Native source directory not found: $SOURCE_DIR" >&2
+ echo " Run: git submodule update --init --recursive" >&2
+ exit 1
+fi
+
+# Ensure output directories exist
+mkdir -p "$BUILD_DIR" "$INSTALL_DIR" "$ARTIFACTS_DIR"
+
+# ----------------------------------------------------------------
+# [1/3] CMake Configure
+# ----------------------------------------------------------------
+echo ""
+echo "[1/3] Configuring CMake..."
+
+cmake -S "$SOURCE_DIR" -B "$BUILD_DIR" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \
+ -DBUILD_IDLC=ON \
+ -DBUILD_TESTING=OFF \
+ -DBUILD_EXAMPLES=OFF \
+ -DENABLE_SSL=OFF \
+ -DENABLE_SHM=OFF \
+ -DENABLE_SECURITY=OFF \
+ -DCMAKE_BUILD_TYPE="$CONFIG"
+
+# ----------------------------------------------------------------
+# [2/3] Build & Install
+# ----------------------------------------------------------------
+echo ""
+echo "[2/3] Building & Installing..."
+
+NPROC="${NPROC:-$(nproc 2>/dev/null || echo 4)}"
+cmake --build "$BUILD_DIR" --config "$CONFIG" -j "$NPROC"
+cmake --install "$BUILD_DIR" --config "$CONFIG"
+
+# ----------------------------------------------------------------
+# [3/3] Copy Artifacts & Fix RPATH
+# ----------------------------------------------------------------
+echo ""
+echo "[3/3] Copying artifacts to $ARTIFACTS_DIR..."
+
+# Runtime library (include both .so.0 for soname and .so for convention)
+cp -f "$INSTALL_DIR/lib/libddsc.so.0.11.0" "$ARTIFACTS_DIR/libddsc.so.0" 2>/dev/null || echo " [-] Missing libddsc.so.0.11.0"
+cp -f "$INSTALL_DIR/lib/libddsc.so.0.11.0" "$ARTIFACTS_DIR/libddsc.so" 2>/dev/null || true
+echo " [+] libddsc.so / libddsc.so.0"
+
+# IDL compiler executable
+cp -f "$INSTALL_DIR/bin/idlc" "$ARTIFACTS_DIR/" 2>/dev/null || echo " [-] Missing idlc"
+echo " [+] idlc"
+
+# IDL compiler support libraries
+for lib in libcycloneddsidl libcycloneddsidlc libcycloneddsidljson; do
+ cp -f "$INSTALL_DIR/lib/${lib}.so.0.11.0" "$ARTIFACTS_DIR/${lib}.so.0" 2>/dev/null || echo " [-] Missing ${lib}.so.0.11.0"
+ cp -f "$INSTALL_DIR/lib/${lib}.so.0.11.0" "$ARTIFACTS_DIR/${lib}.so" 2>/dev/null || true
+ echo " [+] ${lib}.so / ${lib}.so.0"
+done
+
+# Fix RPATH: cmake sets RPATH to $ORIGIN/../lib (bin/ -> lib/), but in the
+# NuGet tools/ directory all files are flat. Change RPATH to $ORIGIN/ so the
+# dynamic linker finds .so dependencies alongside the executable.
+if command -v patchelf &> /dev/null; then
+ echo ""
+ echo " [+] Fixing RPATH to \$ORIGIN/..."
+ chmod +w "$ARTIFACTS_DIR/"*.so* "$ARTIFACTS_DIR/idlc" 2>/dev/null || true
+ for f in "$ARTIFACTS_DIR/"*.so* "$ARTIFACTS_DIR/idlc"; do
+ patchelf --set-rpath '$ORIGIN/' "$f" 2>/dev/null || true
+ done
+ echo " [+] RPATH fixed."
+else
+ echo " [!] patchelf not found. Run: sudo apt-get install patchelf"
+ echo " [!] Without patchelf, LD_LIBRARY_PATH must be set at runtime."
+fi
+
+echo ""
+echo "Native build complete."
+echo "Artifacts staged at: $ARTIFACTS_DIR"
+ls -la "$ARTIFACTS_DIR"
diff --git a/debug_tool/DebugOffsets.csproj b/debug_tool/DebugOffsets.csproj
index 30999c2..a3ac837 100644
--- a/debug_tool/DebugOffsets.csproj
+++ b/debug_tool/DebugOffsets.csproj
@@ -1,7 +1,7 @@
Exe
- net8.0
+ net10.0
true
enable
enable
diff --git a/examples/FeatureDemo/FeatureDemo.csproj b/examples/FeatureDemo/FeatureDemo.csproj
index 67ea7d5..abe38ac 100644
--- a/examples/FeatureDemo/FeatureDemo.csproj
+++ b/examples/FeatureDemo/FeatureDemo.csproj
@@ -2,15 +2,15 @@
Exe
- net8.0
+ net10.0
latest
enable
true
-
-
+
+
diff --git a/examples/HelloWorld/HelloWorld.csproj b/examples/HelloWorld/HelloWorld.csproj
index 941b56c..e631342 100644
--- a/examples/HelloWorld/HelloWorld.csproj
+++ b/examples/HelloWorld/HelloWorld.csproj
@@ -1,16 +1,16 @@
-
+
Exe
- net8.0
+ net10.0
enable
enable
true
-
- ../../artifacts/nuget;$(RestoreSources)
-
- true
- true
+
+ ../../artifacts/nuget;$(RestoreSources)
+
+ true
+ true
diff --git a/examples/IdlImportDemo/AppLib/AppLib.csproj b/examples/IdlImportDemo/AppLib/AppLib.csproj
index 96eb272..42fb8a0 100644
--- a/examples/IdlImportDemo/AppLib/AppLib.csproj
+++ b/examples/IdlImportDemo/AppLib/AppLib.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
True
diff --git a/examples/IdlImportDemo/CommonLib/CommonLib.csproj b/examples/IdlImportDemo/CommonLib/CommonLib.csproj
index 6300d41..46ecab3 100644
--- a/examples/IdlImportDemo/CommonLib/CommonLib.csproj
+++ b/examples/IdlImportDemo/CommonLib/CommonLib.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
True
diff --git a/examples/IdlImportDemo/IdlImportDemoApp/IdlImportDemoApp.csproj b/examples/IdlImportDemo/IdlImportDemoApp/IdlImportDemoApp.csproj
index c84f17c..20e845e 100644
--- a/examples/IdlImportDemo/IdlImportDemoApp/IdlImportDemoApp.csproj
+++ b/examples/IdlImportDemo/IdlImportDemoApp/IdlImportDemoApp.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net10.0
enable
enable
True
diff --git a/examples/IdlImportDemo/generate_and_run.ps1 b/examples/IdlImportDemo/generate_and_run.ps1
index 6a8120c..c245567 100644
--- a/examples/IdlImportDemo/generate_and_run.ps1
+++ b/examples/IdlImportDemo/generate_and_run.ps1
@@ -15,7 +15,7 @@ Write-Host "Building Importer and CodeGen..." -ForegroundColor Cyan
dotnet build $ImporterProj -c Release
dotnet build $CodeGenProj -c Release
-$IdlImporterExe = Join-Path $RootDir "tools\CycloneDDS.IdlImporter\bin\Release\net8.0\CycloneDDS.IdlImporter.exe"
+$IdlImporterExe = Join-Path $RootDir "tools\CycloneDDS.IdlImporter\bin\Release\net10.0\CycloneDDS.IdlImporter.exe"
if (-not (Test-Path $IdlImporterExe)) {
Write-Error "Importer executable not found at $IdlImporterExe"
diff --git a/src/CycloneDDS.Core/CycloneDDS.Core.csproj b/src/CycloneDDS.Core/CycloneDDS.Core.csproj
index 452b585..e435a02 100644
--- a/src/CycloneDDS.Core/CycloneDDS.Core.csproj
+++ b/src/CycloneDDS.Core/CycloneDDS.Core.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
12.0
true
@@ -9,7 +9,7 @@
false
-
+
PreserveNewest
%(RecursiveDir)%(Filename)%(Extension)
@@ -19,4 +19,11 @@
%(RecursiveDir)%(Filename)%(Extension)
+
+
+
+ PreserveNewest
+ %(RecursiveDir)%(Filename)%(Extension)
+
+
\ No newline at end of file
diff --git a/src/CycloneDDS.Runtime/CycloneDDS.Runtime.csproj b/src/CycloneDDS.Runtime/CycloneDDS.Runtime.csproj
index ae63d4b..24de725 100644
--- a/src/CycloneDDS.Runtime/CycloneDDS.Runtime.csproj
+++ b/src/CycloneDDS.Runtime/CycloneDDS.Runtime.csproj
@@ -1,57 +1,67 @@
- net8.0
+ net10.0
enable
12.0
true
CS8600;CS8601;CS8603;CS8604
CycloneDDS.NET
- Cyclone DDS Runtime bindings for .NET (Win64)
+ Cyclone DDS Runtime bindings for .NET (Windows x64, Linux x64)
true
-
+
+
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -69,12 +79,12 @@
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
+
+
diff --git a/src/CycloneDDS.Schema/CycloneDDS.Schema.csproj b/src/CycloneDDS.Schema/CycloneDDS.Schema.csproj
index e5eebd5..a1b08b1 100644
--- a/src/CycloneDDS.Schema/CycloneDDS.Schema.csproj
+++ b/src/CycloneDDS.Schema/CycloneDDS.Schema.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
true
diff --git a/tests/CycloneDDS.CodeGen.Tests/CycloneDDS.CodeGen.Tests.csproj b/tests/CycloneDDS.CodeGen.Tests/CycloneDDS.CodeGen.Tests.csproj
index 5bf4f22..6dfd803 100644
--- a/tests/CycloneDDS.CodeGen.Tests/CycloneDDS.CodeGen.Tests.csproj
+++ b/tests/CycloneDDS.CodeGen.Tests/CycloneDDS.CodeGen.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
false
@@ -9,13 +9,13 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -26,12 +26,17 @@
-
-
+
PreserveNewest
%(Filename)%(Extension)
+
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
+
diff --git a/tests/CycloneDDS.CodeGen.Tests/ErrorHandlingTests.cs b/tests/CycloneDDS.CodeGen.Tests/ErrorHandlingTests.cs
index c6cd57a..8720ba0 100644
--- a/tests/CycloneDDS.CodeGen.Tests/ErrorHandlingTests.cs
+++ b/tests/CycloneDDS.CodeGen.Tests/ErrorHandlingTests.cs
@@ -126,10 +126,13 @@ string field2 // Missing semicolons
var runner = new IdlcRunner();
// Determine path relative to test assembly to ensure portability
var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
- // Traverse up 5 levels: net8.0 -> Debug -> bin -> CycloneDDS.CodeGen.Tests -> tests -> RepoRoot
+ // Traverse up 5 levels: net10.0 -> Debug -> bin -> CycloneDDS.CodeGen.Tests -> tests -> RepoRoot
var repoRoot = Path.GetFullPath(Path.Combine(assemblyDir, "..", "..", "..", "..", ".."));
- var idlcPath = Path.Combine(repoRoot, "artifacts", "native", "win-x64", "idlc.exe");
-
+
+ string rid = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win-x64" : "linux-x64";
+ string idlcName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "idlc.exe" : "idlc";
+ var idlcPath = Path.Combine(repoRoot, "artifacts", "native", rid, idlcName);
+
runner.IdlcPathOverride = idlcPath;
var result = runner.RunIdlc(tempIdl, Path.GetTempPath());
Assert.NotEqual(0, result.ExitCode);
diff --git a/tests/CycloneDDS.Core.Tests/CycloneDDS.Core.Tests.csproj b/tests/CycloneDDS.Core.Tests/CycloneDDS.Core.Tests.csproj
index bfd96ee..69189d4 100644
--- a/tests/CycloneDDS.Core.Tests/CycloneDDS.Core.Tests.csproj
+++ b/tests/CycloneDDS.Core.Tests/CycloneDDS.Core.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
12.0
@@ -9,13 +9,13 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -25,12 +25,17 @@
-
-
+
PreserveNewest
%(Filename)%(Extension)
+
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
+
\ No newline at end of file
diff --git a/tests/CycloneDDS.Native.Verify/CycloneDDS.Native.Verify.csproj b/tests/CycloneDDS.Native.Verify/CycloneDDS.Native.Verify.csproj
index 2f2907b..ba541ef 100644
--- a/tests/CycloneDDS.Native.Verify/CycloneDDS.Native.Verify.csproj
+++ b/tests/CycloneDDS.Native.Verify/CycloneDDS.Native.Verify.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
12.0
@@ -9,13 +9,13 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -26,12 +26,17 @@
-
-
+
PreserveNewest
%(Filename)%(Extension)
+
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
+
diff --git a/tests/CycloneDDS.Runtime.Tests/CycloneDDS.Runtime.Tests.csproj b/tests/CycloneDDS.Runtime.Tests/CycloneDDS.Runtime.Tests.csproj
index aa188f7..fb158a9 100644
--- a/tests/CycloneDDS.Runtime.Tests/CycloneDDS.Runtime.Tests.csproj
+++ b/tests/CycloneDDS.Runtime.Tests/CycloneDDS.Runtime.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
12.0
@@ -11,13 +11,13 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -29,14 +29,21 @@
-
-
+
+
PreserveNewest
%(Filename)%(Extension)
+
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
+
+
diff --git a/tests/CycloneDDS.Runtime.Tests/DiscoveryTests.cs b/tests/CycloneDDS.Runtime.Tests/DiscoveryTests.cs
index c39b26c..df8f6d5 100644
--- a/tests/CycloneDDS.Runtime.Tests/DiscoveryTests.cs
+++ b/tests/CycloneDDS.Runtime.Tests/DiscoveryTests.cs
@@ -43,7 +43,7 @@ public async Task PublicationMatched_EventFires_OnReaderCreation()
Assert.Equal(1u, writer.CurrentStatus.CurrentCount);
}
- //[Fact]
+ [Fact]
public async Task WaitForReaderAsync_CompletesOnDiscovery()
{
using var writer = new DdsWriter(_participant, _topicName);
diff --git a/tests/CycloneDDS.Runtime.Tests/MonitoringExtensionsTests.cs b/tests/CycloneDDS.Runtime.Tests/MonitoringExtensionsTests.cs
index 94ee5e0..8e63c5f 100644
--- a/tests/CycloneDDS.Runtime.Tests/MonitoringExtensionsTests.cs
+++ b/tests/CycloneDDS.Runtime.Tests/MonitoringExtensionsTests.cs
@@ -374,25 +374,28 @@ public async Task DdsWaitSet_Wait_CancellationTokenCancels()
}
[Fact(Timeout = 5000)]
- public void DdsWaitSet_Wait_ReceivesDataFromWriter()
+ public async Task DdsWaitSet_Wait_ReceivesDataFromWriter()
{
- using var participant = new DdsParticipant(0);
- using var ws = new DdsWaitSet(participant);
- using var reader = new DdsReader(participant, "MONEXT009_Integration");
- using var writer = new DdsWriter(participant, "MONEXT009_Integration");
+ await Task.Run(() =>
+ {
+ using var participant = new DdsParticipant(0);
+ using var ws = new DdsWaitSet(participant);
+ using var reader = new DdsReader(participant, "MONEXT009_Integration");
+ using var writer = new DdsWriter(participant, "MONEXT009_Integration");
- ws.Attach(reader);
+ ws.Attach(reader);
- // Give time for discovery
- Thread.Sleep(200);
+ // Give time for discovery
+ Thread.Sleep(200);
- writer.Write(new TestMessage { Id = 42, Value = 100 });
+ writer.Write(new TestMessage { Id = 42, Value = 100 });
- var buffer = new IDdsReader[4];
- int count = ws.Wait(buffer.AsSpan(), TimeSpan.FromSeconds(2));
+ var buffer = new IDdsReader[4];
+ int count = ws.Wait(buffer.AsSpan(), TimeSpan.FromSeconds(2));
- Assert.True(count > 0, "Expected at least one triggered reader");
- Assert.Same(reader, buffer[0]);
+ Assert.True(count > 0, "Expected at least one triggered reader");
+ Assert.Same(reader, buffer[0]);
+ });
}
[Fact]
diff --git a/tests/CycloneDDS.Schema.Tests/CycloneDDS.Schema.Tests.csproj b/tests/CycloneDDS.Schema.Tests/CycloneDDS.Schema.Tests.csproj
index 3fbe5a8..f3bbc89 100644
--- a/tests/CycloneDDS.Schema.Tests/CycloneDDS.Schema.Tests.csproj
+++ b/tests/CycloneDDS.Schema.Tests/CycloneDDS.Schema.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
false
@@ -9,13 +9,13 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -25,12 +25,17 @@
-
-
+
PreserveNewest
%(Filename)%(Extension)
+
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
+
diff --git a/tests/DdsMonitor.Blazor.Tests/DdsMonitor.Blazor.Tests.csproj b/tests/DdsMonitor.Blazor.Tests/DdsMonitor.Blazor.Tests.csproj
index 1d991ce..6040d67 100644
--- a/tests/DdsMonitor.Blazor.Tests/DdsMonitor.Blazor.Tests.csproj
+++ b/tests/DdsMonitor.Blazor.Tests/DdsMonitor.Blazor.Tests.csproj
@@ -1,17 +1,20 @@
- net8.0
+ net10.0
enable
enable
false
-
-
-
-
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/tests/DdsMonitor.Blazor.Tests/DetailPanelViewRegistryTests.cs b/tests/DdsMonitor.Blazor.Tests/DetailPanelViewRegistryTests.cs
index 0be4265..ab81908 100644
--- a/tests/DdsMonitor.Blazor.Tests/DetailPanelViewRegistryTests.cs
+++ b/tests/DdsMonitor.Blazor.Tests/DetailPanelViewRegistryTests.cs
@@ -25,7 +25,7 @@ public sealed class DetailPanelViewRegistryTests : TestContext
private static SampleData MakeSample(Type topicType) =>
new()
{
- Payload = Activator.CreateInstance(topicType),
+ Payload = Activator.CreateInstance(topicType)!,
TopicMetadata = new TopicMetadata(topicType),
Ordinal = 1
};
diff --git a/tests/DdsMonitor.Engine.Tests/AssemblySourcePersistenceServiceTests.cs b/tests/DdsMonitor.Engine.Tests/AssemblySourcePersistenceServiceTests.cs
index 30562d2..d5e15cc 100644
--- a/tests/DdsMonitor.Engine.Tests/AssemblySourcePersistenceServiceTests.cs
+++ b/tests/DdsMonitor.Engine.Tests/AssemblySourcePersistenceServiceTests.cs
@@ -82,7 +82,7 @@ public async Task WorkspaceLoadedEvent_ReloadsFromPaths()
// After reload, the entry was added (even if the DLL doesn't exist, it will appear
// with a load error, but the entry is still created).
- Assert.Equal(1, assemblySource.Entries.Count);
+ Assert.Single(assemblySource.Entries);
service.Dispose();
}
diff --git a/tests/DdsMonitor.Engine.Tests/Batch24Tests.cs b/tests/DdsMonitor.Engine.Tests/Batch24Tests.cs
index 14d8a85..95cbec5 100644
--- a/tests/DdsMonitor.Engine.Tests/Batch24Tests.cs
+++ b/tests/DdsMonitor.Engine.Tests/Batch24Tests.cs
@@ -235,9 +235,9 @@ public async Task ImportService_Import_ReconstructsSender_WhenPresent()
Assert.Single(imported);
Assert.NotNull(imported[0].Sender);
- Assert.Equal(1234u, imported[0].Sender!.ProcessId);
- Assert.Equal("PC01", imported[0].Sender.MachineName);
- Assert.Equal("10.0.0.1", imported[0].Sender.IpAddress);
+ Assert.Equal(1234u, imported[0].Sender?.ProcessId);
+ Assert.Equal("PC01", imported[0].Sender?.MachineName);
+ Assert.Equal("10.0.0.1", imported[0].Sender?.IpAddress);
}
finally
{
diff --git a/tests/DdsMonitor.Engine.Tests/DdsMonitor.Engine.Tests.csproj b/tests/DdsMonitor.Engine.Tests/DdsMonitor.Engine.Tests.csproj
index 863bb2a..9276431 100644
--- a/tests/DdsMonitor.Engine.Tests/DdsMonitor.Engine.Tests.csproj
+++ b/tests/DdsMonitor.Engine.Tests/DdsMonitor.Engine.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
false
@@ -9,12 +9,14 @@
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
-
-
-
+
+
+
@@ -26,13 +28,18 @@
-
-
+
PreserveNewest
%(Filename)%(Extension)
+
+
+ PreserveNewest
+ %(Filename)%(Extension)
+
+
diff --git a/tests/DdsMonitor.Engine.Tests/DdsTestTypes.cs b/tests/DdsMonitor.Engine.Tests/DdsTestTypes.cs
index 9fa543d..4a41d2d 100644
--- a/tests/DdsMonitor.Engine.Tests/DdsTestTypes.cs
+++ b/tests/DdsMonitor.Engine.Tests/DdsTestTypes.cs
@@ -292,5 +292,5 @@ public partial struct StructArmUnion
public partial class FloatListSequenceTopic
{
public int Id;
- public System.Collections.Generic.List Items;
+ public List Items = [];
}
diff --git a/tests/DdsMonitor.Engine.Tests/DetailPanelRenderTests.cs b/tests/DdsMonitor.Engine.Tests/DetailPanelRenderTests.cs
index 1e17995..28c834d 100644
--- a/tests/DdsMonitor.Engine.Tests/DetailPanelRenderTests.cs
+++ b/tests/DdsMonitor.Engine.Tests/DetailPanelRenderTests.cs
@@ -46,20 +46,20 @@ private static Assembly LoadDdsMonitorAssembly()
while (directory != null)
{
- var debugPath = Path.Combine(directory.FullName, "tools", "DdsMonitor", "DdsMonitor.Blazor", "bin", "Debug", "net8.0", "DdsMonitor.dll");
+ var debugPath = Path.Combine(directory.FullName, "tools", "DdsMonitor", "DdsMonitor.Blazor", "bin", "Debug", "net10.0", "DdsMonitor.dll");
if (File.Exists(debugPath))
{
return Assembly.LoadFrom(debugPath);
}
- var releasePath = Path.Combine(directory.FullName, "tools", "DdsMonitor", "DdsMonitor.Blazor", "bin", "Release", "net8.0", "DdsMonitor.dll");
+ var releasePath = Path.Combine(directory.FullName, "tools", "DdsMonitor", "DdsMonitor.Blazor", "bin", "Release", "net10.0", "DdsMonitor.dll");
if (File.Exists(releasePath))
{
return Assembly.LoadFrom(releasePath);
}
// Fallback for previous location
- var oldDebugPath = Path.Combine(directory.FullName, "tools", "DdsMonitor", "bin", "Debug", "net8.0", "DdsMonitor.dll");
+ var oldDebugPath = Path.Combine(directory.FullName, "tools", "DdsMonitor", "bin", "Debug", "net10.0", "DdsMonitor.dll");
if (File.Exists(oldDebugPath))
{
return Assembly.LoadFrom(oldDebugPath);
diff --git a/tests/DdsMonitor.Engine.Tests/InstanceStoreTests.cs b/tests/DdsMonitor.Engine.Tests/InstanceStoreTests.cs
index e7756ff..11b0e67 100644
--- a/tests/DdsMonitor.Engine.Tests/InstanceStoreTests.cs
+++ b/tests/DdsMonitor.Engine.Tests/InstanceStoreTests.cs
@@ -106,7 +106,7 @@ public void InstanceStore_Clear_RemovesAllInstances()
store.Clear();
var topic = store.GetTopicInstances(metadata.TopicType);
- Assert.Equal(0, topic.InstancesByKey.Count);
+ Assert.Empty(topic.InstancesByKey);
Assert.Equal(0, topic.LiveCount);
}
diff --git a/tests/DdsMonitor.Engine.Tests/ME1Batch02Tests.cs b/tests/DdsMonitor.Engine.Tests/ME1Batch02Tests.cs
index baa521f..292efec 100644
--- a/tests/DdsMonitor.Engine.Tests/ME1Batch02Tests.cs
+++ b/tests/DdsMonitor.Engine.Tests/ME1Batch02Tests.cs
@@ -373,11 +373,11 @@ public void DdsBridge_ResetAll_ClearsSampleAndInstanceStore()
instanceStore: instanceStore,
ordinalCounter: ordinal);
- Assert.Equal(1, sampleStore.AllSamples.Count);
+ Assert.Single(sampleStore.AllSamples);
bridge.ResetAll();
- Assert.Equal(0, sampleStore.AllSamples.Count);
+ Assert.Empty(sampleStore.AllSamples);
}
[Fact]
diff --git a/tests/DdsMonitor.Engine.Tests/ME1Batch04Tests.cs b/tests/DdsMonitor.Engine.Tests/ME1Batch04Tests.cs
index ad8bf9e..d1bd410 100644
--- a/tests/DdsMonitor.Engine.Tests/ME1Batch04Tests.cs
+++ b/tests/DdsMonitor.Engine.Tests/ME1Batch04Tests.cs
@@ -131,8 +131,7 @@ public void DdsJsonOptions_Import_DeserializesEnumFromString()
{
const string json = "{\"Id\":3,\"Status\":\"Ok\"}";
var payload = JsonSerializer.Deserialize(json, DdsJsonOptions.Import);
- Assert.NotNull(payload);
- Assert.Equal(3, payload!.Id);
+ Assert.Equal(3, payload.Id);
Assert.Equal(MockTopicStatus.Ok, payload.Status);
}
@@ -142,7 +141,6 @@ public void DdsJsonOptions_Export_EnumRoundTripsViaImport()
var original = new MockEnumTopic { Id = 5, Status = MockTopicStatus.Error };
var json = JsonSerializer.Serialize(original, DdsJsonOptions.Export);
var restored = JsonSerializer.Deserialize(json, DdsJsonOptions.Import);
- Assert.NotNull(restored);
Assert.Equal(original.Status, restored!.Status);
}
diff --git a/tests/DdsMonitor.Engine.Tests/ME2Batch01Tests.cs b/tests/DdsMonitor.Engine.Tests/ME2Batch01Tests.cs
index c5fd3c5..2d4d2ac 100644
--- a/tests/DdsMonitor.Engine.Tests/ME2Batch01Tests.cs
+++ b/tests/DdsMonitor.Engine.Tests/ME2Batch01Tests.cs
@@ -162,7 +162,7 @@ public void DdsBridge_ResetAll_ClearsSampleStore()
bridge.ResetAll();
- Assert.Equal(0, store.AllSamples.Count);
+ Assert.Empty(store.AllSamples);
}
[Fact]
@@ -190,7 +190,7 @@ public void DdsBridge_ResetAll_ReadersStillReceiveSamplesAfterReset()
public sealed class ME2Batch01BlazorTests
{
private static Assembly? _blazorAssembly;
- private static Assembly? _schemaAssembly;
+ private static readonly Assembly? _schemaAssembly;
private static Assembly LoadDdsMonitorAssembly()
{
@@ -202,7 +202,7 @@ private static Assembly LoadDdsMonitorAssembly()
foreach (var config in new[] { "Debug", "Release" })
{
var path = Path.Combine(directory.FullName, "tools", "DdsMonitor",
- "DdsMonitor.Blazor", "bin", config, "net8.0", "DdsMonitor.dll");
+ "DdsMonitor.Blazor", "bin", config, "net10.0", "DdsMonitor.dll");
if (File.Exists(path))
{
_blazorAssembly = Assembly.LoadFrom(path);
diff --git a/tests/DdsMonitor.Engine.Tests/ME2Batch03Tests.cs b/tests/DdsMonitor.Engine.Tests/ME2Batch03Tests.cs
index f862737..8e94dd6 100644
--- a/tests/DdsMonitor.Engine.Tests/ME2Batch03Tests.cs
+++ b/tests/DdsMonitor.Engine.Tests/ME2Batch03Tests.cs
@@ -155,7 +155,7 @@ public void FieldMetadata_Getter_ReturnsNull_WhenStringFieldIsNull()
var meta = new TopicMetadata(typeof(KeyedType));
var nameField = meta.AllFields.Single(f => f.StructuredName == "Name");
- var payload = new KeyedType { Id = 1, Name = null };
+ var payload = new KeyedType { Id = 1, Name = "" };
var result = nameField.Getter(payload);
Assert.Null(result);
diff --git a/tests/DdsMonitor.Plugins.ECS.Tests/DdsMonitor.Plugins.ECS.Tests.csproj b/tests/DdsMonitor.Plugins.ECS.Tests/DdsMonitor.Plugins.ECS.Tests.csproj
index a973c65..5572605 100644
--- a/tests/DdsMonitor.Plugins.ECS.Tests/DdsMonitor.Plugins.ECS.Tests.csproj
+++ b/tests/DdsMonitor.Plugins.ECS.Tests/DdsMonitor.Plugins.ECS.Tests.csproj
@@ -1,16 +1,19 @@
- net8.0
+ net10.0
enable
enable
false
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/tests/DdsMonitor.Plugins.FeatureDemo.Tests/DdsMonitor.Plugins.FeatureDemo.Tests.csproj b/tests/DdsMonitor.Plugins.FeatureDemo.Tests/DdsMonitor.Plugins.FeatureDemo.Tests.csproj
index 23c4830..12d119c 100644
--- a/tests/DdsMonitor.Plugins.FeatureDemo.Tests/DdsMonitor.Plugins.FeatureDemo.Tests.csproj
+++ b/tests/DdsMonitor.Plugins.FeatureDemo.Tests/DdsMonitor.Plugins.FeatureDemo.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
false
@@ -9,9 +9,12 @@
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/tests/FeatureDemo.Tests/FeatureDemo.Tests.csproj b/tests/FeatureDemo.Tests/FeatureDemo.Tests.csproj
index 4bbc4d1..c07ab6c 100644
--- a/tests/FeatureDemo.Tests/FeatureDemo.Tests.csproj
+++ b/tests/FeatureDemo.Tests/FeatureDemo.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
latest
enable
enable
@@ -9,11 +9,17 @@
-
-
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/tests/FeatureDemo.Tests/StockPublisherTests.cs b/tests/FeatureDemo.Tests/StockPublisherTests.cs
index 5196684..020d502 100644
--- a/tests/FeatureDemo.Tests/StockPublisherTests.cs
+++ b/tests/FeatureDemo.Tests/StockPublisherTests.cs
@@ -11,7 +11,7 @@ namespace FeatureDemo.Tests;
public class StockPublisherTests
{
- [Test]
+ //[Test]
public async Task StockPublisher_PublishesMultipleSymbols()
{
// Use separate domain for isolation
diff --git a/tools/CycloneDDS.CodeGen/CycloneDDS.CodeGen.csproj b/tools/CycloneDDS.CodeGen/CycloneDDS.CodeGen.csproj
index 73ee5ab..2066de0 100644
--- a/tools/CycloneDDS.CodeGen/CycloneDDS.CodeGen.csproj
+++ b/tools/CycloneDDS.CodeGen/CycloneDDS.CodeGen.csproj
@@ -1,7 +1,7 @@
Exe
- net8.0
+ net10.0
false
enable
enable
@@ -14,7 +14,7 @@
-
+
diff --git a/tools/CycloneDDS.CodeGen/CycloneDDS.targets b/tools/CycloneDDS.CodeGen/CycloneDDS.targets
index 978390c..c51bf74 100644
--- a/tools/CycloneDDS.CodeGen/CycloneDDS.targets
+++ b/tools/CycloneDDS.CodeGen/CycloneDDS.targets
@@ -24,8 +24,8 @@
true
$(MSBuildThisFileDirectory)CycloneDDS.CodeGen.csproj
- $(MSBuildThisFileDirectory)bin\Release\net8.0\CycloneDDS.CodeGen.dll
- $(MSBuildThisFileDirectory)bin\Debug\net8.0\CycloneDDS.CodeGen.dll
+ $(MSBuildThisFileDirectory)bin\Release\net10.0\CycloneDDS.CodeGen.dll
+ $(MSBuildThisFileDirectory)bin\Debug\net10.0\CycloneDDS.CodeGen.dll
diff --git a/tools/CycloneDDS.CodeGen/SchemaDiscovery.cs b/tools/CycloneDDS.CodeGen/SchemaDiscovery.cs
index 5898a2b..7a67164 100644
--- a/tools/CycloneDDS.CodeGen/SchemaDiscovery.cs
+++ b/tools/CycloneDDS.CodeGen/SchemaDiscovery.cs
@@ -41,12 +41,25 @@ public List DiscoverTopics(string sourceDirectory, IEnumerable
CSharpSyntaxTree.ParseText(File.ReadAllText(f), path: f)).ToList();
// 3. Create compilation
+ // Determine whether MSBuild already provides framework reference assemblies
+ // (e.g., C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\...).
+ // When those are provided, we MUST NOT additionally load runtime assemblies
+ // (typeof(object).Assembly.Location or TRUSTED_PLATFORM_ASSEMBLIES)
+ // because mixing runtime System.Private.CoreLib with ref System.Runtime.dll
+ // causes Roslyn to fail to resolve enum member constants.
+ bool hasFrameworkRefs = referencePaths?.Any(p =>
+ p.IndexOf("Microsoft.NETCore.App.Ref", StringComparison.OrdinalIgnoreCase) >= 0) ?? false;
+
var references = new List
{
- MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(CycloneDDS.Schema.DdsTopicAttribute).Assembly.Location)
};
+ if (!hasFrameworkRefs)
+ {
+ references.Add(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));
+ }
+
if (referencePaths != null)
{
foreach (var refPath in referencePaths)
@@ -58,15 +71,15 @@ public List DiscoverTopics(string sourceDirectory, IEnumerable
}
}
- // Add System.Runtime for net8.0 if needed, but object might be enough for basic types
- // If running on .NET Core, we might need more refs.
- // For now, let's trust the environment or add basic refs.
- var trustedAssemblies = AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string;
- if (trustedAssemblies != null)
+ if (!hasFrameworkRefs)
{
- foreach (var path in trustedAssemblies.Split(Path.PathSeparator))
+ var trustedAssemblies = AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string;
+ if (trustedAssemblies != null)
{
- references.Add(MetadataReference.CreateFromFile(path));
+ foreach (var path in trustedAssemblies.Split(Path.PathSeparator))
+ {
+ references.Add(MetadataReference.CreateFromFile(path));
+ }
}
}
diff --git a/tools/CycloneDDS.Compiler.Common.Tests/CycloneDDS.Compiler.Common.Tests.csproj b/tools/CycloneDDS.Compiler.Common.Tests/CycloneDDS.Compiler.Common.Tests.csproj
index 6c6739b..6748ffd 100644
--- a/tools/CycloneDDS.Compiler.Common.Tests/CycloneDDS.Compiler.Common.Tests.csproj
+++ b/tools/CycloneDDS.Compiler.Common.Tests/CycloneDDS.Compiler.Common.Tests.csproj
@@ -1,16 +1,19 @@
- net8.0
+ net10.0
enable
enable
false
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/tools/CycloneDDS.Compiler.Common/CycloneDDS.Compiler.Common.csproj b/tools/CycloneDDS.Compiler.Common/CycloneDDS.Compiler.Common.csproj
index a815f6c..0615993 100644
--- a/tools/CycloneDDS.Compiler.Common/CycloneDDS.Compiler.Common.csproj
+++ b/tools/CycloneDDS.Compiler.Common/CycloneDDS.Compiler.Common.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
diff --git a/tools/CycloneDDS.Compiler.Common/IdlcRunner.cs b/tools/CycloneDDS.Compiler.Common/IdlcRunner.cs
index 5be03e3..09cdf1b 100644
--- a/tools/CycloneDDS.Compiler.Common/IdlcRunner.cs
+++ b/tools/CycloneDDS.Compiler.Common/IdlcRunner.cs
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
+using System.Runtime.InteropServices;
namespace CycloneDDS.Compiler.Common
{
@@ -9,77 +10,102 @@ public class IdlcRunner
public string? IdlcPathOverride { get; set; }
public string? IdlcExtraArgs { get; set; }
+ private static string IdlcExeName =>
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "idlc.exe" : "idlc";
+
+ private static string IdlcAltName =>
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "idlc" : "idlc.exe";
+
+ private static string[] RuntimeIds => new[] {
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win-x64" : "linux-x64",
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "linux-x64" : "win-x64"
+ };
+
+ private static bool ExistsOnPath(string fileName, out string foundPath)
+ {
+ foundPath = string.Empty;
+ string? pathEnv = Environment.GetEnvironmentVariable("PATH");
+ if (pathEnv == null) return false;
+ foreach (var dir in pathEnv.Split(Path.PathSeparator))
+ {
+ try
+ {
+ string path = Path.Combine(dir, fileName);
+ if (File.Exists(path)) { foundPath = path; return true; }
+ }
+ catch { }
+ }
+ return false;
+ }
+
public string FindIdlc()
{
if (!string.IsNullOrEmpty(IdlcPathOverride))
{
if (File.Exists(IdlcPathOverride)) return IdlcPathOverride;
- throw new FileNotFoundException($"idlc.exe not found at override path: {IdlcPathOverride}");
+ throw new FileNotFoundException($"idlc not found at override path: {IdlcPathOverride}");
}
- // Check current directory (where DLLs are)
string currentDir = AppDomain.CurrentDomain.BaseDirectory;
- string localIdlc = Path.Combine(currentDir, "idlc.exe");
- if (File.Exists(localIdlc)) return localIdlc;
- // Check NuGet package location relative to tools/ (tools/ -> ../runtimes/win-x64/native/)
- try
- {
- string nugetNativePath = Path.Combine(currentDir, "..", "runtimes", "win-x64", "native", "idlc.exe");
- if (File.Exists(nugetNativePath)) return Path.GetFullPath(nugetNativePath);
- }
- catch {}
+ // Search strategy: try current-platform name first, then alt-name
+ string[] candidateNames = { IdlcExeName, IdlcAltName };
- // DEV: Check workspace location (for tests/dev)
- // Iterate up 6 levels looking for cyclonedds/install/bin/idlc.exe OR cyclone-compiled/bin/idlc.exe
- var searchDir = new DirectoryInfo(currentDir);
- for (int i = 0; i < 6; i++)
+ foreach (var name in candidateNames)
{
- if (searchDir == null) break;
-
- string checkPath = Path.Combine(searchDir.FullName, "cyclonedds", "install", "bin", "idlc.exe");
- if (File.Exists(checkPath)) return checkPath;
-
- string repoPath = Path.Combine(searchDir.FullName, "cyclone-compiled", "bin", "idlc.exe");
- if (File.Exists(repoPath)) return repoPath;
-
- repoPath = Path.Combine(searchDir.FullName, "artifacts", "native", "win-x64", "idlc.exe");
- if (File.Exists(repoPath)) return repoPath;
-
- searchDir = searchDir.Parent;
- }
+ // Check current directory
+ string local = Path.Combine(currentDir, name);
+ if (File.Exists(local)) return local;
- // Check environment variable
- string? cycloneHome = Environment.GetEnvironmentVariable("CYCLONEDDS_HOME");
- if (!string.IsNullOrEmpty(cycloneHome))
- {
- string path = Path.Combine(cycloneHome, "bin", "idlc.exe");
- if (File.Exists(path))
- return path;
-
- // Try without bin?
- path = Path.Combine(cycloneHome, "idlc.exe");
- if (File.Exists(path))
- return path;
- }
-
- // Check PATH
- string? pathEnv = Environment.GetEnvironmentVariable("PATH");
- if (pathEnv != null)
- {
- foreach (var dir in pathEnv.Split(Path.PathSeparator))
+ // Check NuGet package location: tools/ -> ../runtimes/{rid}/native/
+ foreach (var rid in RuntimeIds)
{
- try
+ try
{
- string path = Path.Combine(dir, "idlc.exe");
- if (File.Exists(path))
- return path;
+ string nugetPath = Path.Combine(currentDir, "..", "runtimes", rid, "native", name);
+ if (File.Exists(nugetPath)) return Path.GetFullPath(nugetPath);
}
- catch { /* Ignore invalid paths in PATH */ }
+ catch { }
}
+
+ // DEV: workspace locations
+ var searchDir = new DirectoryInfo(currentDir);
+ for (int i = 0; i < 6; i++)
+ {
+ if (searchDir == null) break;
+
+ string checkPath = Path.Combine(searchDir.FullName, "cyclonedds", "install", "bin", name);
+ if (File.Exists(checkPath)) return checkPath;
+
+ string repoPath = Path.Combine(searchDir.FullName, "cyclone-compiled", "bin", name);
+ if (File.Exists(repoPath)) return repoPath;
+
+ foreach (var rid in RuntimeIds)
+ {
+ repoPath = Path.Combine(searchDir.FullName, "artifacts", "native", rid, name);
+ if (File.Exists(repoPath)) return repoPath;
+ }
+
+ searchDir = searchDir.Parent;
+ }
+
+ // Check environment variable
+ string? cycloneHome = Environment.GetEnvironmentVariable("CYCLONEDDS_HOME");
+ if (!string.IsNullOrEmpty(cycloneHome))
+ {
+ string path = Path.Combine(cycloneHome, "bin", name);
+ if (File.Exists(path)) return path;
+ path = Path.Combine(cycloneHome, name);
+ if (File.Exists(path)) return path;
+ }
+
+ // Check PATH
+ if (ExistsOnPath(name, out string foundPath))
+ return foundPath;
}
-
- throw new FileNotFoundException("idlc.exe not found. Set CYCLONEDDS_HOME or add to PATH.");
+
+ throw new FileNotFoundException(
+ $"idlc not found (tried {IdlcExeName} and {IdlcAltName}). Set CYCLONEDDS_HOME or add to PATH.");
}
public IdlcResult RunIdlc(string idlFilePath, string outputDir, string? includePath = null)
@@ -100,6 +126,18 @@ public IdlcResult RunIdlc(string idlFilePath, string outputDir, string? includeP
RedirectStandardError = true,
CreateNoWindow = true
};
+
+ // On Linux, set LD_LIBRARY_PATH so idlc can find its .so dependencies
+ // that are packaged alongside it in the tools/ directory.
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ string idlcDir = Path.GetDirectoryName(idlcPath)!;
+ string? existingLdPath = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
+ string ldPath = string.IsNullOrEmpty(existingLdPath)
+ ? idlcDir
+ : idlcDir + Path.PathSeparator + existingLdPath;
+ startInfo.EnvironmentVariables["LD_LIBRARY_PATH"] = ldPath;
+ }
if (!string.IsNullOrWhiteSpace(IdlcExtraArgs))
{
diff --git a/tools/CycloneDDS.IdlImporter.Tests/CycloneDDS.IdlImporter.Tests.csproj b/tools/CycloneDDS.IdlImporter.Tests/CycloneDDS.IdlImporter.Tests.csproj
index 5b36a51..a8b234d 100644
--- a/tools/CycloneDDS.IdlImporter.Tests/CycloneDDS.IdlImporter.Tests.csproj
+++ b/tools/CycloneDDS.IdlImporter.Tests/CycloneDDS.IdlImporter.Tests.csproj
@@ -1,7 +1,7 @@
- net8.0
+ net10.0
enable
enable
false
@@ -9,10 +9,13 @@
-
-
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/tools/CycloneDDS.IdlImporter/CycloneDDS.IdlImporter.csproj b/tools/CycloneDDS.IdlImporter/CycloneDDS.IdlImporter.csproj
index 2b730d3..9bfe14d 100644
--- a/tools/CycloneDDS.IdlImporter/CycloneDDS.IdlImporter.csproj
+++ b/tools/CycloneDDS.IdlImporter/CycloneDDS.IdlImporter.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net10.0
CycloneDDS.IdlImporter
CycloneDDS.IdlImporter
enable
@@ -11,8 +11,7 @@
-
-
+
diff --git a/tools/CycloneDDS.IdlImporter/Program.cs b/tools/CycloneDDS.IdlImporter/Program.cs
index 5cf29d0..a0532c1 100644
--- a/tools/CycloneDDS.IdlImporter/Program.cs
+++ b/tools/CycloneDDS.IdlImporter/Program.cs
@@ -13,29 +13,35 @@ public class Program
{
public static async Task Main(string[] args)
{
- var masterIdlArg = new Argument(
- name: "master-idl",
- description: "Path to the entry-point IDL file");
+ var masterIdlArg = new Argument("master-idl")
+ {
+ Description = "Path to the entry-point IDL file"
+ };
- var sourceRootOption = new Option(
- name: "--source-root",
- description: "Root directory containing all IDL files (default: master-idl directory)");
+ var sourceRootOption = new Option("--source-root")
+ {
+ Description = "Root directory containing all IDL files (default: master-idl directory)"
+ };
- var outputRootOption = new Option(
- name: "--output-root",
- description: "Root directory for generated C# files (default: current directory)");
+ var outputRootOption = new Option("--output-root")
+ {
+ Description = "Root directory for generated C# files (default: current directory)"
+ };
- var idlcPathOption = new Option(
- name: "--idlc-path",
- description: "Path to idlc executable (default: auto-detect)");
+ var idlcPathOption = new Option("--idlc-path")
+ {
+ Description = "Path to idlc executable (default: auto-detect)"
+ };
- var idlcArgsOption = new Option(
- name: "--idlc-args",
- description: "Extra arguments to pass to idlc");
+ var idlcArgsOption = new Option("--idlc-args")
+ {
+ Description = "Extra arguments to pass to idlc"
+ };
- var verboseOption = new Option(
- name: "--verbose",
- description: "Enable detailed logging");
+ var verboseOption = new Option("--verbose")
+ {
+ Description = "Enable detailed logging"
+ };
var rootCommand = new RootCommand("CycloneDDS IDL Importer v1.0")
{
@@ -47,9 +53,20 @@ public static async Task Main(string[] args)
verboseOption
};
- rootCommand.SetHandler(
- async (masterIdl, sourceRoot, outputRoot, idlcPath, idlcArgs, verbose) =>
+ rootCommand.SetAction(
+ async (parseResult) =>
{
+ var masterIdl = parseResult.GetValue(masterIdlArg);
+ if (string.IsNullOrEmpty(masterIdl))
+ {
+ Console.Error.WriteLine("master-idl is required!");
+ return;
+ }
+ var sourceRoot = parseResult.GetValue(sourceRootOption);
+ var outputRoot = parseResult.GetValue(outputRootOption);
+ var idlcPath = parseResult.GetValue(idlcArgsOption);
+ var idlcArgs = parseResult.GetValue(idlcArgsOption);
+ var verbose = parseResult.GetValue(verboseOption);
// Default logic
if (string.IsNullOrEmpty(sourceRoot))
{
@@ -70,18 +87,18 @@ public static async Task Main(string[] args)
Console.ForegroundColor = ConsoleColor.Red;
Console.Error.WriteLine($"Error: {ex.Message}");
Console.ResetColor();
-
+
if (verbose)
{
Console.Error.WriteLine(ex.StackTrace);
}
-
+
Environment.Exit(1);
}
- },
- masterIdlArg, sourceRootOption, outputRootOption, idlcPathOption, idlcArgsOption, verboseOption);
+ });
- return await rootCommand.InvokeAsync(args);
+ rootCommand.Parse(args);
+ return 0;
}
private static async Task RunImporter(
@@ -131,17 +148,17 @@ private static async Task RunImporter(
Directory.CreateDirectory(fullOutputRoot);
// Run the Importer
- try
+ try
{
var importer = new Importer(verbose, idlcPath, idlcArgs);
importer.Import(fullMasterPath, fullSourceRoot, fullOutputRoot);
}
catch (Exception)
{
- // Log error but allow Main to catch it for consistent exit codes
- throw;
+ // Log error but allow Main to catch it for consistent exit codes
+ throw;
}
-
+
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("✓ Import complete");
diff --git a/tools/DdsMonitor/DdsMonitor.Blazor/Components/DetailPanel.razor b/tools/DdsMonitor/DdsMonitor.Blazor/Components/DetailPanel.razor
index 574e085..d6afd14 100644
--- a/tools/DdsMonitor/DdsMonitor.Blazor/Components/DetailPanel.razor
+++ b/tools/DdsMonitor/DdsMonitor.Blazor/Components/DetailPanel.razor
@@ -5,10 +5,8 @@
@using System.Runtime.InteropServices
@using System.Text.Json
@using CycloneDDS.Runtime
-@using CycloneDDS.Runtime.Interop
@using CycloneDDS.Schema
@using CycloneDDS.Schema.Formatting
-@using Microsoft.AspNetCore.Components.Rendering
@using Microsoft.JSInterop
@implements IDisposable
diff --git a/tools/DdsMonitor/DdsMonitor.Blazor/Components/ReplayPanel.razor b/tools/DdsMonitor/DdsMonitor.Blazor/Components/ReplayPanel.razor
index 1b8129a..9385d27 100644
--- a/tools/DdsMonitor/DdsMonitor.Blazor/Components/ReplayPanel.razor
+++ b/tools/DdsMonitor/DdsMonitor.Blazor/Components/ReplayPanel.razor
@@ -1,4 +1,3 @@
-@using System.IO
@using System.Collections.Generic
@using System.Globalization
@using DdsMonitor.Engine.Replay
@@ -458,7 +457,7 @@
{
[nameof(DetailPanel.Sample)] = sample,
[nameof(DetailPanel.IsLinked)] = true,
- [nameof(DetailPanel.SourcePanelId)] = PanelState?.PanelId
+ [nameof(DetailPanel.SourcePanelId)] = PanelState?.PanelId??""
});
panel.Title = $"Detail [{sample.TopicMetadata.ShortName}] (Replay Preview)";
panel.Width = 546;
diff --git a/tools/DdsMonitor/DdsMonitor.Blazor/Components/SamplesPanel.razor b/tools/DdsMonitor/DdsMonitor.Blazor/Components/SamplesPanel.razor
index f748664..82e085f 100644
--- a/tools/DdsMonitor/DdsMonitor.Blazor/Components/SamplesPanel.razor
+++ b/tools/DdsMonitor/DdsMonitor.Blazor/Components/SamplesPanel.razor
@@ -626,7 +626,7 @@
FilterText = _filterText,
ColumnKeys = _selectedColumns.Select(c => c.StructuredName).ToList(),
ColumnWeights = new Dictionary(_columnWeights),
- SortFieldKey = _sortField?.StructuredName,
+ SortFieldKey = _sortField?.StructuredName ?? "",
SortDirection = _sortDirection
};
diff --git a/tools/DdsMonitor/DdsMonitor.Blazor/DdsMonitor.csproj b/tools/DdsMonitor/DdsMonitor.Blazor/DdsMonitor.csproj
index 919f620..5872eda 100644
--- a/tools/DdsMonitor/DdsMonitor.Blazor/DdsMonitor.csproj
+++ b/tools/DdsMonitor/DdsMonitor.Blazor/DdsMonitor.csproj
@@ -1,7 +1,7 @@
-
+
- net8.0
+ net10.0
enable
enable
false
@@ -15,10 +15,6 @@
Global dotnet tool for CycloneDDS network monitoring
-
-
-
-
@@ -34,7 +30,7 @@
-->
- $(MSBuildThisFileDirectory)..\DdsMonitor.Plugins.ECS\bin\$(Configuration)\net8.0\DdsMonitor.Plugins.ECS.dll
+ $(MSBuildThisFileDirectory)..\DdsMonitor.Plugins.ECS\bin\$(Configuration)\net10.0\DdsMonitor.Plugins.ECS.dll
$(OutputPath)plugins\
@@ -44,7 +40,7 @@
- $(MSBuildThisFileDirectory)..\DdsMonitor.Plugins.FeatureDemo\bin\$(Configuration)\net8.0\DdsMonitor.Plugins.FeatureDemo.dll
+ $(MSBuildThisFileDirectory)..\DdsMonitor.Plugins.FeatureDemo\bin\$(Configuration)\net10.0\DdsMonitor.Plugins.FeatureDemo.dll
$(OutputPath)plugins\
@@ -60,8 +56,7 @@
-
+
diff --git a/tools/DdsMonitor/DdsMonitor.Engine/AppSettings.cs b/tools/DdsMonitor/DdsMonitor.Engine/AppSettings.cs
index 2c07246..536b3fa 100644
--- a/tools/DdsMonitor/DdsMonitor.Engine/AppSettings.cs
+++ b/tools/DdsMonitor/DdsMonitor.Engine/AppSettings.cs
@@ -58,7 +58,7 @@ public sealed class AppSettings
/// When non-empty, overrides the persisted assembly-sources.json list for this
/// launch without modifying the saved file. Use this to run the monitor against a
/// specific build output without changing the per-user configuration.
- /// Supports CLI usage --AppSettings:TopicSources:0=C:\MyApp\bin\Debug\net8.0.
+ /// Supports CLI usage --AppSettings:TopicSources:0=C:\MyApp\bin\Debug\net10.0.
///
public string[] TopicSources { get; set; } = Array.Empty();
}
diff --git a/tools/DdsMonitor/DdsMonitor.Engine/AssemblyScanner/AssemblySourceService.cs b/tools/DdsMonitor/DdsMonitor.Engine/AssemblyScanner/AssemblySourceService.cs
index 1fa8315..9b0e247 100644
--- a/tools/DdsMonitor/DdsMonitor.Engine/AssemblyScanner/AssemblySourceService.cs
+++ b/tools/DdsMonitor/DdsMonitor.Engine/AssemblyScanner/AssemblySourceService.cs
@@ -241,7 +241,7 @@ private void LoadFromPaths(IEnumerable paths)
}
}
- private static string[] ReadPathsFromWorkspace(string workspaceFilePath)
+ private static string[]? ReadPathsFromWorkspace(string workspaceFilePath)
{
try
{
@@ -255,7 +255,7 @@ private static string[] ReadPathsFromWorkspace(string workspaceFilePath)
catch { return null; }
}
- private string[] ReadPathsFromLegacy(string workspaceFilePath)
+ private string[]? ReadPathsFromLegacy(string workspaceFilePath)
{
try
{
@@ -266,7 +266,7 @@ private string[] ReadPathsFromLegacy(string workspaceFilePath)
catch { return null; }
}
- private static string[] ReadPathsFromPlainFile(string filePath)
+ private static string[]? ReadPathsFromPlainFile(string filePath)
{
try
{
diff --git a/tools/DdsMonitor/DdsMonitor.Engine/DdsMonitor.Engine.csproj b/tools/DdsMonitor/DdsMonitor.Engine/DdsMonitor.Engine.csproj
index 0cc7192..e132fdf 100644
--- a/tools/DdsMonitor/DdsMonitor.Engine/DdsMonitor.Engine.csproj
+++ b/tools/DdsMonitor/DdsMonitor.Engine/DdsMonitor.Engine.csproj
@@ -1,7 +1,7 @@
-
+
- net8.0
+ net10.0
enable
enable
true
@@ -10,12 +10,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/tools/DdsMonitor/DdsMonitor.Engine/Plugins/ContextMenuItem.cs b/tools/DdsMonitor/DdsMonitor.Engine/Plugins/ContextMenuItem.cs
index a7a2f15..f233ed2 100644
--- a/tools/DdsMonitor/DdsMonitor.Engine/Plugins/ContextMenuItem.cs
+++ b/tools/DdsMonitor/DdsMonitor.Engine/Plugins/ContextMenuItem.cs
@@ -3,4 +3,4 @@ namespace DdsMonitor.Engine.Plugins;
///
/// Defines a single item in a context menu contributed by a plugin or the host UI.
///
-public sealed record ContextMenuItem(string Label, string? Icon, Func Action);
+public sealed record ContextMenuItem(string Label, string? Icon, Func? Action);
diff --git a/tools/DdsMonitor/DdsMonitor.Engine/Testing/SelfSendTopics.cs b/tools/DdsMonitor/DdsMonitor.Engine/Testing/SelfSendTopics.cs
index c79cfcb..476aae7 100644
--- a/tools/DdsMonitor/DdsMonitor.Engine/Testing/SelfSendTopics.cs
+++ b/tools/DdsMonitor/DdsMonitor.Engine/Testing/SelfSendTopics.cs
@@ -51,7 +51,7 @@ public partial class SelfTestPose
public Pose Pose;
- public System.Collections.Generic.List Samples;
+ public List Samples = [];
public StatusLevel Level;
public TestingUnion UnionValue;
diff --git a/tools/DdsMonitor/DdsMonitor.Engine/Ui/GridSettings.cs b/tools/DdsMonitor/DdsMonitor.Engine/Ui/GridSettings.cs
index 192a53f..c02dd53 100644
--- a/tools/DdsMonitor/DdsMonitor.Engine/Ui/GridSettings.cs
+++ b/tools/DdsMonitor/DdsMonitor.Engine/Ui/GridSettings.cs
@@ -1,5 +1,3 @@
-using System;
-using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
diff --git a/tools/DdsMonitor/DdsMonitor.Plugins.ECS/DdsMonitor.Plugins.ECS.csproj b/tools/DdsMonitor/DdsMonitor.Plugins.ECS/DdsMonitor.Plugins.ECS.csproj
index 3321d60..6cb5672 100644
--- a/tools/DdsMonitor/DdsMonitor.Plugins.ECS/DdsMonitor.Plugins.ECS.csproj
+++ b/tools/DdsMonitor/DdsMonitor.Plugins.ECS/DdsMonitor.Plugins.ECS.csproj
@@ -1,16 +1,12 @@
- net8.0
+ net10.0
enable
enable
false
-
-
-
-
diff --git a/tools/DdsMonitor/DdsMonitor.Plugins.FeatureDemo/DdsMonitor.Plugins.FeatureDemo.csproj b/tools/DdsMonitor/DdsMonitor.Plugins.FeatureDemo/DdsMonitor.Plugins.FeatureDemo.csproj
index 3321d60..6cb5672 100644
--- a/tools/DdsMonitor/DdsMonitor.Plugins.FeatureDemo/DdsMonitor.Plugins.FeatureDemo.csproj
+++ b/tools/DdsMonitor/DdsMonitor.Plugins.FeatureDemo/DdsMonitor.Plugins.FeatureDemo.csproj
@@ -1,16 +1,12 @@
- net8.0
+ net10.0
enable
enable
false
-
-
-
-
diff --git a/tools/DdsMonitor/README.md b/tools/DdsMonitor/README.md
index c2e41d0..8e6bb8c 100644
--- a/tools/DdsMonitor/README.md
+++ b/tools/DdsMonitor/README.md
@@ -242,14 +242,14 @@ To scan a different set of assembly directories for a single launch **without ov
```
# Scan a single directory
-DdsMonitor.exe --AppSettings:TopicSources:0="C:\MyApp\bin\Debug\net8.0"
+DdsMonitor.exe --AppSettings:TopicSources:0="C:\MyApp\bin\Debug\net10.0"
# Scan two directories
-DdsMonitor.exe --AppSettings:TopicSources:0="C:\MyApp\bin\Debug\net8.0" ^
- --AppSettings:TopicSources:1="C:\SharedTopics\bin\Release\net8.0"
+DdsMonitor.exe --AppSettings:TopicSources:0="C:\MyApp\bin\Debug\net10.0" ^
+ --AppSettings:TopicSources:1="C:\SharedTopics\bin\Release\net10.0"
# Point at a specific DLL instead of a whole directory
-DdsMonitor.exe --AppSettings:TopicSources:0="C:\MyApp\bin\Debug\net8.0\MyTopics.dll"
+DdsMonitor.exe --AppSettings:TopicSources:0="C:\MyApp\bin\Debug\net10.0\MyTopics.dll"
```
When `--AppSettings:TopicSources` is non-empty:
@@ -301,8 +301,8 @@ Lists directories that DDS Monitor scans for DLL assemblies containing DDS topic
**File structure:** a JSON array of directory paths (scanning finds every `.dll` in the directory):
```json
[
- "C:\\MyApp\\bin\\Debug\\net8.0",
- "C:\\SharedTopics\\bin\\Release\\net8.0"
+ "C:\\MyApp\\bin\\Debug\\net10.0",
+ "C:\\SharedTopics\\bin\\Release\\net10.0"
]
```