Skip to content

Add GCC example with scoped configs and assembly support#6

Open
typeless wants to merge 15 commits intomainfrom
wip/example-gcc
Open

Add GCC example with scoped configs and assembly support#6
typeless wants to merge 15 commits intomainfrom
wip/example-gcc

Conversation

@typeless
Copy link
Owner

@typeless typeless commented Feb 10, 2026

Summary

  • Add examples/gcc/ demonstrating a real-world multi-directory build: GMP + MPFR + MPC from GCC's bundled sources
  • Extend putup configure to copy subdir tup.config files for scoped config merging

Build Features Demonstrated

  • Assembly support: CPU-specific .asm → m4 → assembler pipeline with config-driven source selection
  • foo-y conditional compilation: Kbuild-inspired pattern for toggling multi-function sources without ifeq
  • Multi-variant parallel builds: Multiple -B directories with different toolchain configs
  • Per-component scoped configs: Each library has its own tup.config, merged with root via scoped config merging
  • Self-contained libraries: Each library buildable standalone or composed under root
  • 3-tree builds: Tupfiles (-C), GCC sources (-S), and build output (-B) in separate directories
  • Cross-directory groups: Subdirectory objects collected via ../<objs> into parent archive

Files

Area Files Purpose
Build driver Makefile.pup, scripts/resolve-mpn.sh Make wrapper + mpn source resolution
Root config Tuprules.tup, Tupfile, configs/*.config Toolchain vars, library directory layout
GMP gmp/{Tupfile,Tuprules.tup,tup.config}, gmp/{mpn,mpz,mpq,mpf,printf,scanf,rand}/Tupfile 8-directory build with assembly support
MPFR mpfr/{Tupfile,Tuprules.tup,tup.config,src/Tupfile} Depends on GMP headers
MPC mpc/{Tupfile,Tuprules.tup,tup.config,src/Tupfile} Depends on GMP + MPFR headers
Configure src/cli/cmd_configure.cpp Copy subdir tup.config files to build tree

Test plan

  • make -f Makefile.pup SRCDIR=../gcc-15.2.0 builds all three libraries in generic C mode
  • make -f Makefile.pup MPN_CPU=x86_64 SRCDIR=../gcc-15.2.0 builds with x86-64 assembly
  • make -f Makefile.pup multi SRCDIR=../gcc-15.2.0 builds x86_64-linux + aarch64-linux variants
  • Standalone cd gmp && putup configure && putup works with ?= defaults
  • make test passes (no regressions in existing tests)

🤖 Generated with Claude Code

@typeless typeless force-pushed the wip/example-gcc branch 4 times, most recently from 95d15db to 55673fb Compare February 10, 2026 10:16
Build GCC's three prerequisite libraries using putup with a 3-tree
layout (-C/-S/-B) against a read-only GCC source tree.

Each library is self-contained with ?= defaults for standalone builds.
Per-component tup.config files use prefix-free entries — the directory
scope provides the namespace via scoped config merging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@typeless typeless changed the title Add GCC example: build GMP, MPFR, MPC from source Add GCC example with scoped configs and assembly support Feb 12, 2026
typeless and others added 2 commits February 13, 2026 13:42
Add libiberty, libdecnumber, libbacktrace, libcpp libraries and the
full gcc/ build pipeline (config headers, ~25 generator programs,
~500 backend objects, cc1 link) to the GCC example.

The generator bootstrap chain builds genmodes first, then BUILD_RTL
support objects, then all RTL generators that produce insn-*.h and
insn-*.cc from machine description files. Pre-generated files from
gengtype and genmatch are expected in gcc/pre-generated/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
genmatch reads match.pd and generates optimized C++ for GIMPLE and
GENERIC IR simplification. It was previously requiring users to run
./configure && make on the GCC source tree to produce its outputs.

Now genmatch is compiled and linked against libcpp (for tokenization)
and run as part of the normal build. Only gengtype outputs remain in
pre-generated/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@typeless
Copy link
Owner Author

GCC Example Build — Handoff Note

Current State

Build reaches ~1088/1740 commands before failing. The build command:

cd /home/mural/src/pup/examples/gcc && \
  PUP_IMPLICIT_DEPS=0 /home/mural/src/pup/build/putup \
  -C . -S /home/mural/src/gcc-15.2.0 -B ../../build-gcc -j$(nproc)

You need a GCC 15.2.0 source tree at /home/mural/src/gcc-15.2.0 (adjust -S path as needed).

Next Issue to Fix

4 generators with file-output flags write relative to CWD (read-only in 3-tree mode)

These generators use flags like -O, -H, -A, -D, -L, -h, -c to write output files relative to their working directory. In 3-tree mode, CWD = source dir (read-only).

Affected rules in examples/gcc/gcc/Tupfile (lines ~408-459):

Generator Flags Outputs
genattrtab -A, -D, -L insn-attrtab.cc, insn-dfatab.cc, insn-latencytab.cc
genopinit -h, -c insn-opinit.h, insn-opinit.cc
genemit -O (x10) insn-emit-{1..10}.cc
genrecog -H, -O (x10) insn-recog.h, insn-recog-{1..10}.cc

Fix: Use the same SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) pattern already applied to genmatch (lines 308-332). Check whether %f gives absolute or relative paths in 3-tree mode — if $(MD) already resolves to absolute source paths, a simple cd $(TUP_VARIANT_OUTPUTDIR) may suffice. Test with a single generator first.

Key Discoveries (This Build Effort)

  1. $VAR (bare dollar) passes through to shell — putup's expand() only expands $(VAR). Bare $PWD, $SRCDIR etc. pass through as shell variables.

  2. Display text ^ ... ^ must be on the SAME line as |> — if on a continuation line, it gets included in the shell command and causes /bin/sh: ^: not found.

  3. GCC generators need BOTH -DIN_GCC AND -DGENERATOR_FILE — already set in HOST_CXXFLAGS in gcc/Tuprules.tup.

  4. tm_p.h must include 3 headers: config/i386/i386-protos.h, config/linux-protos.h, and tm-preds.h (declares predicate functions like register_operand).

  5. Don't set CONFIG_HAVE_UCHAR=1 — modern Linux doesn't provide uchar. GCC's coretypes.h typedefs it when HAVE_UCHAR is NOT defined.

  6. After editing tup.config, must re-run putup configure to propagate to build dir.

Workflow

Build → read first error → diagnose → fix Tupfile/config → rebuild. Repeat until cc1 links.

Separate Issue: 3-Tree Groups Bug

Order-only groups produce "has no members" warnings in 3-tree mode. Plan exists at .claude/plans/snuggly-noodling-scroll.md. This is a putup core bug, separate from the GCC example work. The GCC example uses PUP_IMPLICIT_DEPS=0 as a workaround.

typeless and others added 12 commits February 13, 2026 18:53
…ee mode

Build reaches ~1088/1740. Fixes applied:
- genmatch: SRCDIR=$PWD pattern for cfn-operators.pd in 3-tree mode
- tm_p.h: add missing linux-protos.h and tm-preds.h includes
- tup.config: remove incorrect HAVE_UCHAR, fix library configs
- gencondmd: fix display text placement (must be on same line as |>)
- Tuprules.tup: use ?= defaults for self-contained library builds

Next: fix genattrtab/genopinit/genemit/genrecog file-output flags
(write relative to CWD which is read-only source dir in 3-tree mode).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
genattrtab, genopinit, genemit, and genrecog write output files relative
to CWD via flags (-A/-D/-L, -h/-c, -O, -H/-O). In 3-tree mode CWD is
the read-only source directory, so cd to the build directory first using
the same SRCDIR=$PWD pattern established by genmatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lchain

Extends the GCC example from cc1-only to a complete cross-compiler toolchain
(aarch64-apple-darwin host → x86_64-pc-linux-gnu target). 3517 commands,
~133s on M4 Mac. Five verified binaries: cc1 (40MB), cc1plus (42MB),
xgcc (2.4MB), xg++ (2.4MB), collect2 (2.3MB).

New components:
- cc1plus: C++ compiler backend (40 cp/ source files, gengtype [cp] support)
- xgcc/xg++: C/C++ compiler drivers with specs.h for language dispatch
- collect2: linker wrapper for C++ constructor/destructor collection
- libcody: C++ modules protocol library (required by cc1plus)

Architecture improvements:
- Extract LIBCOMMON_OBJS/DRIVER_LIBS to DRY up xgcc/collect2/xg++ link commands
- Move target-specific config (tm.h, tm_p.h, MD files) to targets/*.tup
- Add macOS host configs (configs/host-darwin/) for cross-compilation
- Add darwin-x86_64-linux.config variant for macOS→Linux cross builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Four more tools built from existing GCC source, bringing the total to
9 binaries: cc1, cc1plus, xgcc, xg++, collect2, cpp, lto-wrapper,
gcov, gcov-dump. All follow established patterns (LIBCOMMON_OBJS +
DRIVER_LIBS). Only 6 new object compilations — rest reuses existing
objects from cc1/xgcc/collect2 builds via $(D)/ path references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add $$ → $ de-escaping in the evaluator so shell variable references
survive Tupfile expansion (e.g., for f in $(names); do ... $$f).

In 3-tree builds (-C/-S/-B), the scheduler now creates source subdirs
that exist in the config tree but not the source tree, enabling packages
whose actual source lives in a separate tree (referenced via config
variables rather than the -S tree).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Build GNU binutils 2.44 cross-assembler and cross-archiver targeting
x86_64-linux from a separate source tree via @(BINUTILS_SRC). This is
the first package to use an explicit source variable rather than the
implicit -S tree, establishing the pattern for future packages.

Single Tupfile builds BFD (38 files), libsframe (2), opcodes (4),
gas (39), and ar (11) — producing working as and ar binaries that
integrate with the existing xgcc/cc1 toolchain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The pattern required at least one token between the compiler name and
-c, so commands like `gcc -c foo.c -o foo.o` never matched. Also add
\s as an anchor alternative so compiler wrappers like `ccache gcc` are
recognized.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mode

The scheduler auto-created source-tree directories when a config-tree
directory had no counterpart. This papered over a user setup issue
rather than honoring the 3-tree model: config tree mirrors source tree.

Makefile.pup now creates the binutils/ directory in the source tree as
an explicit setup step.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The examples/ directory becomes the BSP root (-C tree). Infrastructure
(Tupfile.ini, Tuprules.tup, Makefile.pup, configs/, scripts/) moves up
from examples/gcc/. Binutils moves to examples/binutils/ as a peer
tarball group. GCC-internal packages stay under examples/gcc/ with a
new group Tuprules.tup providing ?= defaults for standalone use.

Key changes:
- Root Tuprules.tup uses gcc/ prefix for all GCC-tarball DIR variables
- Binutils uses $(S)/$(BINUTILS_DIR) instead of @(BINUTILS_SRC)
- Nested Tupfile.ini markers removed from busybox/ and helloworld/
- Source assembly model: one source-root/ subdir per extracted tarball

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…symbol

The foreach *.c glob picks up both hello.c and main.c, so hello.c must
not define main() — use hello() instead to avoid duplicate symbol errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

1 participant