Commit graph Crafter.Build/README.md
Author SHA1 Message Date
631c60892a
docs: scripts in the README
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-20 19:08:26 +02:00
fe38cc1f66
docs: sysroot compiles use the sysroot's libc++ headers
Some checks failed
Flatpak / flatpak (pull_request) Successful in 7m54s
Flatpak / flatpak (push) Has been cancelled
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 16:50:41 +02:00
c6b0bbaf25
readme change
All checks were successful
Flatpak / flatpak (push) Successful in 13m43s
2026-10-03 21:16:01 +02:00
7abbdf503b
readme change
Some checks failed
Flatpak / flatpak (push) Has been cancelled
2026-10-03 21:14:30 +02:00
03728fd4a7
docs: describe the output directory name and what a compiler update does
The README still gave the output path as bin/<name>-<target>-<march>/,
which has not been its shape since the variant hash was introduced. It
now shows the real one and says what the hash stands for, including
that a compiler update starts a new directory and `clean` removes the
old. AGENTS.md lists the toolchain among VariantId()'s inputs and notes
that a glob over variant directories matches two after an update.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 20:09:22 +02:00
4e5d17b9e9
docs: describe how a sysroot build finds its std module source
All checks were successful
Flatpak / flatpak (push) Successful in 1h30m57s
The README said a cross build precompiles the sysroot's own std.cppm,
which was never the whole story for sysroots that do not ship one. It
now states the order (the sysroot's, the toolchain's for the same major
release, the sources crafter-build carries for other releases), what
the failure looks like when nothing matches and how to resolve it, and
lists the new directory in the install layout.

AGENTS.md records the rule for the next LLVM bump: the release the
bundled toolchain leaves behind stays available as a module-source
module, because stable distros remain on it long after.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 17:01:21 +02:00
2b7c8f7f2d
docs: install from the Catcrafts Flatpak repo
The README leads with the Flatpak install, keeps the native loop as the
way to build from source, and drops the tarball, musl and makepkg text
that no longer describes anything CI produces. The install layout shows
the /app tree and the per-app cache directory.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 23:29:44 +02:00
c3485b7ab1
docs: name the toolchain in the cache directory layout
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 23:18:09 +02:00
a72d18eeab
docs: describe the toolchain resolver and --version
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 22:26:31 +02:00
68e9b6bfa5
docs: describe the Linux-only host
README and AGENTS.md stop documenting build.cmd, LIBCXX_DIR, the
DLL-plus-launcher design rule and the cmd-over-SSH gotcha. The runner
section also drops Ssh, SshWin and Wsl, which were removed from the
code earlier but still had README entries, and the stale pointer to a
deleted cross-arch test. ci.yaml loses the commented-out Windows build,
staging and upload steps and the comments that counted them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 22:03:34 +02:00
f60ba809b5
docs: describe IsTopLevelProject for test-only dependencies
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 22:02:40 +02:00
c3d97be59e
Merge branch 'claude/project-dependencies': project.cpp dependencies, AGENTS.md
Some checks failed
CI / build-test-release (push) Failing after 4m7s
CI / release-musl (push) Has been skipped
Brings in `#pragma crafter dependency`, the switch to Crafter.LintRules
for the house style, and the contributor guide in AGENTS.md.

The branch predates the musl host work on master, and both rewrote the
command that compiles project.so, so the merge reconciles them by hand:

- LoadProject compiles project.so for hostConfig.target (HostTarget(),
  from master) with the pre-dependency module path and archives from
  the branch. -fuse-ld=lld appears once, with both reasons in the
  comment.
- ForceHostTooling added -fPIC only for the literal x86_64-pc-linux-gnu
  triple. hostConfig now comes from HostTarget(), so on Alpine the host
  is x86_64-alpine-linux-musl and the dependency archive would not have
  been position-independent. It now matches any *-linux-gnu or
  *-linux-musl host, as project.cpp and the cmake flags do since the
  musl change, and its comment no longer argues against HostTarget().
- The ProjectDependency test compared the dependency's target against
  the glibc triple, which the musl CI job would fail; it compares
  against HostTarget().
- README keeps master's paragraph on the bootstrap triple. AGENTS.md
  describes the test block as `if (linuxTarget)`, which is what
  project.cpp has now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 20:47:23 +02:00
991ae7549e
docs change 2026-10-02 20:35:38 +02:00
825cc875ad
refactor: pull the house-style rules from Crafter.LintRules instead of a copied header
lint-rules.h moves to its own repo as the module Crafter.LintRules, which
project.cpp now imports through `#pragma crafter dependency`. Editing a
rule no longer needs `touch project.cpp`: the rebuilt dependency makes
project.so stale by itself. tests/HouseRules moves with the rules.

