Skip to content

Experimental Buck2 build of stage 1 and stage 2 with cabal buck2 - #195

Merged
angerman merged 7 commits into
stable-ghc-9.14from
cabal-buck2-ghc
Oct 18, 2026
Merged

angerman merged 7 commits into
stable-ghc-9.14from
cabal-buck2-ghc

Conversation

@hsyl20

@hsyl20 hsyl20 commented Oct 1, 2026 •

Copy link
Copy Markdown

Add an experimental native Linux Buck2 build for GHC stage 1 and static stage 2. cabal buck2 generates the package build rules; //buck2-ghc:stage2-libdir supplies an installation with registered libraries and compiler tools.

  • Keep the existing Make static/dynamic solver constraints and list the interpreter-init stub explicitly when the interpreter is disabled.
  • Pin the patched Cabal and haskell-buck2 sources, verify the downloaded Buck2 archive, and identify cached tools by their sources. Preserve dirty developer checkouts.
  • Stop stage-2 generation on failed stage-1 tool builds and retain diagnostics. Respect Cmm: declare CPU requirements on RTS procedures #197 per-procedure CPU requirements instead of adding file-wide AVX flags.
  • Make installed runghc select the installed compiler explicitly, and supply Haddock's installed GHC libdir and copied HTML/LaTeX resources.
  • Exercise both TH interpreters, CInt FFI, process exits, runghc compiler/package selection, and actual Haddock HTML/JS/CSS in the smoke test.

The verbose runghc identity check accepts the Stable Haskell Edition banner while retaining exact numeric-version, output, exit-status, and package-database checks. On failure it prints the captured output and diagnostics.

Validation: the fresh native Linux Buck2 run passed on combined head 7eb9fecf. It built both compiler stages with no cached Buck2 actions and completed the installed-tool smoke test: libraries, threaded RTS, both TH interpreters, CInt FFI, hsc2hs, ghc-e, runghc compiler/version/package-database selection, generated Haddock HTML/index/JavaScript/CSS, and hpc.

Installer/cache/failure controls, generator equivalence checks, actual wrapper expansion, copied-tool layout probes, ShellCheck, and smoke controls also pass. The identity controls reject wrong compiler versions, package databases, output, and failed commands.

The ordinary CI, Nix CI, and Build and release workflows also passed on that head: 53 checks passed overall, with the expected PR publication skip. The Alpine release suite passed after one retry of the unchanged compiler artifact.

Make MULTI installed-artifact tests passed on x86_64 Linux, AArch64 Linux, and AArch64 Darwin, executing native, Wasm, and JavaScript hello-world programs and compiling Miso for Wasm.

For Buck2, stage 3, cross-compilation, dynamic/profiled stage-2 libraries, and the complete GHC test suite remain outside this experimental build path's claimed coverage.

Track Cmm unwind nodes and machine stack adjustments, use AArch64 DWARF register numbers and extended encodings, and emit procedure range labels on ELF and Mach-O. Preserve the C stack separately from the Haskell CFA.

Move the Linux/Darwin AArch64 STG runner into StgCRunAsm.S so its CFI describes a complete frame rather than guessing the C compiler frame around inline assembly. Describe save/restore transitions and connect the bottom STG frame to StgRunJmp. Add assembler and nested callback ABI regressions.
Create a process-lifetime log once, gate emission and runtime availability, and keep each GC interval ID on the initiating collector stack. This avoids capability-array resizing and stale or orphan interval IDs when instrumentation is toggled.

Forward user events directly from Darwin PrimOps in vanilla, tracing, and DTrace ways. Add observable mock-backend concurrency and pairing checks, and verify disabled non-Darwin macros do not evaluate arguments.
angerman and others added 5 commits October 18, 2026 07:57
Keep host plugin packages, settings and interface caches separate from target compilation. Retain a session-lived in-process interpreter while Template Haskell runs in the target interpreter. Add host package selection, failure recovery and cross-compilation regressions.
…er is disabled

With flag -interpreter, GHC.Driver.Config.Interpreter imports the stub
branch of GHC.Runtime.Interpreter.Init, but ghc.cabal.in listed the
module only under `if flag(interpreter)`. The cabal build works because
`ghc --make` finds the module through the source directory; a build
system with explicit sources (buck2) does not. List it in both cases.
Add what is needed to build stage 1 with Buck2 through Simon Marlow's
experimental `cabal buck2` command (simonmar/cabal, branch buck2) and
the haskell-buck2 rules:

