Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d05fbe7
Initial plan
Copilot Feb 23, 2026
09a3696
Start CDT.Comparison.Benchmarks project with 6 libraries
Copilot Feb 23, 2026
3a855af
Add base scaffold + CDT.NET baseline benchmark
Copilot Feb 23, 2026
7af0daf
Add Triangle.NET adapter and benchmark methods
Copilot Feb 23, 2026
66176b0
Add NetTopologySuite adapter and benchmark methods
Copilot Feb 23, 2026
8852bb1
Add Poly2Tri.NetStandard adapter and benchmark methods
Copilot Feb 23, 2026
70d9a78
Add artem-ogre/CDT C++ wrapper and benchmark methods
Copilot Feb 23, 2026
38ab62b
Add .gitignore for native build artifacts, remove committed build dir
Copilot Feb 23, 2026
974b556
Add Spade Rust wrapper, benchmark methods, and README
Copilot Feb 23, 2026
3cab3ec
Pin artem-ogre/CDT to tag 1.4.4 for reproducible builds
Copilot Feb 23, 2026
fd712ab
Add benchmark results to README; remove CodeQL symlink from git
Copilot Feb 23, 2026
9d6d4ae
Add Windows support, cross-platform native build targets, and missing…
Copilot Feb 23, 2026
7d02431
Document Poly2Tri coordinate-precision limitation causing low triangl…
Copilot Feb 23, 2026
899c222
Remove stray test Program.cs from repo root
Copilot Feb 23, 2026
bdc1923
Remove Poly2Tri; add CGAL C++ wrapper (system-installed CGAL via find…
Copilot Feb 23, 2026
6270015
CGAL 6.1.1 library ZIP + minimal Boost via per-lib ZIPs; Windows CI w…
Copilot Feb 23, 2026
217771c
Add boost/detail to Boost sub-library fetch list (fixes CI missing in…
Copilot Feb 23, 2026
1eda585
Add boost/array to Boost sub-library fetch list (fixes CI on both pla…
Copilot Feb 23, 2026
6e9f891
Remove comparison-benchmarks.yml after confirming Windows + Linux CI …
Copilot Feb 23, 2026
84eac58
Update benchmark results with fresh CGAL run (Linux, .NET 10.0.2)
Copilot Feb 23, 2026
d53571b
Fix native build skip: inline Condition in Target; add CleanNativeWra…
Copilot Feb 23, 2026
65a7073
Exclude CDT.Comparison.Benchmarks from CI/CD build pipeline
Copilot Feb 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,15 @@ jobs:
8.0.x
10.0.x

# Windows: restore full solution (includes Windows-only CDT.Viz)
# Windows: restore cross-platform + Windows-only projects (CDT.Viz targets Windows only)
# CDT.Comparison.Benchmarks is excluded: its native cmake/cargo build is too slow for CI
- name: Restore dependencies
if: runner.os == 'Windows'
run: dotnet restore
run: |
dotnet restore src/CDT.Core/CDT.Core.csproj
dotnet restore test/CDT.Tests/CDT.Tests.csproj
dotnet restore benchmark/CDT.Benchmarks/CDT.Benchmarks.csproj
dotnet restore viz/CDT.Viz/CDT.Viz.csproj

# Linux: restore only cross-platform projects (CDT.Viz targets Windows only)
- name: Restore dependencies
Expand All @@ -50,10 +55,15 @@ jobs:
dotnet restore src/CDT.Core/CDT.Core.csproj
dotnet restore test/CDT.Tests/CDT.Tests.csproj

# Windows: build full solution
# Windows: build cross-platform + Windows-only projects
# CDT.Comparison.Benchmarks is excluded: its native cmake/cargo build is too slow for CI
- name: Build
if: runner.os == 'Windows'
run: dotnet build --no-restore -c Release
run: |
dotnet build --no-restore -c Release src/CDT.Core/CDT.Core.csproj
dotnet build --no-restore -c Release test/CDT.Tests/CDT.Tests.csproj
dotnet build --no-restore -c Release benchmark/CDT.Benchmarks/CDT.Benchmarks.csproj
dotnet build --no-restore -c Release viz/CDT.Viz/CDT.Viz.csproj

# Linux: build only cross-platform projects
- name: Build
Expand All @@ -62,10 +72,10 @@ jobs:
dotnet build --no-restore -c Release src/CDT.Core/CDT.Core.csproj
dotnet build --no-restore -c Release test/CDT.Tests/CDT.Tests.csproj

# Windows: test full solution
# Windows: test CDT.Tests only (CDT.Comparison.Benchmarks excluded from CI build)
- name: Test
if: runner.os == 'Windows'
run: dotnet test --no-build -c Release --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=${{ github.workspace }}/coverage/coverage.cobertura.xml
run: dotnet test --no-build -c Release --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=${{ github.workspace }}/coverage/coverage.cobertura.xml test/CDT.Tests/CDT.Tests.csproj

# Linux: test only CDT.Tests (CDT.Viz has no tests; benchmark is not a test project)
- name: Test
Expand Down Expand Up @@ -110,11 +120,12 @@ jobs:
with:
fetch-depth: 0 # Required for SourceLink

# Only CDT.Core is needed for pack; CDT.Comparison.Benchmarks is excluded
- name: Restore dependencies
run: dotnet restore
run: dotnet restore src/CDT.Core/CDT.Core.csproj

- name: Build
run: dotnet build --no-restore -c Release
run: dotnet build --no-restore -c Release src/CDT.Core/CDT.Core.csproj

- name: Pack
shell: pwsh
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ _ReSharper*/
# BenchmarkDotNet
BenchmarkDotNet.Artifacts/

# Native build artifacts
benchmark/CDT.Comparison.Benchmarks/native/cdt_wrapper/build/
benchmark/CDT.Comparison.Benchmarks/native/cgal_wrapper/build/
benchmark/CDT.Comparison.Benchmarks/native/spade_wrapper/target/

# OS generated files
.DS_Store
.DS_Store?
Expand All @@ -69,3 +74,5 @@ lcov.info
# Temp files
*.tmp
*.temp
_codeql_detected_source_root
Program.cs
1 change: 1 addition & 0 deletions CDT.NET.slnx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Solution>
<Folder Name="/benchmark/">
<Project Path="benchmark/CDT.Benchmarks/CDT.Benchmarks.csproj" />
<Project Path="benchmark/CDT.Comparison.Benchmarks/CDT.Comparison.Benchmarks.csproj" />
</Folder>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
Expand Down
157 changes: 157 additions & 0 deletions benchmark/CDT.Comparison.Benchmarks/CDT.Comparison.Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<!-- Exclude native/ from all MSBuild default SDK globs.
Without this, .resx files inside Boost's downloaded sources
(e.g., boost_math .NET examples) get picked up as EmbeddedResource
items and cause MSB3822 build errors. -->
<PropertyGroup>
<DefaultItemExcludes>$(DefaultItemExcludes);native\**</DefaultItemExcludes>
</PropertyGroup>

<!-- CDT.NET (baseline) -->
<ItemGroup>
<ProjectReference Include="..\..\src\CDT.Core\CDT.Core.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
<!-- Triangle.NET: classic robust CDT, supports constrained edges via Segments -->
<PackageReference Include="Unofficial.Triangle.NET" Version="0.0.1" />
<!-- NetTopologySuite: conforming CDT (may insert Steiner points) -->
<PackageReference Include="NetTopologySuite" Version="2.6.0" />
</ItemGroup>

<!-- Copy test input files so benchmarks can find them at runtime -->
<ItemGroup>
<Content Include="..\..\test\CDT.Tests\inputs\*.txt"
CopyToOutputDirectory="PreserveNewest"
Link="inputs\%(Filename)%(Extension)" />
</ItemGroup>

<!--
═══════════════════════════════════════════════════════════════════════════
Native wrapper configuration (artem-ogre/CDT C++, CGAL C++, Spade Rust)

Requirements
C++ wrappers: cmake ≥ 3.20, a C++17 compiler, internet access (FetchContent)
Rust wrapper: cargo / rustup, internet access (crates.io)

Output filename conventions (all end up in $(OutputPath)):
Windows : cdt_wrapper.dll / cgal_wrapper.dll / spade_wrapper.dll
macOS : libcdt_wrapper.dylib / libcgal_wrapper.dylib / libspade_wrapper.dylib
Linux : libcdt_wrapper.so / libcgal_wrapper.so / libspade_wrapper.so
═══════════════════════════════════════════════════════════════════════════
-->
<PropertyGroup>
<_CdtNativeDir>$(MSBuildThisFileDirectory)native/cdt_wrapper</_CdtNativeDir>
<_CdtBuildDir>$(_CdtNativeDir)/build</_CdtBuildDir>
<_CgalNativeDir>$(MSBuildThisFileDirectory)native/cgal_wrapper</_CgalNativeDir>
<_CgalBuildDir>$(_CgalNativeDir)/build</_CgalBuildDir>
<_SpadeNativeDir>$(MSBuildThisFileDirectory)native/spade_wrapper</_SpadeNativeDir>
<_SpadeReleaseDir>$(_SpadeNativeDir)/target/release</_SpadeReleaseDir>

<!-- lib prefix: empty on Windows, "lib" everywhere else -->
<_NativeLibPrefix Condition="'$(OS)' != 'Windows_NT'">lib</_NativeLibPrefix>

<!-- extension: .dll on Windows, .dylib on macOS, .so on Linux -->
<_NativeLibExt Condition="'$(OS)' == 'Windows_NT'">.dll</_NativeLibExt>
<_NativeLibExt Condition="$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))">.dylib</_NativeLibExt>
<_NativeLibExt Condition="'$(_NativeLibExt)' == ''">.so</_NativeLibExt>

<!-- Source-side paths (in native/*/build or target/) -->
<_CdtLibFile>$(_CdtBuildDir)/$(_NativeLibPrefix)cdt_wrapper$(_NativeLibExt)</_CdtLibFile>
<_CgalLibFile>$(_CgalBuildDir)/$(_NativeLibPrefix)cgal_wrapper$(_NativeLibExt)</_CgalLibFile>
<_SpadeLibFile>$(_SpadeReleaseDir)/$(_NativeLibPrefix)spade_wrapper$(_NativeLibExt)</_SpadeLibFile>
</PropertyGroup>

<!-- ── artem-ogre/CDT C++ wrapper ──────────────────────────────────────── -->

<!-- Friendly error when cmake is not on PATH (shared by both C++ wrappers).
BeforeTargets means this is also skipped when its owning targets are
skipped via Condition (i.e. when the output libs already exist). -->
<Target Name="CheckCmake" BeforeTargets="BuildCdtNative;BuildCgalNative">
<Exec Command="cmake --version"
IgnoreExitCode="true"
ConsoleToMSBuild="true"
StandardOutputImportance="Low"
StandardErrorImportance="Low">
<Output TaskParameter="ExitCode" PropertyName="_CmakeExitCode" />
</Exec>
<Error Condition="'$(_CmakeExitCode)' != '0'"
Text="cmake was not found on PATH. It is required to build the C++ wrappers. Install CMake from https://cmake.org/download/ and ensure it is on your PATH." />
</Target>

<!--
IMPORTANT: $(OutputPath) is empty at PropertyGroup evaluation time in SDK-style
projects, so the output lib paths must be inlined directly in Condition attributes
(which are evaluated at target-execution time when $(OutputPath) is fully resolved).

Condition="!Exists('$(OutputPath)...')" means:
• First build (or after `dotnet clean`): output lib is missing → run cmake/cargo.
The BeforeTargets check targets (CheckCmake/CheckCargo) also run.
• Every subsequent `dotnet build`: output lib already in output dir → entire
target AND its BeforeTargets prerequisites are skipped — no cmake or cargo invoked.
The cmake/cargo build dirs (native/*/build, native/*/target) are NOT cleaned by
`dotnet clean`, so a rebuild after clean is fast (only re-links if needed).
-->
<Target Name="BuildCdtNative" BeforeTargets="Build"
Condition="!Exists('$(OutputPath)$(_NativeLibPrefix)cdt_wrapper$(_NativeLibExt)')">
<MakeDir Directories="$(_CdtBuildDir)" />
<Exec Command="cmake -S &quot;$(_CdtNativeDir)&quot; -B &quot;$(_CdtBuildDir)&quot; -DCMAKE_BUILD_TYPE=Release" />
<Exec Command="cmake --build &quot;$(_CdtBuildDir)&quot; --config Release" />
<MakeDir Directories="$(OutputPath)" />
<Copy SourceFiles="$(_CdtLibFile)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true" />
</Target>

<!-- ── CGAL C++ wrapper ─────────────────────────────────────────────────── -->

<Target Name="BuildCgalNative" BeforeTargets="Build"
Condition="!Exists('$(OutputPath)$(_NativeLibPrefix)cgal_wrapper$(_NativeLibExt)')">
<MakeDir Directories="$(_CgalBuildDir)" />
<Exec Command="cmake -S &quot;$(_CgalNativeDir)&quot; -B &quot;$(_CgalBuildDir)&quot; -DCMAKE_BUILD_TYPE=Release" />
<Exec Command="cmake --build &quot;$(_CgalBuildDir)&quot; --config Release" />
<MakeDir Directories="$(OutputPath)" />
<Copy SourceFiles="$(_CgalLibFile)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true" />
</Target>

<!-- ── Spade Rust wrapper ───────────────────────────────────────────────── -->

<!-- Friendly error when cargo is not on PATH -->
<Target Name="CheckCargo" BeforeTargets="BuildSpadeNative">
<Exec Command="cargo --version"
IgnoreExitCode="true"
ConsoleToMSBuild="true"
StandardOutputImportance="Low"
StandardErrorImportance="Low">
<Output TaskParameter="ExitCode" PropertyName="_CargoExitCode" />
</Exec>
<Error Condition="'$(_CargoExitCode)' != '0'"
Text="cargo was not found on PATH. It is required to build the Spade Rust wrapper. Install Rust from https://rustup.rs/ and ensure cargo is on your PATH." />
</Target>

<Target Name="BuildSpadeNative" BeforeTargets="Build"
Condition="!Exists('$(OutputPath)$(_NativeLibPrefix)spade_wrapper$(_NativeLibExt)')">
<Exec Command="cargo build --release --manifest-path &quot;$(_SpadeNativeDir)/Cargo.toml&quot;" />
<MakeDir Directories="$(OutputPath)" />
<Copy SourceFiles="$(_SpadeLibFile)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true" />
</Target>

<!-- ── Clean hook ───────────────────────────────────────────────────────── -->

<!-- Remove the native libs from the output dir when `dotnet clean` runs,
so the next build will re-copy (and re-compile if needed) them. -->
<Target Name="CleanNativeWrappers" AfterTargets="Clean">
<Delete Files="$(OutputPath)$(_NativeLibPrefix)cdt_wrapper$(_NativeLibExt);
$(OutputPath)$(_NativeLibPrefix)cgal_wrapper$(_NativeLibExt);
$(OutputPath)$(_NativeLibPrefix)spade_wrapper$(_NativeLibExt)" />
</Target>

</Project>
Loading