Building this checkout needs a crafter-build that understands the
directive (`./build.sh` bootstraps one) and the Crafter.LintRules repo on
Forgejo.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 20:03:22 +02:00
b94139b67c
feat: project.cpp declares its own dependencies with #pragma crafter dependency
A project.cpp could only import std and Crafter.Build, so anything shared
between build descriptions had to be a header every consumer copies. Now

    #pragma crafter dependency "<source>" [branch "<b>" | commit "<sha>"] [project "<file>"]

names a sibling crafter-build project that project.cpp itself imports a
module from. LoadProject scans for the directive, resolves it through
GitProject (a URL) or LocalProject (a path relative to the project file),
forces the result into host-tooling mode (the host triple LoadProject's
own cache is keyed on, native march, no debug, -fPIC so the archive links
into a shared object), builds it, and puts its BMIs and archive on the
project.so command line. The dependency's own project.cpp goes through
the same loader, so its directives resolve recursively; a cycle between
project files is an error instead of unbounded recursion.

The dependency is built on every load, fresh or not: clang crashes rather
than erroring when it imports a BMI whose own imported PCM was rebuilt
underneath it, and the module depfile — which Module::Check already reads —
is what notices the host PCM cache was regenerated. Its artifact mtime is
an input to project.so's staleness check, so editing the dependency
recompiles project.cpp without touching it. The Linux link gains
-fuse-ld=lld because release archives hold ThinLTO bitcode.

ProjectDependency(name) hands the same Configuration* back from inside
CrafterBuildProject, by configuration name or exported module name, so a
test that links the module needn't spell the source twice. It reads a
thread_local frame stack that an RAII guard keeps for the whole of
LoadProject, which also provides the cycle check.

ExpectedOutput() is the link gate's artifact-path lambda hoisted into the
:Clang partition, so the staleness check and the -r runner share the one
rule. Windows branches are wired identically but unverified.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-02 20:03:22 +02:00
dc239f4257 musl host support: bootstrap and run on Alpine (x86_64-alpine-linux-musl)
All checks were successful
CI / build-test-release (push) Successful in 7m43s
CI / release-musl (push) Successful in 8m56s
The Linux host code paths were gated on the x86_64_pc_linux_gnu target
define alone, and LoadProject hardcoded --target=x86_64-pc-linux-gnu when
compiling project.cpp and the module PCMs. Both break on musl hosts: the
glibc release launcher cannot run there at all (no glibc loader; gcompat
lacks libgcc_s and the __isoc23_* symbols), and a musl-built launcher
would still compile project.cpp for the wrong libc.

- The host gates test clang's __linux__ instead of one triple's define:
  they mean "Linux host", whatever the libc (or, later, the CPU).
- LoadProject derives the host triple from HostTarget() (clang's
  -print-target-triple), which is also more correct on glibc distros
  whose triple isn't x86_64-pc-linux-gnu.
- project.cpp / the cmake libc++ flags treat any *-linux-gnu or
  *-linux-musl target as Linux.
- build.sh targets the host toolchain's triple (CRAFTER_BUILD_TARGET
  overrides) and derives the per-target define from it. On Arch this is
  byte-for-byte the previous behaviour.
- CI: a release-musl job bootstraps on alpine:edge, runs the tests, and
  attaches crafter-build-linux-x86_64-musl-v2.tar.gz to the rolling
  latest release (via the API, so the glibc assets survive). Dynamic
  against musl libc++: the launcher dlopens project.so, so it cannot be
  fully static.

First consumer: imsd's package CI, which cross-compiles for aarch64 from
an Alpine container.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 00:05:44 +02:00
catbot
cec20717d0 docs: state that build steps fail on exit status, not on output
All checks were successful
CI / build-test-release (pull_request) Successful in 5m31s
2026-08-26 00:51:22 +00:00
catbot
1d0d8e1e28 feat(incremental): rebuild when an #included header changes
The staleness check compared an artifact against its own source and its
module imports. Headers were in neither set: the scanner reads `import`
lines, and a .cppm or .cpp keeps its mtime when a header it includes is
edited — so the build reported nothing to do and left objects compiled
against the previous contents. Same silent mixed-layout binary as issue
27, reached through #include instead of import.

Ask the compiler what it actually opened. Every C++ and C compile now
passes -MD -MF <artifact>.d, and Check reads that depfile back through
NewestPrerequisite, comparing every prerequisite's mtime against the
artifact. A missing depfile (an object from a crafter-build that wrote
none) or a prerequisite that no longer exists reads as "rebuild": neither
is evidence of freshness.