- `make buck2-stage1 CABAL_BUCK2=...`: runs the configure prerequisites
  and `cabal buck2` on cabal.project.stage1 (with --enable-shared, since
  buck2's dev mode links dynamically).
- Hand-maintained BUCK files for the packages with a Custom Setup.hs,
  which `cabal buck2` does not run: compiler/BUCK (primop .hs-incl files,
  GHC.Platform.Constants, GHC.Settings.Config) and libraries/ghc-boot/BUCK
  (GHC.Platform.Host). Two Python scripts replicate the Setup.hs code.
- BUCK files in libraries/ghc-boot-th and libraries/ghc-internal/src that
  export their sources for ghc-boot-th-next (hs-source-dirs: ../...).
- The plain BUCK wrappers that `cabal buck2` creates for the other
  stage-1 packages, so that a fresh checkout has them.
- .gitignore entries for the generated files and README section.

Stage 2 is out of scope: its project files need the Stable Haskell cabal,
which does not have the buck2 command yet.
Stage 2 is built by the stage-1 compiler that buck2 built: `cabal buck2
--variant stage2` on cabal.project.stage2.buck2 generates
BUCK.stage2.cabal.bzl files with targets suffixed -stage2, built in the
`stage2` buck2 platform whose Haskell toolchain is the wrapper
//buck2-ghc:ghc (the stage-1 compiler with a libdir of its own).
`buck2 build //buck2-ghc:ghc-stage2 -m opt` gives the stage-2 compiler
with a libdir where every stage-2 library is registered; it compiles
and links programs (static libraries).

- cabal.project.stage2.buck2: the static stage-2 project for an upstream
  cabal; the fork-only `build:any.ghc-internal installed` constraint
  moves from cabal.project.stage2.common to the .static/.dynamic files.
- .buckconfig (tracked now): the third-party-haskell-stage2 cell and the
  [haskell_stage2] tools; a root BUCK exporting config.sub, config.guess
  and install-sh.
- buck2-ghc/BUCK, store.bzl: the two installations (stage-1 compiler +
  libdir as the stage-2 toolchain; stage-2 compiler + libdir with
  haskell_package_db).
- rts/BUCK: the RTS ways as `sublibraries` of the rts unit (GHC links
  the way it selects through the package db), rts-constants-stage2 for
  the ways' platform constants. Vector procedures declare their CPU
  requirements in Cmm; the file/component flags stay at the baseline.
- libraries/ghc-internal/BUCK + BUCK.autogen.bzl: GHC.Internal.Prim and
  GHC.Internal.PrimopWrappers printed by the compiler; the exports of
  src/ for ghc-boot-th-next (replacing libraries/ghc-internal/src/BUCK,
  so that ghc-internal can use its own files by path).
- compiler/BUCK, libraries/ghc-boot/BUCK: the Setup.hs generators for
  both stages (BUCK.autogen.bzl); gen_settings_config.py takes the
  ghc-internal unit id of the stage.
- The BUCK wrappers cabal buck2 creates for the stage-2 packages,
  .gitignore entries, README and Makefile.
- //buck2-ghc:stage2-libdir is an installation: bin/ghc (the stage-2
  compiler with its libdir), bin/ghc-pkg, and hsc2hs, hpc, haddock,
  hp2ps, runghc, ghc-iserv, unlit (the Makefile's STAGE2_EXECUTABLES);
  `make buck2-stage2` passes `all exe:hsc2hs exe:hpc` to `cabal buck2`,
  and the executables of the two source-repository packages are named
  through the generated aliases //dist-newstyle/src:hsc2hs-stage2.
- The hand-maintained stage-2 rules test the GENERATED constant of the
  generated files (see Note [Variant stubs] in cabal-install): a fresh
  tree builds stage 1 with `buck2 build //...` before stage 2 exists.
- mk/buck2-tools.sh installs the tools (buck2, cabal with the buck2
  command, haskell-buck2 at ./buck2); mk/buck2-smoke-test.sh compiles
  and runs programs with an installation (libraries, -threaded,
  Template Haskell, the FFI, hsc2hs, runghc); .github/workflows/buck2.yml
  runs stage 1, stage 2 and the smoke test on ubuntu-24.04.
- C sources of every component are compiled by GHC now (generator):
  no more -cxx overrides.

Pin the tool source revisions and verify the Buck2 release archive before
running it. Include the pins in the CI cache identity and preserve clean
source checkouts. Report failed tool builds before invoking cabal buck2.
Keep the RTS at the baseline ISA after procedure-level CPU attributes.
Check smoke-program exits, both interpreters and the C FFI's CInt ABI.

Wrap runghc with the installed compiler path rather than relying on
executable-relative lookup from a raw Buck output. Wrap Haddock with the
installed GHC libdir and the haddock-api data-files target copied into
the store. Smoke checks now verify runghc's compiler/package database and
generate Haddock HTML with installed JS/CSS resources.

Accept edition names in the verbose runghc banner while retaining the
exact numeric version and selected package database checks. Print the
captured output when any compiler identity check fails.
@angerman
angerman merged commit 7eb9fec into stable-ghc-9.14 Oct 18, 2026
82 of 83 checks passed
@angerman
angerman deleted the cabal-buck2-ghc branch October 18, 2026 18:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants