Conversation
Golden tests byte-compare LF interpreter output against .expected files; without an attributes file, Git for Windows' default autocrlf would check every golden out as CRLF. Renormalizes the two vendored CRLF files. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…`long` On Windows `long` is 32 bits. lang's Word::i, the engine's i64/u64, the ext_vector_type lane types in shared/tzpl_simd.hpp, the voicer header's standalone alias, and the bridge/app node/control/tap IDs were all `long` and would silently truncate. All are now std::int64_t / std::uint64_t (the same type in every namespace, which also removes the old long-vs-long-long split between engine and lang). isize is std::ptrdiff_t (no ssize_t in the MSVC CRT). The non-Apple SIMD branch gains the u32xN types the Apple branch already had. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…e golden set Map/Set iteration order (and so printed output) hashed through std::hash, which differs between libc++, libstdc++ and the MSVC STL, and sinpi/cospi/ tanpi/exp10 mapped to Apple libm extensions on macOS but sin(x*pi) elsewhere. Windows would have added a third set of golden overrides. - lang/src/stable_hash.hpp: ints hash to themselves and floats to their bits (libc++'s rules, so existing macOS output is preserved); strings use FNV-1a with a splitmix64 finalizer. Symbols hash by name, which also makes the hash(Symbol) builtin deterministic across runs. - shared/tzpl_sinpi.hpp: exact quadrant reduction, then one std::sin, so integer/half-integer arguments give exact 0/+-1 on every platform. Used by the interpreter, the synthdef constant folder, generated plugin code, and the 2-wide SIMD fallbacks. M_PI/M_E users switch to <numbers> (MSVC has no M_PI without _USE_MATH_DEFINES). - shared/tzpl_fft.hpp: the portable radix-2 path is now the only path; the vDSP branches and the three Accelerate links are gone. - Golden files: 8 macOS goldens regenerated (map order, FFT signed zeros); the 14 .expected.linux overrides shrink to 3 residual libm-drift cases. run_tests.sh now selects .expected.<os> from uname (linux / windows). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…known paths
New shared/tzpl_platform static library (linked through the shared
INTERFACE target):
- tzpl_dynlib.hpp: dlopen/dlsym/dlclose/dladdr on POSIX, LoadLibraryExW/
GetProcAddress/FreeLibrary/GetModuleHandleExW on Windows. Replaces the
raw dl* calls in the engine loader, the synthdef compiler, and the FFI
integration test.
- tzpl_process.hpp: runProcess(argv, onLine) via posix_spawnp or
CreateProcessW, no shell. The plugin compile/link steps now pass argv
vectors, which also fixes paths with spaces on every platform (the old
string concatenation quoted nothing), and works from a GUI-subsystem
process where _popen does not.
- tzpl_paths.hpp: executablePath, distRoot (the folder holding modules/),
homeDir, userConfigDir, defaultBuildDir, and kPathListSep (';' on
Windows, since drive letters contain ':'). module_paths.cpp, both
main.cpp REPL history paths, -I / $TZPL_PATH splitting, and the app's
user config location use these.
synthdef_compile_link.cpp: plugin compiler resolution order is $TZPL_CC,
the toolchain bundled in the distribution folder (Windows), the baked-in
compiler if it still exists, then PATH; headers are staged from
$TZPL_SHARED_INCLUDE, the distribution's include/, or the source tree
(previously only the source tree, which does not exist on a user's
machine); Sleef staging also looks in the distribution folder; a
once-per-process sweep prunes revisions an earlier session could not
delete; .dll is the plugin extension on Windows. The --test stage macros
are #ifndef-overridable for staged bring-up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…ders in the distribution - lang/src/builtins_io.cpp: fileExists/isDirectory/fileSize/listDir/ makeDir/removeFile/renameFile/currentDir are std::filesystem now (dirent/stat/mkdir/unlink/getcwd do not exist in the MSVC CRT). Paths cross the boundary as UTF-8 via tzpl::pathFromUtf8/pathToUtf8, and currentDir stays '/'-separated on every platform, the form std.path expects. New tempDir() builtin; the four scratch-dir tests use it instead of a literal /tmp and mask the directory in printed errors. - shared/tzpl_plugin_abi.h: TZPL_PLUGIN_EXPORT (__declspec(dllexport) on Windows, default visibility elsewhere), emitted on all seven exported symbols by both the C++ and the synthc code generators. A Windows DLL exports nothing unless told to. - The dist component installs shared/*.h* as include/ (and Sleef on Linux) beside modules/. Runtime synthdef compilation copied headers from the absolute source path baked in at configure time, so a shipped DMG only worked on machines that had the source tree at that path. make_dist_dmg.sh now refuses a stage without the headers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
CMake: a WIN32 block in the root (clang-cl host toolchain, /MD runtime, /utf-8 /bigobj /EHsc, NOMINMAX etc., 16 MB stack, TZPL_PLUGIN_TOOLCHAIN_DIR and TZPL_BUNDLE_TOOLCHAIN_DIR cache vars, a dist target that zips via packaging/make_dist_win.ps1); RtAudio with WASAPI + DirectSound; Sleef on every non-Apple platform (static for the clang-cl host) plus an ExternalProject build of Sleef with the llvm-mingw plugin toolchain, installed as lib/libsleef.a + include/sleef.h in the dist; libsndfile via a CMake config package or a static FetchContent build; oscpack's vendored win32 sockets; GNU-style -O/-W/-ffast-math options guarded on CMAKE_CXX_COMPILER_FRONTEND_VARIANT (clang-cl gets /clang:-ffast-math); tzpl.exe and Tzopilotl.exe install at the distribution root beside modules/; the headless app tests build with either GUI app. Sources (all under _WIN32, POSIX paths unchanged): MMCSS "Pro Audio" + TIME_CRITICAL for worker silos; WASAPI backend selection; rand_s seeding (no extra library, the header is compiled into plugins); CLI console setup (binary LF stdout, UTF-8 code page, VT processing for colours) and an application manifest (UTF-8 active code page, DPI awareness); steady_clock for the GC deadline clock; _create_locale/_strtod_l; a linenoise stand-in over fgets; Winsock in the OSC server; the app's print capture on _pipe + PeekNamedPipe and its 8 MB evaluation thread on _beginthreadex; sleep_for instead of usleep. shared/tzpl_abi_layout_check.c prints sizeof/alignof of every ABI struct so the clang-cl host and mingw plugin builds can be diffed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
- packaging/make_toolchain_subset.ps1 trims llvm-mingw (llvm-mingw-20260826-ucrt-x86_64, LLVM 23.1) to what plugin compilation needs and self-checks by building a DLL with PATH cleared; packaging/make_dist_win.ps1 assembles Tzopilotl-<ver>-win64.zip from the dist stage: bundled toolchain/, app-local VC++ runtime DLLs, an import check mirroring the DMG script's otool check. Unsigned (no certificate). - .github/workflows/tests.yml: windows-core job (clang-cl + Ninja on windows-latest, cached llvm-mingw, ABI layout diff between the two compilers, lang suite under Git Bash, synthdef --test, doc/config tests, JUCE self-test), continue-on-error until it has a green streak. - docs/WINDOWS.md (requirements, build, tests, audio backends, runtime plugin compilation, distribution, known gaps), dev/windows/README.md (first-build checklist), and platform statements in README, CLAUDE.md files, the site pages (which still claimed macOS only), Getting Started, the shortcut table (Ctrl for Cmd), packaging/README.txt, THIRD_PARTY_NOTICES.md, NEWS.md, and the release skill. - toolchainCommand prefers llvm-mingw's target-prefixed driver. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Syntax-checking all non-JUCE sources for x86_64-w64-windows-gnu (real Windows/UCRT headers) and building a generated plugin into a DLL found: - synthdef_hash.hpp: two constrained hash_combine overloads became functionally identical under LLP64 (size_t == uint64_t == unsigned long long) and Clang rejected the redefinition. One std::integral template replaces the per-type set. - tzpl_random.hpp (both copies): _CRT_RAND_S must precede the first <stdlib.h> in the translation unit, which generated plugin code (starting with tzpl_plugin_abi.h) cannot guarantee; rand_s is declared directly. - tzpl_client_interface.cpp: std::filesystem::path::c_str() is wide on Windows; the loader now passes UTF-8 to loadOneDef. - plugin_tags.cpp: fnmatch(3) does not exist on Windows; a small glob matcher (checked against fnmatch on a test matrix) replaces it, and the store's default location goes through tzpl::userConfigDir. Sleef 3.7 cross-builds for the mingw target, and the resulting plugin DLL exports load/tzpl_abi_version and imports only KERNEL32 and the UCRT api-sets. dev/windows/README.md records the procedure and what remains for a real Windows machine. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…tent) Its cmake_minimum_required(3.1.2) is rejected by CMake 4.x, which the windows-latest runner has; CMAKE_POLICY_VERSION_MINIMUM=3.5 scoped to the sub-build. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
With the MSVC toolchain the header pulls in headers that open namespace std; nested inside simd_compat that became simd_compat::std and shadowed ::std for every std:: call in the SIMD wrappers (first clang-cl build error on the windows-core job). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
CMake already embeds a default manifest for MSVC-style links; the .rc copy produced a duplicate RT_MANIFEST resource at link time (windows-core run 3). Listing the .manifest as a source merges it instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
open_memstream and setenv are POSIX-only (windows-core run 4 stopped on them at step 394/404, after every library and the tzpl/engine/compiler executables had linked). TestPrintCapture wraps a memstream on POSIX and a delete-on-close temp file on Windows. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
juce_add_gui_app links with /SUBSYSTEM:WINDOWS, so the CRT wants WinMain (windows-core run 5: the one remaining link error at step 403/404). It attaches the parent console when stdio was not redirected, converts the wide command line to UTF-8, and forwards to the shared entry point. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
long double is 16 bytes under mingw and 8 under MSVC; it was an informational row, not an ABI type, but it failed the comparison (run 6, the first run in which the whole tree built on Windows). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Run 7 built everything and passed the ABI check; every golden test then failed with exit code 126 (cannot execute) and the runner discards stderr. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Run 8: tzpl.exe would not start ('side-by-side configuration is
incorrect'). The fragment CMake merges into its default manifest now
carries only the activeCodePage and dpiAwareness settings, the form
Microsoft documents; the diagnostic step dumps the embedded manifest.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
First Windows golden run (run 9): 437 of 475 pass. The errors/ goldens compare stderr with the repo root stripped; the interpreter printed native paths (backslashes, drive letter) where bash knows /d/a/.... Display paths are generic_string() now and the runner normalizes/strips the native root on Windows. The suite runs --verbose in CI until the remaining diffs are understood. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
- parseInt: writeOptionIntResult(vm, dst, parseIntStrict(..., v), v) read v in the same argument list that filled it. Argument evaluation order is unspecified; Clang goes left-to-right on Itanium targets and right-to- left on the MSVC ABI, so every parseInt (and every `try` test built on it) returned garbage on Windows. Sequenced into two statements. - formatFloat: every NaN prints as "nan". to_chars spells the sign and MSVC's adds "(ind)", and whether 0.0/0.0 sets the sign bit differs between x86 and ARM, so output was platform-dependent. - Integer / and %: defined results for x/0, x%0 and INT64_MIN/-1 (the ARM64 hardware results the language has always shipped: 0, x, wrap) instead of C undefined behaviour, which traps on x86 (the qa/bug_int_div_zero test crashed on Windows and would on x86 Linux). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Run 11: 474 of 475 golden tests pass on Windows; the last one is the complex exp() libm difference that Linux already overrides, same output. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Run 12: all 475 golden tests pass on Windows; the plugin pipeline then compiled but failed to link (undefined __declspec(dllimport) Sleef_powf4_u10): Sleef's header declares dllimport on Windows unless SLEEF_STATIC_LIBS is defined, and both sides link it statically. Verified by linking bank_voicer (which calls Sleef pow) with the cross toolchain. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
windows-core is green: full clang-cl build, ABI layout diff, 475/475 golden tests, synthdef-compiler --test through the llvm-mingw plugin pipeline, doc/config tests, JUCE self-test. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Builds the llvm-mingw subset with packaging/make_toolchain_subset.ps1, runs the dist target (packaging/make_dist_win.ps1), and uploads Tzopilotl-<version>-win64.zip as an artifact (14-day retention) after the test steps, so testers can try audio on real hardware. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…toolchain The first CI run of make_toolchain_subset.ps1 hit a PowerShell parse error (a bare comma is the array separator) and the step did not check its exit code, so the zip shipped without toolchain/. The dist script now errors when a toolchain dir is configured but missing. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
No lld.exe (only ld.lld.exe); the drivers are launchers for clang-<N>.exe; copy only the DLLs clang and lld import instead of all of bin\ (which holds lldb, python, OpenMP and ASan libraries nothing here needs). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…lvm-mingw Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
…erShell Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
They select libc++, compiler-rt, libunwind and lld; without them the trimmed driver searched for libstdc++ headers and the self-check's probe could not find <cmath>. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6
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.
Windows (x64) support for all components: clang-cl host binaries, a bundled llvm-mingw toolchain for runtime-compiled synthdef plugins, WASAPI/DirectSound audio, OSC, and the JUCE app. See
docs/WINDOWS.mdfor the design anddev/windows/README.mdfor the first-build checklist.Draft: opened to run the new
windows-coreCI job (continue-on-error). macOS and Linux suites are green; every Windows code path was cross-checked with the llvm-mingw cross compiler from macOS, but nothing has run on a Windows machine yet.Also in this branch, on every platform: platform-independent value hashing and
sinpifamily (one golden set), plugin headers shipped in the distribution folder (fixes runtime synthdef compilation on machines without the source tree), and argv-based plugin compile/link (paths with spaces).🤖 Generated with Claude Code
https://claude.ai/code/session_012dpZrs6vKijjsnpWRKtBJ6