The parser unescapes make syntax rather than splitting on whitespace,
since clang wraps depfiles onto continuation lines and escapes spaces in
filenames.
2026-07-31 11:11:38 +00:00
catbot
f38521298b fix: track what a primary module interface imports
Some checks failed
CI / build-test-release (pull_request) Failing after 6m5s
A primary module interface unit — `export module Widget;`, no partitions —
recorded nothing about what it imported. GetInterfacesAndImplementations
registered the Module and then erased the file from the scan list, so the
import pass only ever saw partitions, and Module had no vectors to hold an
edge anyway.

Two consequences, both reported as issue #26:

  Module::Check consulted only its own .cppm and its partitions. A data
  member added to an imported module left Widget.pcm, Widget.o and every
  consumer object untouched while the imported library rebuilt and both
  binaries relinked — one executable holding two class layouts, no
  diagnostic, and a crash somewhere unrelated. Wiping build/ was the only
  cure, so `crafter-build test` could not be trusted straight after an
  interface edit.

  Module::Compile waited on nothing. Two modules in one Configuration
  compile on concurrent threads, so a primary interface importing a
  sibling was a coin flip between working and "module 'Base' not found".

Partitions never had either problem — they carry the same three vectors and
Check/Compile honour them — which is why the gap only surfaced on a module
whose interface is one flat unit.

Module now carries moduleDependencies, externalModuleDependencies and
pendingImports with the same meanings as on ModulePartition; primary units
stay in the scan list so their imports land there; Check sees through them;
Compile orders itself behind a local sibling; and ResolvePendingImports
sweeps them so an edge survives dependencies being wired up afterwards.
Build() now Checks every interface before spawning any compile thread — the
`compiled` flag a waiter blocks on is raised either by a Compile that runs
or by the Check that decides none is needed, so a Check still pending while
another module's thread waits would have hung the build.

Resolves #26

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 18:19:04 +00:00
catbot
2fbcb6fbf3 docs: incrementality, variant identity and clean in the README
Some checks failed
CI / build-test-release (pull_request) Failing after 6m2s
2026-07-30 17:43:46 +00:00
8892154b28 linting
Some checks failed
CI / build-test-release (push) Failing after 7m15s
2026-07-23 01:24:42 +02:00
7ff426b2f0 SPDX license update
Some checks failed
CI / build-test-release (push) Failing after 5m36s
Canonical LGPL-3.0-only text, GPL-3.0 companion, SPDX headers on all
first-party sources, MIT for examples/. Vendored lib/ untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 18:19:17 +02:00
19b059a88c more tests
Some checks failed
CI / build-test-release (push) Has been cancelled
2026-04-29 03:52:08 +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
698665215b additional file fix 2025-11-09 20:08:23 +01:00
f90881b03d wasm 2025-11-09 18:56:24 +01:00
f8fc3836dd README update 2025-11-03 17:00:23 +01:00
0eed272765 rewrite 2025-10-31 16:50:47 +01:00
42756cf75e update README.md 2025-06-10 00:10:48 +02:00
fc0659207a test 2
Some checks failed
Main / build (push) Has been cancelled
2025-03-30 00:08:07 +01:00
445ad96c26 Merge branch 'master' of https://forgejo.catcrafts.net/Catcrafts/Crafter.Build 2025-03-30 00:07:58 +01:00
063285df6b test 2025-03-30 00:07:39 +01:00
The-Mighty-Cat
856de70133
Update README.md 2025-03-29 22:39:08 +01:00
c19a287fe2 readme changes 2025-02-03 22:18:56 +01:00
30b4182771 readme changes 2025-02-03 22:11:27 +01:00
dc3865ba6d march, flags, and git dependencies 2025-02-03 22:06:54 +01:00
914992cba9 added additional_files 2025-01-02 02:53:39 +01:00
The-Mighty-Cat
bcaaea4834
Update README.md 2024-12-30 22:08:31 +01:00
The-Mighty-Cat
168a1f381b
Update README.md 2024-12-29 20:20:06 +01:00
The-Mighty-Cat
55dac8ca59
Update README.md 2024-12-29 20:18:51 +01:00
The-Mighty-Cat
02465c2690
Update README.md 2024-12-29 20:17:19 +01:00
The-Mighty-Cat
dd3832a697
Update README.md 2024-12-29 20:16:53 +01:00
c5d6aa532c fixed readme 2024-12-29 17:54:57 +01:00
The-Mighty-Cat
40c9ef257a
Update README.md 2024-12-29 03:32:38 +01:00
98a73c0443 added wasm64 support 2024-12-29 03:30:22 +01:00
2f2ea03546 added wasm32-unknown-wasi target support via the wasi-sdk 2024-12-29 03:13:14 +01:00