Commit graph

185 commits

Author SHA1 Message Date
catbot
06cccc3921 perf: build external cmake deps in parallel
All checks were successful
CI / build-test-release (pull_request) Successful in 9m0s
cmake --build was invoked with no --parallel, so the default Unix
Makefiles generator compiled external deps (DPP, msquic, glslang, …)
one translation unit at a time, leaving all but one core idle.

Pass an explicit --parallel N using hardware_concurrency() so dep
builds use the available cores. An explicit count (not a bare
--parallel) avoids an unbounded make -j fork bomb on the Makefiles
generator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:38:00 +00:00
catbot
0ff9050eb3 fix: line-buffer stdout when redirected so progress/readiness lines flush
All checks were successful
CI / build-test-release (pull_request) Successful in 6m13s
When crafter-build's stdout is not a TTY (redirected to a file or pipe) the
C runtime defaults to full (block) buffering. The progress path is TTY-aware
and the in-place redraw flushes explicitly, but the non-TTY append path
(`[N/M]` lines), Finalize()'s `Built N steps` line and the `-r` server's
`listening on port :N` line all go through block-buffered stdout with no
flush. They accumulate in the buffer and only spill at ~4KB boundaries.

On a normal build this is hidden because the C runtime flushes stdout at
exit. Under `-r` the process never exits — it blocks in its serve loop — so
the trailing buffer is never flushed: a redirected log freezes mid-build (or
sits at 0 bytes) even though the build finished and the server is already
answering. Any tooling that polls the log for `Built …` / `listening …` /
`[N/N]` hangs forever. This is the real cause of the frozen log misdiagnosed
as a build deadlock in #16.

Fix: switch stdout to line buffering at the very top of main(), before any
output, only when stdout is not a terminal. Every `\n` then flushes, so the
markers reach a redirected log immediately. No behaviour change on a TTY.

Kept self-contained in main.cpp using system headers (isatty + setvbuf)
rather than a new Crafter::Progress export: the self-hosting exe build
compiles main.cpp against the installed/cached Crafter.Build module BMIs,
which shadow the freshly built local ones, so a new interface symbol would
not be visible without reinstalling crafter-build first.

Resolves #18

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:42:33 +00:00
catbot
e76f92ae0a fix: scope per-build module-state reset to the config being built
All checks were successful
CI / build-test-release (pull_request) Successful in 6m41s
Build() resets each Module/ModulePartition's per-build `compiled`/`checked`
flags so a reused Configuration re-evaluates mtimes. That reset recursed into
cfg.dependencies — but dependency Configurations are shared across the build
DAG and each is compiled concurrently by its own Build() call.

A parent/sibling's recursive reset could therefore clear a shared dependency's
module `compiled` atomic *after* that dependency's module-compile thread had
set it true and exited, but before an intra-config waiter (its impl, or a
dependent partition) ran compiled.wait(false). The waiter then blocked forever
on a flag nothing would re-signal: the build froze mid-compile, idle, with no
compiler process alive — exactly the hang in issue #16.

Reset only the current configuration's own modules. Every config in the tree
already gets its own Build() call (the per-PcmDir builder registered in
depResults), which resets its own state at the top of that call, sequenced
before its compile threads spawn. Cross-config module state is consulted only
via PCM file mtimes and the depResults futures, never via these flags, so the
narrower reset is correct and removes the data race entirely.

Adds ConcurrentDependencyReset: builds a static-lib dependency fully, then
builds a consumer that depends on it while the dependency is already cached in
depResults (so it is never rebuilt), and asserts the consumer build leaves the
dependency's module `compiled` flag intact. Fails deterministically on the old
recursive reset; passes with the fix.

