TINS.Native.FFTW.Desktop
1.1.0
dotnet add package TINS.Native.FFTW.Desktop --version 1.1.0
NuGet\Install-Package TINS.Native.FFTW.Desktop -Version 1.1.0
<PackageReference Include="TINS.Native.FFTW.Desktop" Version="1.1.0" />
<PackageVersion Include="TINS.Native.FFTW.Desktop" Version="1.1.0" />
<PackageReference Include="TINS.Native.FFTW.Desktop" />
paket add TINS.Native.FFTW.Desktop --version 1.1.0
#r "nuget: TINS.Native.FFTW.Desktop, 1.1.0"
#:package TINS.Native.FFTW.Desktop@1.1.0
#addin nuget:?package=TINS.Native.FFTW.Desktop&version=1.1.0
#tool nuget:?package=TINS.Native.FFTW.Desktop&version=1.1.0
tins-lib-native
Native (C/C++) dependency builds for TINS-Library
(TINS.Core), split into their own repo since they change far less often than the managed library
itself.
Packages are split into two license-separated families, not just by RID — see "Why two package families" below before assuming this is one native package per RID:
TINS.Native.<rid>(win-x64,linux-x64,osx-x64,osx-arm64) — BSD-3-Clause. OpenBLAS plus the PocketFFT shim (pocketfft-shim/, BSD-3-Clause, implemented and confirmed green in real CI). This is the default package every consumer adds alongsideTINS.Core. A fifth package,TINS.Native.Desktop, is a meta-package with no native content of its own that depends on all four RID packages, for a consumer that wants every desktop RID at once (e.g. a cross-platform test project).TINS.Native.FFTW.<rid>— GPL-2.0-or-later, strictly opt-in. FFTW binaries only. A consumer adds this in addition to the core package only if they specifically need FFTW (e.g. viaTINS.Core'sFFTW<T>.Plan) and knowingly accepts the GPL obligation that comes with it for their own application.
Each package contains only runtimes/<rid>/native/* content, no managed assembly.
Why two package families
FFTW is GPL-2.0-or-later. OpenBLAS and PocketFFT are both BSD-3-Clause. Bundling all three into one package (the original design) would mean every consumer's application inherits GPL obligations just from adding "the native package," whether or not they actually use FFTW — a real, not hypothetical, licensing trap once this ships on nuget.org. Splitting FFTW into its own package puts that decision where it belongs: on the consumer, at the point they explicitly reference it. This is the same pattern projects like FFmpeg use to ship GPL and LGPL builds as separate artifacts.
Scope (current)
| Library | win-x64 | linux-x64 | osx-x64 | osx-arm64 | Package | License |
|---|---|---|---|---|---|---|
OpenBLAS (libopenblas) |
CI-built (vcpkg) | CI-built (vcpkg) | CI-built (vcpkg) | CI-built (vcpkg) | TINS.Native.<rid> |
BSD-3-Clause |
| PocketFFT | CI-built (bespoke CMake) | CI-built (bespoke CMake) | CI-built (bespoke CMake) | CI-built (bespoke CMake) | TINS.Native.<rid> |
BSD-3-Clause |
FFTW (libfftw3-3, libfftw3f-3) |
CI-built (vcpkg) | CI-built (vcpkg) | CI-built (vcpkg) | CI-built (vcpkg) | TINS.Native.FFTW.<rid> |
GPL-2.0-or-later, opt-in |
All four RIDs are built from source in CI via vcpkg (see vcpkg.json,
.github/workflows/ci.yml) — both FFTW and OpenBLAS come from the same manifest/vcpkg install per
RID; the license split happens at staging/packing time (scripts/stage-native.ps1 -Component Core|Fftw), not in what vcpkg builds. osx-x64 was excluded from 2026-09-24 to
2026-10-15 over a believed GitHub-plan restriction on its runner that turned out to be wrong (or no
longer true) — re-checked live, re-enabled, and confirmed working.
TINS.Core used to also depend on two custom native wrappers with no tracked source anywhere
(libeigenexports for SVD/PCA, libdpss for multitaper analysis); both were replaced with pure
managed code directly in TINS.Core (SVD/PCA now use the OpenBLAS.SGESVD call already covered by
this repo; DPSS is a managed tridiagonal-eigensolver implementation), so there was never a need to
build or vendor them here.
win-arm64 and linux-arm64 are follow-ups, not yet in the CI matrix. GitHub-hosted native ARM
runner availability is no longer the blocker — confirmed available (2026-01-29, private-repo GA,
Free-plan eligible) — but they're deliberately deferred for now (2026-09-24): not currently useful
enough to prioritize, revisit if that changes.
Known limitations
OpenBLAS is built single-target, not dynamic-arch. It's compiled once per RID, targeting
whatever CPU instruction set the build machine (a GitHub Actions runner) supports — currently up
to AVX2/AVX-512 on x64. That instruction set is baked directly into the binary with no runtime
fallback. If your actual CPU doesn't support it, calling into OpenBLAS won't degrade gracefully or
throw a normal .NET exception — it will crash the process with an illegal-instruction fault
(SIGILL) the first time an unsupported instruction executes. This is unlikely to matter on
mainstream desktop/laptop/cloud hardware from the last several years, but it's a real risk on older
or unusual CPUs, and there's currently no way to detect it ahead of time other than actually running
the affected code path.
The portable fix is a dynamic-arch build (multiple kernel variants + runtime CPU detection), which
this repo does not currently produce — for Windows specifically it isn't even an option, since
vcpkg's openblas port doesn't offer the dynamic-arch feature for MSVC builds at all
("supports": "!windows | mingw"). If this affects you, please open an issue — it hasn't been
prioritized yet since most users are expected to be on recent Windows or Apple Silicon hardware, but
that assumption hasn't been validated against real-world usage.
Publishing
CI builds and smoke-tests every push/PR and uploads each RID's .nupkg as a workflow artifact.
Pushing a vX.Y.Z release tag additionally publishes every package to
nuget.org via nuget.org's Trusted Publishing
(OIDC) — no long-lived API key stored anywhere. For day-to-day local development, download an
artifact (or pack one yourself, see CLAUDE.md) and drop it into whatever local NuGet feed
folder you use.
Repo layout
vcpkg.json/vcpkg-configuration.json— manifest-mode dependencies (fftw3,openblas,pocketfft) and a pinnedbuiltin-baselinefor reproducible builds. FFTW/OpenBLAS are still built together per RID; the license split happens downstream of vcpkg, not here.pocketfftis an ordinary, unmodified registry dependency, vendoring only the header the shim below builds against.pack/TINS.Native.<rid>/— one minimal native-asset-only.csprojper RID (OpenBLAS + the pocketfft shim, BSD-3-Clause).pack/TINS.Native.FFTW.<rid>/— one minimal native-asset-only.csprojper RID (FFTW only, GPL-2.0-or-later, opt-in).pack/TINS.Native.Desktop/— meta-package depending on all four core RID packages, no native content of its own.pack/TINS.Native.FFTW.Desktop/is the equivalent for the FFTW family.LICENSE/licenses/— this repo's own BSD-3-Clause license, plus vendored upstream license text for FFTW/OpenBLAS/pocketfft (BSD/GPL both require reproducing it in redistributions, not just declaringPackageLicenseExpression), packed into the matching nupkg(s). Seelicenses/README.mdfor exact provenance.pocketfft-shim/— a bespoke CMake project (not a vcpkg overlay port) implementing a thin, P/Invoke-able C ABI around header-only PocketFFT. Implemented and confirmed green in real CI on all four RIDs (export symbols, a standalone functional test harness, and a full .NET P/Invoke round trip), and cross-repo-verified againsttins-lib's own native provider code.scripts/stage-native.ps1— copies vcpkg's build output into a flatruntimes/<rid>/native/staging folder consumed by the pack step, split by-Component Core|Fftwinto the two license families' separate staging roots.scripts/build-pocketfft-shim.ps1— configures/builds/installs the pocketfft shim and copies its output into the same core staging folder as OpenBLAS.smoke/— a small console app with its own corrected native-library resolver (fixes a double-lib-prefix bug present inTINS-Library'sNativeImportResolver.csas of this writing; that fix should be ported back there once this repo's non-Windows packages are proven). CI restores the just-built local core and FFTW packages into this project separately (add, run, remove; then the other) and runs it to prove each package's own shared libraries actually load and resolve symbols in isolation, not just that files exist in the package.
Status
All four RIDs — win-x64, linux-x64, osx-x64, and osx-arm64 — have been built, packed, and
smoke-tested successfully in real CI, with genuine (not placeholder) native binaries, including the
pocketfft shim.
TINS-Library's TINS.Core, on its own main branch, still bundles its own win-x64 natives
directly — that migration (dropping the glob in favor of an explicit TINS.Native.<rid> reference)
exists on a separate tins-lib branch, not yet merged there either.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- TINS.Native.FFTW.linux-x64 (>= 1.1.0)
- TINS.Native.FFTW.osx-arm64 (>= 1.1.0)
- TINS.Native.FFTW.osx-x64 (>= 1.1.0)
- TINS.Native.FFTW.win-x64 (>= 1.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.