Resolves #16

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 11:32:46 +00:00
0dd1738e33 added listening output
All checks were successful
CI / build-test-release (push) Successful in 9m58s
2026-05-31 17:23:34 +02:00
47cd50a7d2 fixed build error and file stdpcm lock 2026-05-30 19:28:06 +02:00
catbot
96d1df9233 fix: atomic-rename host-cache PCMs to close concurrent-build race
All checks were successful
CI / build-test-release (pull_request) Successful in 11m50s
Two crafter-build invocations sharing XDG_CACHE_HOME used to clobber each
other's writes to <cache>/<target>-<march>/std.pcm and the
Crafter.Build-*.pcm modules: each LoadProject path wrote directly to the
final path, so a reader could see a half-written file and die with
"malformed or corrupted precompiled file: 'can't skip to bit X from Y'"
(issue #14). Every BuildStdPcm / EnsureCrafterBuildPcms write now goes via
<final>.tmp.<pid>.<seq> and atomic-renames into place; concurrent writers
always see either the old or the new file, never torn bytes. The mingw-on-
Linux std.cppm copy is per-PID for the same reason. Adds a regression test
(ConcurrentCacheRace) that races four LoadProject() calls against a cold
scratch cache — reproduces the race 5/5 without the fix and passes 5/5
with it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 16:36:45 +00:00
603840879d new tests
All checks were successful
CI / build-test-release (push) Successful in 1h4m52s
2026-05-27 19:45:05 +02:00
8de93aaf06 test: drop transport runners (ssh/sshwin/wsl) and the Shell-quoting enum
All checks were successful
CI / build-test-release (pull_request) Successful in 9m56s
With test.toml + ForTarget covering the cross-arch + Windows-on-Linux
cases, the env-var-driven transport runners are dead weight. This commit
removes them and the retired tests that exercised the env-var plumbing:

  - TestRunner::Ssh / SshWin / Wsl factories and their copy/exec/cleanup
    template machinery.
  - TestRunner::Shell enum (Host/Sh/Cmd) and the ShellQuoteSh helper —
    only Host shell quoting is needed once the remote shells are gone.
  - TestRunner::copy / cleanup / remoteDir / argsShell fields.
  - WindowsPathToWsl and the {remote_bundle}/{bin_win}/{bundle_wsl}
    placeholder substitution in RunSingleTest's transport branch.
  - ParseRunnerSpec narrowed from {local, cmd, ssh, sshwin, wsl} to
    {local, cmd} — the override hatch is preserved, just simpler.
  - tests/SshRunner, tests/WindowsViaSsh, tests/QemuUser: these tested
    the CRAFTER_BUILD_RUNNER_<target> → runner plumbing that has been
    replaced by ForTarget. The runner derivation is exercised every
    time CrossArchAarch64 / Wasi / WindowsViaWine runs.
  - tests/UnitLib: ssh/sshwin spec assertions become "throws on bogus
    spec" assertions.

Refs issue #8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 18:07:33 +02:00
dc27c5c204 test: introduce test.toml + target-derived runners alongside existing machinery
Vendors toml++ v3.4.0 as lib/toml.hpp and wires it into Crafter.Build-Test
to parse a declarative test.toml manifest (target/march/mtune/sysroot/
requires/timeout/args/defines). Test discovery now treats project.cpp and
test.toml as mutually exclusive: project.cpp stays the escape hatch for
outer-driver tests, test.toml gives downstream test authors a no-boilerplate
path.

Adds:
- TestRunner::Wine() and TestRunner::ForTarget(cfg) — runner is now derived
  from cfg.target (Local for host, Wine for Windows-on-Linux, wasmtime for
  WASI, qemu-<arch> with QEMU_LD_PREFIX for non-host Linux). The env-var
  override CRAFTER_BUILD_RUNNER_<target> still wins as a power-user escape
  hatch via FromEnv.
- Declarative preconditions: tool:<name>, file:<path>, env:<VAR> are
  evaluated before the build; missing preconditions Skip without paying
  the compile cost.
- Hard-fail-unless-declared: when a derived runner's tool is missing AND
  the test didn't declare 'tool:<that>' in requires, the missing runner
  is a Fail instead of a silent Skip. Surfaces broken cross-arch CI
  config that previously hid as "skipped".
- Multi-target sweep: bare `crafter-build test` (no --target=) now
  iterates every distinct test.toml-declared target plus the host, so
  cross-arch tests run by default without the user needing to know which
  targets exist. `--target=X` bypasses the sweep.

Test struct gains a `requires_` vector so project.cpp users can declare
preconditions too (matching what test.toml writes there).

Existing tests, factories (Ssh/SshWin/Wsl/Cmd), and CRAFTER_BUILD_RUNNER_*
machinery remain intact — this commit only adds; migration and deletion
follow in subsequent commits.

Refs issue #8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 17:57:47 +02:00
f0bdfbee77 fixed mingw warning
All checks were successful
CI / build-test-release (push) Successful in 18m54s
2026-05-27 05:43:56 +02:00
catbot
47b886602a fix: unbreak mingw build of Crafter.Build-Clang
Some checks failed
CI / build-test-release (pull_request) Has been cancelled
Two Windows-only compile errors blocked the mingw cross-compile:

* `<winsock2.h>` transitively includes `<rpc.h>`, which defines
  `#define interface struct`. The file uses `interface` as a loop
  variable name in three for-loops, so on mingw it expanded into
  `for(... struct : ...)` and cascaded into a wall of unrelated parse
  errors. Undefine the macro right after the Windows headers in the
  global module fragment.
* `static_cast<uint16_t>` in the port-probe helper failed because
  mingw's `<stdint.h>` typedefs are in the global module fragment and
  the C-namespace `::uint16_t` isn't anchored into the module purview
  on this toolchain. `import std;` does export `std::uint16_t`, so
  qualify the cast.

Verified by running `crafter-build --target=x86_64-w64-mingw32` end to
end and the full test suite (13 passed, 5 environment-skipped).
2026-05-27 03:15:19 +00:00
catbot
5ac7077dd0 fix external cache race on concurrent builds
Some checks failed
CI / build-test-release (pull_request) Has been cancelled
Two crafter-build invocations resolving to the same external dep both
cloned into <cache>/<name>-<hash>.tmp, corrupting each other's pack
tempfiles. Use a random per-invocation tmp suffix and treat a failed
rename whose destination now exists as the loser-of-the-race case —
discard the local clone and reuse the winner's.
2026-05-27 01:55:29 +00:00
2b7e37e3b9 wasm fixes
Some checks failed
CI / build-test-release (push) Failing after 16m28s
2026-05-26 22:50:08 +02:00
e77d17ba46 fixed stale dep
Some checks failed
CI / build-test-release (push) Failing after 18m7s
2026-05-19 16:53:24 +02:00
b8dc380c33 wasm vfs path fix
Some checks failed
CI / build-test-release (push) Failing after 14m41s
2026-05-19 03:28:27 +02:00
f442caa888 asset changes
Some checks failed
CI / build-test-release (push) Failing after 15m11s
2026-05-19 00:50:06 +02:00
c466d90eec wasm improvements
Some checks failed
CI / build-test-release (push) Failing after 14m16s
2026-05-18 05:23:11 +02:00
dea67ae5aa recursive assets
Some checks failed
CI / build-test-release (push) Failing after 14m17s
2026-05-12 03:44:14 +02:00
03717b5f33 asset compression
Some checks failed
CI / build-test-release (push) Failing after 15m11s
2026-05-12 01:16:40 +02:00
659103a123 external dep lib dir
Some checks failed
CI / build-test-release (push) Failing after 13m55s
2026-05-06 03:59:19 +02:00
d7a9c85ea6 fixes
All checks were successful
CI / build-test-release (push) Successful in 15m14s
2026-05-02 21:08:51 +02:00
de9865b583 shader copy to output
All checks were successful
CI / build-test-release (push) Successful in 15m1s
2026-05-01 19:16:13 +02:00
df9436c51d fixed error shader crash
Some checks failed
CI / build-test-release (push) Has been cancelled
2026-05-01 19:02:14 +02:00
988c1821af LoadProject: extend DLL search path to mingw / libcxx bin dir
All checks were successful
CI / build-test-release (push) Successful in 14m49s
Before LoadLibraryA on the project.dll, point Windows's loader at the
directory we already know holds the runtime DLLs the dll depends on
(libstdc++/libgcc/libwinpthread for mingw-host, c++.dll for msvc-host).
Lets a user run crafter-build.exe straight out of the release zip
without having to prepend C:\msys64\ucrt64\bin (or the libc++ bin
dir) to PATH first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 05:00:25 +02:00
50ae80a206 ArgQuery: out-of-line CRAFTER_API methods for Windows DLL crossing
All checks were successful
CI / build-test-release (push) Successful in 14m37s
In-class inline methods on a module-exported class get the @<module>
linkage attachment, and clang does not emit their bodies into
consumers; the resulting external reference fails to resolve when a
project.dll on Windows tries to call ArgQuery::Has after consuming
ApplyStandardArgs's return value. Move the bodies to the implementation
unit and dllexport them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 04:15:29 +02:00
730e763718 ShellQuote: use double quotes on Windows
All checks were successful
CI / build-test-release (push) Successful in 14m41s
cmd.exe treats single quotes as literal characters, so the existing
single-quote wrapping broke git/cmake invocations on a Windows host
("could not create leading directories of '<path>'").

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 03:50:06 +02:00
0ab30a1d81 fixes
Some checks failed
CI / build-test-release (push) Failing after 8m31s
2026-04-30 02:20:19 +02:00
bc9ceb8f24 config from args
All checks were successful
CI / build-test-release (push) Successful in 9m2s
2026-04-29 18:59:01 +02:00
52c4eed8c6 help command
All checks were successful
CI / build-test-release (push) Successful in 9m11s
2026-04-29 04:00:07 +02:00
c0e4067639 CI fix 2
All checks were successful
CI / build-test-release (push) Successful in 14m45s
2026-04-29 03:37:09 +02:00
4d09eaac2a loading bar
Some checks failed
CI / build-test-release (push) Failing after 4m41s
2026-04-29 03:27:11 +02:00
307db7169d home autodetect 2026-04-29 03:00:53 +02:00
bed4a7c9e4 Cross-compiled mingw artifact: full DLL+launcher pattern + MSVC target
Some checks failed
CI / build-test-release (pull_request) Has been cancelled
Linux→mingw cross-compile now produces the same architectural shape as
build.cmd (DLL + import lib + launcher exe) instead of a single static
binary. The CI Windows artifact becomes a first-class drop-in: a user
on Windows can run crafter-build.exe against any project.cpp and have
it produce real Windows binaries — for either mingw or MSVC ABI.

What changed:

project.cpp: when target=mingw or target=msvc, crafter.build-lib is
built as LibraryDynamic instead of LibraryStatic so the link emits a
DLL + import lib (matching what build.cmd produces natively).

Crafter.Build-Clang.cpp Build():
- LibraryDynamic now branches per target — mingw emits <name>.dll +
  lib<name>.dll.a via lld --out-implib; msvc emits <name>.dll +
  <name>.lib via /IMPLIB; unix unchanged.
- expectedOutputFor returns .dll for Windows-target dynamic libs.
- Executable on Windows host now branches per target: mingw target
  uses simple link (no -lc++/-nostdlib++/LIBCXX_DIR), msvc target keeps
  the existing path. Both auto-copy LibraryDynamic dep DLLs + import
  libs alongside the launcher exe (Windows resolves DLLs from the exe's
  own directory at load time).
- Mingw-target Executables get -D CRAFTER_BUILD_DLL_IMPORT so
  CRAFTER_API resolves to dllimport in their PCMs.
- mingw link adds -static-libstdc++ -static-libgcc -Wl,-Bstatic
  -lpthread so produced .exe/.dll don't depend on a particular
  libstdc++-6.dll / libwinpthread-1.dll being on the consumer's PATH
  (avoids the Arch UCRT vs msys2 UCRT vs msys2 MSVCRT ABI rabbit hole).
  Drops the old auto-copy of /usr/x86_64-w64-mingw32/bin/*.dll which
  is now dead weight.
- -r flag resolves to an absolute path before std::system, otherwise
  cmd.exe rejects "./bin/..." with "'.' is not recognized...".

Crafter.Build-Platform.cpp:
- Split the Windows-host block into shared shell helpers (#if MSVC ||
  MINGW) plus separate #if MSVC and #if MINGW blocks for LoadProject /
  EnsureCrafterBuildPcms / GetBaseCommand / BuildStdPcm.
- Mingw-host LoadProject compiles project.cpp with --target=mingw,
  --sysroot=C:\msys64\ucrt64 (default; override with CRAFTER_MINGW_DIR),
  -femulated-tls, -Wl,--export-all-symbols (mingw-lld doesn't accept
  /EXPORT:NAME), and links against libcrafter-build.dll.a from the
  launcher's directory.
- Mingw-host GetBaseCommand and BuildStdPcm dispatch on config.target
  so a mingw-host crafter-build can also build msvc-target outputs
  (uses LIBCXX_DIR + libc++ headers, same as native build.cmd) when
  the user sets cfg.target = "x86_64-pc-windows-msvc".

README adds a Quick start (Windows) section covering both build paths
(native MSVC via build.cmd and the cross-compiled mingw artifact),
documenting the msys2 UCRT toolchain prerequisite.

Verified end-to-end on the winvm:
- mingw target: cross-compiled crafter-build.exe builds hello-world's
  project.cpp, compiles main.cpp, links a hello.exe that runs without
  any custom PATH (only Windows system DLLs needed).
- msvc target: same crafter-build.exe builds an MSVC-ABI hello.exe
  linked against c++.dll (auto-copied from LIBCXX_DIR), runs cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 02:23:42 +02:00
eaee502e8c V2: WASI, -r flag, CI pipeline, examples & tests cleanup
Some checks failed
CI / build-test-release (pull_request) Failing after 44s
WASI / wasm32 target support
- Auto-detect /usr/share/wasi-sysroot on Linux when target starts_with("wasm32")
- Skip -march/-mtune for wasm (clang rejects them)
- Apply -fno-exceptions -fno-c++-static-destructors -mllvm -wasm-enable-sjlj
  -D_WASI_EMULATED_SIGNAL to wasm builds (compile + std PCM, kept in sync)
- .wasm output extension in expectedOutputFor and link command
- EnableWasiBrowserRuntime(cfg): opt-in helper that drops index.html +
  runtime.js next to the .wasm; runtime.js reads window.CRAFTER_WASM_URL
  set in the templated index.html so a single shim handles any output name

-r run flag in the CLI: build then exec the artifact (host targets only;
  rejects libraries; auto .exe/.wasm extension handling)

CI pipeline (.forgejo/workflows/ci.yaml)
- Triggers: PR/push to master + manual dispatch
- Single arch-latest container job: install deps, bootstrap, self-rebuild,
  run tests, cross-compile mingw, package both archives, upload artifacts
- Rolling 'latest' release published only on push/dispatch to master

mingw cross-compile from Linux now works end-to-end:
- ExternalDependency cache key includes target so per-target glslang builds
  don't collide; CMAKE_BUILD_TYPE=Release pinned (otherwise glslang appends
  'd' to lib names and breaks linking); cross-compile cmake flags
  (CMAKE_SYSTEM_NAME=Windows, CMAKE_*_COMPILER_TARGET=...)
- project.cpp accepts --target=<triple>; Linux-only -Wl,--export-dynamic
  and -ldl are gated; mingw glslang skips the standalone exe (its libgcc_eh
  link pulls pthread which mingw doesn't link by default)
- mingw compile uses -femulated-tls so std::__once_callable etc reference
  the same emutls symbols libstdc++ provides
- mingw link auto-adds -lstdc++exp -lpthread

GetCrafterBuildHome() exposed from the Platform module; LoadProject (Linux
+ Windows) now both use it instead of duplicating the resolution.

Examples reorg: hello-world, library, with-module, wasi, tests — each with
its own README. Tests reorg: per-test directory with inner/ fixture, no
shared tests/fixtures/ tree. New Wasi test verifies .wasm magic bytes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 23:24:46 +02:00
cdfdb976c8 test runner, cross-target runners, lib/exe split
- subprocess-isolated test runner (replaces V1 dlopen-RunTest);
  Pass/Fail/Crash/Timeout/Skipped outcomes via :Test partition
- TestRunner abstraction with command templates: Local, Ssh,
  SshWin (cmd.exe-shell), QemuUser, FromEnv; probe-based skip
  when runner unreachable
- transitive PCM-path propagation in Build(); resolveImport
  walks deps recursively; depResults cache keyed by PcmDir()
  so per-target builds don't collide
- cfg.sysroot threaded through BuildStdPcm + base compile/link
  command (enables aarch64 cross via Arch Linux ARM rootfs)
- lib + exe split: project.cpp defines crafterBuildLib
  (LibraryStatic) + crafterBuildExe (Executable depending on
  it); build.sh produces lib/libcrafter-build.a alongside
  bin/crafter-build for downstream static-link consumers
- Windows DLL+launcher: CRAFTER_API macro, /EXPORT flag for
  project.dll's CrafterBuildProject; Crafter::Run as the real
  entry point with main.cpp as a thin wrapper
- 18 tests: HelloWorld/WithModule/Defines/CrossProjectModule/
  Diamond × (Linux + sshwin:winvm), plus Incremental,
  BuildError, Libraries, RunnerClassification, QemuUser,
  SshRunner, WindowsViaSsh, CrossArchAarch64
- single ./bin/crafter-build test runs everything; Windows
  variants skip gracefully if winvm SSH alias unreachable

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-27 22:32:19 +02:00
f13671b2be v2 nearly done 2026-04-27 07:04:42 +02:00
5e1fcd8590 V2 progress 2026-04-23 01:57:25 +02:00
d2f5863552 windows define fix
Some checks failed
demo.yaml / windows define fix (push) Failing after 0s
2026-04-14 16:34:35 +02:00
d4ec1127f8 msvc pcm folder fix
Some checks failed
demo.yaml / msvc pcm folder fix (push) Failing after 0s
2026-04-14 16:25:37 +02:00
b906fa55fb msvc pcm march
Some checks failed
demo.yaml / msvc pcm march (push) Failing after 0s
2026-04-14 16:23:40 +02:00
4f6a77fb54 fixed msvc stdpcm
Some checks failed
demo.yaml / fixed msvc stdpcm (push) Failing after 0s
2026-04-14 16:12:06 +02:00
2d89528bdf fixed mingw
Some checks failed
demo.yaml / fixed mingw (push) Failing after 0s
2026-04-02 16:53:07 +02:00
e4e4e67cc0 cmake lib fix
Some checks failed
demo.yaml / cmake lib fix (push) Failing after 0s
2026-03-24 01:12:36 +01:00
cbdcfee462 std pcm march dependant 2026-03-22 20:40:59 +01:00
a6fbed5d5f added config target string 2026-03-15 01:52:07 +01:00
8d521340d4 windows exception handler
Some checks failed
demo.yaml / windows exception handler (push) Failing after 0s
2026-03-09 20:22:01 +01:00
64945d95ef windows exception handler
Some checks failed
demo.yaml / windows exception handler (push) Failing after 0s
2026-03-09 20:20:17 +01:00
7a64859d24 windows exception handler
Some checks failed
demo.yaml / windows exception handler (push) Failing after 0s
2026-03-09 20:14:44 +01:00
898e3f8a16 windows build fix
Some checks failed
demo.yaml / windows build fix (push) Failing after 0s
2026-03-03 00:06:00 +01:00
515294c7e6 windows build fix
Some checks failed
demo.yaml / windows build fix (push) Failing after 0s
2026-03-02 23:46:36 +01:00