diff --git a/.clang-tidy b/.clang-tidy index b5ffae9..de87757 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,194 +1,81 @@ --- -# clang-tidy configuration for uld_cpp -# Based on Ladybird browser config, adapted for C++11 embedded/AOSP project +# clang-tidy configuration for putup +# +# Approach: allowlist high-value checks, skip expensive analysis families. +# Modeled after DuckDB (allowlist + cherry-pick) and Ladybird (no clang-analyzer +# in CI). See https://github.com/duckdb/duckdb and +# https://github.com/LadybirdBrowser/ladybird for reference. +# +# Families enabled in full: bugprone, cert, concurrency, misc, performance, +# portability, readability (with selective exclusions below). +# Families cherry-picked: modernize (6 checks), cppcoreguidelines (7 checks). +# Families omitted: +# clang-analyzer-* — path-sensitive symbolic execution; 10x slower than all +# other checks combined. DuckDB omits it; Ladybird only uses it locally. +# google-* — style rules for Google's C++ guidelines, not our style. # # ============================================================================= # DISABLED CHECKS RATIONALE # ============================================================================= # -# bugprone-easily-swappable-parameters: -# This check warns when adjacent function parameters have similar types and -# could be accidentally swapped by callers. While the warning is valid, it's -# extremely noisy and the suggested fix (wrapping in structs) adds complexity. -# Example: void foo(int width, int height) triggers this warning. -# -# bugprone-macro-parentheses: -# Warns when macro arguments aren't parenthesized in expansion. Our ALOGE/ALOGI -# logging macros use variadic arguments that can't be parenthesized. Ladybird -# also disables this for code-generating macros. -# -# bugprone-reserved-identifier, cert-dcl37-c, cert-dcl51-cpp: -# These warn about identifiers starting with underscore or containing double -# underscores. System headers and OpenSSL headers legitimately use these. -# cert-dcl37-c and cert-dcl51-cpp are aliases for bugprone-reserved-identifier. -# -# cert-err33-c: -# Requires checking return values of certain C functions including fprintf(). -# Our logging macros (ALOGE, ALOGI, etc.) expand to fprintf() calls where -# ignoring the return value is intentional - logging failures shouldn't crash. -# -# cert-err58-cpp: -# ENABLED: Warns about exceptions in static object constructors. This project -# doesn't use exceptions, so no warnings expected. -# -# concurrency-mt-unsafe: -# Flags functions like strerror(), localtime(), getenv() as thread-unsafe. -# This project is single-threaded and these are standard C idioms. Using -# thread-safe alternatives (_r variants) would reduce portability. -# -# misc-const-correctness: -# Suggests adding const to variables that could be const. While good practice, -# enabling this generates hundreds of warnings requiring significant refactoring -# with minimal practical benefit for this codebase. -# -# misc-include-cleaner: -# Analyzes whether includes are necessary. Very noisy, reports many false -# positives, and the suggested changes often break compilation due to -# transitive includes. -# -# misc-no-recursion: -# Warns about recursive function calls. This project intentionally uses -# recursion for tree traversal and nested data structure parsing. -# -# misc-non-private-member-variables-in-classes: -# Warns when classes have non-private member variables. This project uses -# POD-style structs (CAPHeader, FileInfo, etc.) where public members are -# appropriate. The CheckOption IgnoreClassesWithAllMemberVariablesBeingPublic -# handles most cases but some edge cases remain. -# -# misc-unused-parameters: -# Warns about unused function parameters. These are not a security or safety -# concern. Some parameters are intentionally unused in stub implementations -# or virtual method overrides where the signature is fixed. -# -# misc-use-anonymous-namespace: -# Suggests using anonymous namespaces instead of static for internal linkage. -# We prefer static for C++11 compatibility and consistency with existing code. -# Anonymous namespaces can cause issues with some debuggers. -# -# modernize-avoid-c-arrays: -# Suggests replacing C arrays with std::array. This project uses fixed-size -# C arrays intentionally for protocol buffers, crypto operations, and embedded -# compatibility. std::array adds overhead and isn't always available on AOSP. -# -# modernize-use-auto: -# ENABLED: We now use auto declarations where the type is clear from context -# (e.g., auto it = container.begin(), auto result = SomeFunction()). -# Explicit types are still preferred for numeric types where precision matters. -# -# modernize-use-trailing-return-type: -# ENABLED: We now use trailing return type syntax (auto foo() -> ReturnType) -# for consistency with modern C++ style and better readability with complex -# return types. -# -# modernize-raw-string-literal: -# Suggests R"(...)" for strings with escapes. Not always clearer, especially -# for short strings, and can hurt readability for strings with mixed content. -# -# performance-enum-size: -# Suggests using smaller base types for enums (int8_t instead of int). While -# this could save memory, enums in this project are not in hot paths or large -# arrays where size matters. The default int size aids debugging. -# -# performance-trivially-destructible: -# Suggests defaulting empty destructors in class definitions to make them -# trivially destructible. While technically correct, explicit destructor -# declarations document intent and allow future extension. -# -# performance-no-int-to-ptr: -# Warns about integer-to-pointer casts. Low-level serial and crypto code -# sometimes requires legitimate pointer arithmetic. This check is overly -# broad for systems programming. -# -# performance-noexcept-move-constructor: -# Suggests adding noexcept to move constructors. This project doesn't use -# exceptions (-fno-exceptions on AOSP), so noexcept provides no benefit -# and adds visual noise. -# -# readability-braces-around-statements: -# ENABLED: Project style now requires braces around all if/for/while bodies -# for consistency and to prevent bugs from later additions. -# -# readability-convert-member-functions-to-static: -# Suggests making member functions static when they don't use 'this'. This -# is a design choice - keeping methods as non-static preserves API flexibility -# and allows future refactoring to use member state without API changes. -# -# readability-else-after-return: -# Warns about using 'else' after a return statement. While early return can -# be cleaner, explicit else blocks can improve readability by making all -# branches visually parallel, especially in switch-like if/else chains. -# -# readability-function-cognitive-complexity: -# Measures function complexity and warns above threshold. Complex functions -# in crypto and protocol parsing are sometimes unavoidable. Warnings are -# hard to fix without artificial refactoring that hurts readability. -# -# readability-function-size: -# Warns when functions exceed size thresholds. Crypto functions (OAEP, -# decryption) and protocol parsers are inherently complex and can't be -# split without hurting readability. Test runners also legitimately large. -# -# readability-identifier-length: -# Warns about short variable names (i, n, fd, etc.). These are idiomatic -# in C/C++ for loop indices, counts, and file descriptors. Longer names -# would hurt readability in tight loops. -# -# readability-implicit-bool-conversion: -# Warns about implicit conversions to bool (if (ptr) instead of if (ptr != -# nullptr)). The implicit form is idiomatic C++ and often clearer. -# -# readability-magic-numbers: -# Warns about numeric literals in code. Despite recent cleanup to add named -# constants, many legitimate magic numbers remain (bit shifts, protocol -# offsets, etc.) where inline numbers are clearer than constants. -# -# readability-named-parameter: -# Requires naming all function parameters. We intentionally omit names for -# unused parameters to satisfy -Wunused-parameter: void foo(int /*unused*/) -# -# readability-simplify-boolean-expr: -# Suggests applying DeMorgan's theorem to simplify boolean expressions. While -# mathematically equivalent, the original form (explicit range checks like -# c >= '0' && c <= '9') is often more readable than the transformed version. -# -# readability-make-member-function-const: -# Suggests making member functions const when they don't modify member -# variables. This produces false positives for I/O methods that don't -# modify class state but have observable side effects (serial reads/writes, -# file operations). The check can't detect that calling read()/write() -# on a file descriptor has side effects. -# -# readability-uppercase-literal-suffix: -# Suggests 1UL instead of 1ul for literal suffixes. Low priority style issue -# with many occurrences. Can be enabled later for incremental cleanup. +# bugprone-easily-swappable-parameters: too noisy, fix adds complexity +# bugprone-macro-parentheses: variadic macros can't parenthesize args +# cert-err33-c: fprintf return values in logging are intentionally ignored +# concurrency-mt-unsafe: single-threaded project, standard C idioms fine +# misc-const-correctness: hundreds of warnings, marginal benefit +# misc-include-cleaner: noisy false positives, breaks transitive includes +# misc-no-recursion: intentional recursion for tree traversal / parsing +# misc-non-private-member-variables-in-classes: POD structs use public members +# misc-unused-parameters: intentional in stubs and virtual overrides +# performance-enum-size: not in hot paths; default int aids debugging +# performance-no-int-to-ptr: legitimate in low-level pointer arithmetic +# performance-noexcept-move-constructor: no exceptions in this project +# readability-convert-member-functions-to-static: design choice for API flex +# readability-function-cognitive-complexity: unavoidable in parsers +# readability-function-size: large functions in parsers are sometimes clearest +# readability-identifier-length: short names (i, n, fd) are idiomatic C++ +# readability-implicit-bool-conversion: if (ptr) is idiomatic +# readability-magic-numbers: inline numbers often clearer than constants +# readability-make-member-function-const: false positives on I/O methods +# readability-named-parameter: intentionally omitted for unused params +# readability-redundant-member-init: explicit init documents intent +# readability-simplify-boolean-expr: explicit range checks are more readable # # ============================================================================= Checks: > bugprone-*, - cert-*, - clang-analyzer-*, - -clang-analyzer-core.uninitialized.Assign, - concurrency-*, - misc-*, - modernize-*, - performance-*, - portability-*, - readability-*, -bugprone-easily-swappable-parameters, -bugprone-macro-parentheses, + cert-*, -cert-err33-c, + concurrency-*, -concurrency-mt-unsafe, + cppcoreguidelines-avoid-non-const-global-variables, + cppcoreguidelines-interfaces-global-init, + cppcoreguidelines-pro-type-const-cast, + cppcoreguidelines-pro-type-cstyle-cast, + cppcoreguidelines-rvalue-reference-param-not-moved, + cppcoreguidelines-slicing, + cppcoreguidelines-virtual-class-destructor, + misc-*, -misc-const-correctness, -misc-include-cleaner, -misc-no-recursion, -misc-non-private-member-variables-in-classes, -misc-unused-parameters, - -modernize-raw-string-literal, + modernize-use-auto, + modernize-use-bool-literals, + modernize-use-emplace, + modernize-use-nullptr, + modernize-use-override, + modernize-use-trailing-return-type, + performance-*, -performance-enum-size, -performance-no-int-to-ptr, -performance-noexcept-move-constructor, + portability-*, + readability-*, -readability-convert-member-functions-to-static, -readability-function-cognitive-complexity, -readability-function-size, @@ -199,12 +86,6 @@ Checks: > -readability-named-parameter, -readability-redundant-member-init, -readability-simplify-boolean-expr, - cppcoreguidelines-*, - -cppcoreguidelines-avoid-magic-numbers, - -cppcoreguidelines-pro-bounds-array-to-pointer-decay, - -cppcoreguidelines-pro-bounds-constant-array-index, - -cppcoreguidelines-pro-bounds-pointer-arithmetic, - -cppcoreguidelines-pro-type-reinterpret-cast WarningsAsErrors: '' @@ -219,9 +100,5 @@ CheckOptions: value: 'true' - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic value: true - - key: readability-function-size.LineThreshold - value: 200 - - key: readability-function-size.StatementThreshold - value: 400 - key: modernize-use-trailing-return-type.AllowOverridingMethods value: true diff --git a/.claude/skills/gcc-example/SKILL.md b/.claude/skills/gcc-example/SKILL.md new file mode 100644 index 0000000..e1d9ecc --- /dev/null +++ b/.claude/skills/gcc-example/SKILL.md @@ -0,0 +1,192 @@ +--- +name: gcc-example +description: Building GCC with putup. Use when working on the examples/ BSP directory, debugging GCC build failures, adding new GCC source files to the build, fixing generator issues, or extending the toolchain. Covers 3-tree mode workflow, generator patterns, config headers, and accumulated fixes. +--- + +# GCC Example Build + +The `examples/` BSP directory builds GCC and binutils from source using putup in 3-tree mode. GCC-specific Tupfiles live under `examples/gcc/`. This skill captures the architecture and hard-won knowledge from iterative debugging. + +## Build Command + +```bash +cd /path/to/pup/examples && \ + make -f Makefile.pup SRCDIR=../source-root +``` + +Or directly with putup: + +```bash +cd /path/to/pup/examples && \ + putup configure --config configs/x86_64-linux.config \ + -C . -S ../source-root -B ../build-gcc + putup -C . -S ../source-root -B ../build-gcc -j$(nproc) +``` + +- `-C .` — config tree (BSP root: Tupfiles, tup.config, Tuprules.tup) +- `-S ../source-root` — assembled source tree (gcc/ + binutils/ subdirs, read-only) +- `-B ../build-gcc` — build output directory + +After editing any `tup.config`, re-run `putup configure` to propagate to the build dir. + +## Architecture + +14 build phases in `gcc/gcc/Tupfile`: + +1. **Config headers** (``) — auto-host.h, bconfig.h, config.h, tm.h, tm_p.h, options.h, etc. +2. **Generator bootstrap** — genmodes → insn-modes.h → BUILD_RTL → genconditions → insn-conditions.md +3. **RTL generators** — 20+ generators producing insn-*.h/cc files (``) +4. **Generated source compilation** — compile all generated .cc into `` +5. **Backend objects** — ~445 source files from gcc/ +6. **Common objects** — OBJS-libcommon + OBJS-libcommon-target +7. **cc1 link** — link everything with library archives +8. **xgcc driver** — main gcc/g++ driver executable +9. **cc1plus** — C++ compiler (C++ frontend objects from gcc/cp/) +10. **collect2** — linker wrapper +11. **g++ driver** (xg++) — C++ compilation driver +12. **cpp** — standalone C preprocessor +13. **lto-wrapper** — LTO linker plugin interface +14. **gcov + gcov-dump** — code coverage tools + +### Group Dependencies + +| Group | Purpose | Producers | +|-------|---------|-----------| +| `` | Config/target headers | Phase 1 (auto-host.h, tm.h, options.h, etc.) | +| `` | Generated insn headers | Phase 3 generators | +| `` | GC type descriptors | gengtype | +| `` | All object files | Phases 4-6 | + +### Two Compilation Modes + +**HOST** (generators) — runs on build machine: +``` +HOST_CXXFLAGS = -O0 -std=gnu++14 -DIN_GCC -DGENERATOR_FILE -DHAVE_CONFIG_H +``` + +**TARGET** (cc1 objects) — runs on target: +``` +TARGET_CXXFLAGS = -O2 -std=gnu++14 -DIN_GCC -DHAVE_CONFIG_H +``` + +`-DGENERATOR_FILE` is the key difference. It gates which headers generators see (they skip insn-flags.h, insn-modes.h via guards in tm.h). + +## Generator Patterns + +### Stdout Generators (simple — just redirect) + +```tup +: $(MD) insn-conditions.md | gen-foo |> ^ GEN %o^ \ + $(TUP_VARIANT_OUTPUTDIR)/gen-foo %f > %o |> insn-foo.h +``` + +### File-Output Generators (need cd to build dir) + +Generators with `-O`, `-H`, `-A`, `-D`, `-L`, `-h`, `-c` flags write files relative to CWD. In 3-tree mode CWD is the read-only source dir, so cd first: + +```tup +: $(MD) insn-conditions.md | generator |> ^ GEN outputs^ \ + cd $(TUP_VARIANT_OUTPUTDIR) && ./generator %f \ + -O output-1.cc -O output-2.cc \ + |> output-1.cc output-2.cc +``` + +If `%f` produces relative paths that break after cd, capture CWD first: + +```tup +: $(MD) insn-conditions.md | generator |> ^ GEN outputs^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && \ + ./generator $SRCDIR/common.md $SRCDIR/config/i386/i386.md insn-conditions.md \ + -O output-1.cc -O output-2.cc \ + |> output-1.cc output-2.cc +``` + +Note: `$SRCDIR` and `$PWD` are shell variables (bare `$` passes through putup to shell). + +### genmatch (special case) + +genmatch uses libcpp's `getpwd()` as include search path. `match.pd` includes `cfn-operators.pd` which lives in the build dir. Must cd to build dir AND pass source-relative match.pd path: + +```tup +: $(SRC)/match.pd | genmatch cfn-operators.pd |> ^ GEN gimple-match-*^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && ./genmatch --gimple \ + --header=gimple-match-auto.h --include=gimple-match-auto.h \ + $SRCDIR/match.pd \ + gimple-match-1.cc ... gimple-match-10.cc \ + |> gimple-match-auto.h gimple-match-1.cc ... gimple-match-10.cc +``` + +### gengtype (two-pass) + +gengtype scans GTY-annotated source files. Uses `-DHOST_GENERATOR_FILE` (NOT `-DGENERATOR_FILE`) because it needs full host header access: + +```tup +# Pass 1: write state file +gengtype -S $(SRC) -I gtyp-input.list -w gtype.state +# Pass 2: generate from state +cd $(TUP_VARIANT_OUTPUTDIR) && ./gengtype -r gtype.state +``` + +## Config Headers + +### auto-host.h (from tup.config via !gen-config) + +`CONFIG_FOO=value` in `tup.config` → `#define FOO value` in auto-host.h. + +Key gotchas: +- **Do NOT set `CONFIG_HAVE_UCHAR=1`** — modern Linux doesn't provide `uchar`. GCC's coretypes.h typedefs it when `HAVE_UCHAR` is NOT defined. +- Cross-reference with real `./configure` output for your platform. + +### tm.h (target machine) + +Must match the real configure-generated layout exactly. Key structure: +- LIBC defines (GLIBC, UCLIBC, etc.) outside `#ifdef IN_GCC` +- Target headers inside `#ifdef IN_GCC` +- `insn-flags.h` guarded with `!defined GENERATOR_FILE && !defined USED_FOR_TARGET` +- `insn-modes.h` guarded with `!defined GENERATOR_FILE` +- `defaults.h` at the end + +### tm_p.h (target machine prototypes) + +Must include exactly three headers: +```c +#include "config/i386/i386-protos.h" +#include "config/linux-protos.h" +#include "tm-preds.h" +``` + +The `tm-preds.h` is generated by `genpreds -h` and declares predicate functions like `register_operand`. Missing this causes "undeclared" errors in many files. + +### bconfig.h vs config.h + +- `bconfig.h` — for generators: includes `auto-host.h` + `ansidecl.h` +- `config.h` — for target objects: includes `auto-host.h`, errors if `GENERATOR_FILE` defined + +## Self-Contained Library Convention + +Each library (gmp, mpfr, mpc, libiberty, libcpp, libdecnumber, libbacktrace) has: +- Its own `Tuprules.tup` with `?=` defaults +- Its own `tup.config` for library-specific config +- Its own `Tupfile` for compilation rules + +The root `Tuprules.tup` sets prefixed DIR vars (`GMP_DIR = gmp`, etc.) that override the `?=` defaults when building as part of the larger project. + +## Debugging Workflow + +1. Run the build command +2. Read the **first** error (ignore cascading failures) +3. Diagnose: missing header? → check group deps. Undeclared symbol? → check which generated header provides it. Read-only filesystem? → generator needs cd to build dir. +4. Fix the Tupfile or tup.config +5. If tup.config changed, run `putup configure` to propagate +6. Rebuild and repeat + +## Common Error Patterns + +| Error | Likely Cause | Fix | +|-------|-------------|-----| +| `Read-only file system` | Generator writes to CWD (source dir) | cd to build dir before running | +| `No such file or directory` (generator output) | Same as above | cd to build dir | +| `undeclared` symbol from generated header | Missing group dependency or header include | Check which generator produces it | +| `/bin/sh: ^: not found` | Display text on continuation line | Move `^ ... ^` to same line as `|>` | +| `uchar not declared` | `HAVE_UCHAR` wrongly defined | Remove `CONFIG_HAVE_UCHAR` from tup.config | +| `register_operand undeclared` | `tm_p.h` missing `tm-preds.h` | Add `#include "tm-preds.h"` to tm_p.h generation | diff --git a/.claude/skills/tupfile-patterns/SKILL.md b/.claude/skills/tupfile-patterns/SKILL.md new file mode 100644 index 0000000..b6e34aa --- /dev/null +++ b/.claude/skills/tupfile-patterns/SKILL.md @@ -0,0 +1,210 @@ +--- +name: tupfile-patterns +description: Patterns and gotchas for writing Tupfiles with putup. Use when authoring Tupfiles, debugging build failures, working with 3-tree builds (-C/-S/-B), cross-directory dependencies, order-only groups, bang macros, generator programs, or multi-library projects. Covers Tup syntax that putup supports. +--- + +# Tupfile Patterns + +Reference for writing Tupfiles with putup. See [docs/reference.md](../../../docs/reference.md) for the full manual. + +## Rule Syntax + +```tup +: [foreach] [inputs] [| order-only] |> command |> [outputs] [| extra-outputs] [{group}] [] +``` + +- `%f` — all inputs, `%o` — all outputs, `%b` — input basename, `%B` — basename without extension +- `%d` — input directory, `%e` — extension, `%%` — literal `%` +- Display text: `^ TEXT ^` right after `|>` on the **same line** (never on a continuation line) + +## Variable Expansion vs Shell Variables + +putup expands `$(VAR)` as a Tup variable. Bare `$VAR` passes through to the shell unchanged. + +```tup +# $(CC) expanded by putup at parse time +# $PWD passed through to /bin/sh at execution time +: |> $(CC) -DPREFIX=$PWD -c %f -o %o |> output.o +``` + +This is useful for shell tricks like capturing CWD before `cd`: + +```tup +: |> SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && ./tool $SRCDIR/input |> output +``` + +## Display Text Gotcha + +Display text `^ ... ^` **must** appear on the same line as the opening `|>`. If placed on a continuation line, it becomes part of the shell command. + +```tup +# CORRECT +: input |> ^ CC %b^ $(CC) -c %f -o %o |> output.o + +# CORRECT (continuation after display text) +: input |> ^ CC %b^ \ + $(CC) -c %f -o %o |> output.o + +# WRONG — ^ becomes a shell command +: input |> \ + ^ CC %b^ $(CC) -c %f -o %o |> output.o +``` + +## 3-Tree Builds (-C / -S / -B) + +```bash +putup -C config_dir -S source_dir -B build_dir +``` + +- `-C` — config tree (Tupfiles, tup.config, Tuprules.tup) +- `-S` — source tree (read-only source code) +- `-B` — build tree (output directory) + +Commands run with CWD = source directory. The source tree is **read-only**. + +### Key Variables in 3-Tree Mode + +| Variable | Meaning | +|----------|---------| +| `$(TUP_CWD)` | Config-relative directory of current Tupfile | +| `$(TUP_VARIANT_OUTPUTDIR)` | Absolute path to the build directory | +| `$(S)` (convention) | Usually set to `$(TUP_CWD)` in root Tuprules.tup | +| `$(B)` (convention) | Usually set to `$(TUP_VARIANT_OUTPUTDIR)/$(S)` | + +### Generator Programs in 3-Tree Mode + +Generators that write output files via flags (not stdout) write relative to CWD, which is the read-only source dir. Two approaches: + +**Approach 1: cd to build dir** (preferred for programs that write many files by name) + +```tup +: $(MD) | generator |> ^ GEN outputs^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && \ + ./generator $SRCDIR/input1.md $SRCDIR/input2.md \ + -O output-1.cc -O output-2.cc \ + |> output-1.cc output-2.cc +``` + +Note: inputs that are already in the build dir (previously generated) don't need `$SRCDIR/`. + +**Approach 2: stdout redirect** (preferred for single-output generators) + +```tup +: input.md | generator |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/generator %f > %o |> output.h +``` + +## Order-Only Groups + +Groups create ordering dependencies without file-level dependencies. + +```tup +# Producer: outputs go into group +: |> gen-header > %o |> config.h +: |> gen-header > %o |> types.h + +# Consumer: waits for all members before starting +: src.c | |> $(CC) -c %f -o %o |> src.o +``` + +Cross-directory groups use the `$(S)/dir/` prefix: + +```tup +# In lib/Tupfile: produce into group +: |> generate > %o |> header.h + +# In app/Tupfile: consume from lib's group +: src.c | $(S)/lib/ |> $(CC) -c %f -o %o |> src.o +``` + +## Bang Macros + +Define reusable command templates in `Tuprules.tup`: + +```tup +!cc = |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> + +# With order-only deps (consumers auto-wait) +!cc = | |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> +``` + +Usage in Tupfile: + +```tup +: foreach *.c |> !cc |> %B.o +``` + +## Self-Contained Library Convention + +For multi-library projects (like GCC with GMP, MPFR, MPC): + +**Root `Tuprules.tup`** — sets layout variables: + +```tup +S = $(TUP_CWD) +B = $(TUP_VARIANT_OUTPUTDIR)/$(S) +GMP_DIR = gcc/gmp +MPFR_DIR = gcc/mpfr +``` + +**Each library's `Tuprules.tup`** — uses `?=` defaults for standalone builds: + +```tup +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +GMP_DIR ?= . +CFLAGS = -I$(B)/$(GMP_DIR) -I$(S)/$(GMP_DIR) +!cc = |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> +``` + +`?=` means "set only if undefined". When built as part of the larger project, the root Tuprules.tup values win. When built standalone, the `?=` defaults apply. + +Prefixed DIR vars (`GMP_DIR`, `MPFR_DIR`) are needed because `include_rules` merges ALL `Tuprules.tup` from root to leaf — a single `DIR` variable would collide. + +## Scoped tup.config + +Each subdirectory can have its own `tup.config` for `@(VAR)` config variables: + +``` +project/ + tup.config # Global: CC=gcc, AR=ar + gmp/tup.config # GMP-specific: HAVE_ALLOCA=1 + mpfr/tup.config # MPFR-specific: HAVE_LOCALE=1 +``` + +Run `putup configure` to propagate config files into the build directory. Parent config values override child values (parent wins on conflict). + +## `!gen-config` Pattern + +Convert `tup.config` variables into C `#define` headers: + +```tup +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2); \ + if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(GCC_DIR)/tup.config > %o |> +``` + +`CONFIG_HAVE_MMAP=1` becomes `#define HAVE_MMAP 1`. `CONFIG_HAVE_UCHAR=n` is suppressed. + +## Line Continuation + +Use `\` at end of line. Works in rules and variable assignments: + +```tup +SRCS = file1.c +SRCS += file2.c \ + file3.c \ + file4.c +``` + +## Conditional Compilation + +```tup +ifdef CC + CFLAGS += -Wall +endif + +ifeq ($(TARGET),arm) + CFLAGS += -marm +endif +``` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d56efd8..851df0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,12 +167,30 @@ jobs: path: build/ - name: Fix permissions run: chmod +x build/putup - # clang-tidy 18 (ubuntu default) errors on Checks: '-*' in - # third_party/.clang-tidy ("no checks enabled", exit 1). - # --allow-no-checks was added in 19. See llvm/llvm-project#86355 - - name: Install LLVM 21 - run: | - wget -qO- https://apt.llvm.org/llvm.sh | sudo bash -s -- 21 - sudo apt-get install -y clang-tidy-21 - name: Run clang-tidy - run: make tidy PUTUP=./build/putup RUN_CLANG_TIDY=run-clang-tidy-21 TIDY_FLAGS=-allow-no-checks + run: make tidy PUTUP=./build/putup RUN_CLANG_TIDY=run-clang-tidy-18 + + build-gcc-bsp: + needs: build-linux + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-linux + path: build/ + - name: Fix permissions + run: chmod +x build/putup + - name: Download source + working-directory: examples + run: make -f Makefile.pup download-source SRCDIR=../source-root + - name: Build + working-directory: examples + run: make -f Makefile.pup PUTUP=../build/putup SRCDIR=../source-root + - name: Smoke test cc1 + run: | + echo 'int main() { return 0; }' > /tmp/test.c + build-gcc/gcc/gcc/cc1 /tmp/test.c -quiet -o /tmp/test.s + grep 'GCC.*15.2.0' /tmp/test.s diff --git a/Makefile b/Makefile index b4fa4c6..0631c85 100644 --- a/Makefile +++ b/Makefile @@ -55,11 +55,11 @@ RUN_CLANG_TIDY ?= run-clang-tidy tidy: compdb @echo "Running clang-tidy..." - @$(RUN_CLANG_TIDY) -p . $(TIDY_FLAGS) + @$(RUN_CLANG_TIDY) -p . $(TIDY_FLAGS) 'src/|test/' tidy-fix: compdb @echo "Running clang-tidy with fixes..." - @$(RUN_CLANG_TIDY) -p . -fix $(TIDY_FLAGS) + @$(RUN_CLANG_TIDY) -p . -fix $(TIDY_FLAGS) 'src/|test/' format: @echo "Formatting sources..." diff --git a/docs/reference.md b/docs/reference.md index 2fe38fc..3122288 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -269,6 +269,8 @@ putup # Pass 2: Build with generated configs - `-v` - Verbose output - `-k` - Continue after failures - `-n` - Dry-run: show what would execute +- `-C DIR` - Config directory (where Tupfiles and tup.config live) +- `-S DIR` - Source directory (read-only source tree) - `-B DIR` - Specify build directory (created automatically if it doesn't exist) - `-c, --config FILE` - Install FILE as root tup.config before running config rules diff --git a/examples/Makefile.pup b/examples/Makefile.pup new file mode 100644 index 0000000..9d5e073 --- /dev/null +++ b/examples/Makefile.pup @@ -0,0 +1,116 @@ +# Makefile.pup - Build GCC cross-compiler toolchain with putup +# +# Usage: +# make -f Makefile.pup # Build toolchain (libraries + compilers + tools) +# make -f Makefile.pup clean # Clean build artifacts +# make -f Makefile.pup distclean # Full clean +# +# Assembly support: +# make -f Makefile.pup MPN_CPU=x86_64 # x86-64 arch-level assembly +# make -f Makefile.pup MPN_CPU=x86_64/core2 # CPU-specific assembly +# make -f Makefile.pup MPN_CPU=generic # Pure C (default) +# +# Cross-compiler (macOS host → x86-64 Linux target): +# make -f Makefile.pup PLATFORM=darwin-x86_64-linux HOST=darwin +# +# 3-tree layout: +# -C . BSP root (examples/) +# -S $(SRCDIR) Assembled source tree (gcc/, binutils/ subdirs) +# -B $(BUILD) Build output directory + +.PHONY: all build configure resolve-mpn setup-host-configs \ + clean distclean download-source download-binutils + +PLATFORM ?= x86_64-linux +HOST ?= linux +SRCDIR ?= ../source-root +BUILD ?= ../build-gcc +MPN_CPU ?= generic +PUTUP ?= putup +TREES = -C . -S $(SRCDIR) -B $(BUILD) + +all: build + +build: resolve-mpn setup-host-configs + $(PUTUP) configure --config configs/$(PLATFORM).config $(TREES) + $(PUTUP) $(TREES) -j$$(nproc) + +configure: resolve-mpn setup-host-configs + $(PUTUP) configure --config configs/$(PLATFORM).config $(TREES) + +# Copy host-specific library configs when building for non-Linux hosts. +# Linux configs are the in-tree defaults; other hosts overlay from configs/host-$(HOST)/. +# To restore Linux defaults: git checkout -- gcc/*/tup.config binutils/tup.config +setup-host-configs: + @if [ "$(HOST)" != "linux" ] && [ -d configs/host-$(HOST) ]; then \ + for cfg in configs/host-$(HOST)/*.config; do \ + lib=$$(basename "$$cfg" .config); \ + if [ -f "$$lib/tup.config" ]; then \ + echo " COPY $$lib/tup.config (host-$(HOST))"; \ + cp "$$cfg" "$$lib/tup.config"; \ + elif [ -f "gcc/$$lib/tup.config" ]; then \ + echo " COPY gcc/$$lib/tup.config (host-$(HOST))"; \ + cp "$$cfg" "gcc/$$lib/tup.config"; \ + fi; \ + done; \ + fi + +# Resolve mpn sources for the selected CPU target. +# - gcc/gmp/mpn/tup.config: source lists and per-function toggles (child scope) +# - gcc/gmp/tup.config: GMP_MPARAM and ASM_ENABLED (parent scope, visible to gmp/Tupfile) +resolve-mpn: + @scripts/resolve-mpn.sh $(MPN_CPU) $(SRCDIR)/gcc/gmp/mpn > gcc/gmp/mpn/tup.config + @grep -v '^CONFIG_GMP_MPARAM=\|^CONFIG_ASM_ENABLED=\|^CONFIG_NO_ASM=' gcc/gmp/tup.config > gcc/gmp/tup.config.tmp && mv gcc/gmp/tup.config.tmp gcc/gmp/tup.config + @if [ "$(MPN_CPU)" != "generic" ]; then \ + arch=$${MPN_CPU%%/*}; \ + if [ -f "$(SRCDIR)/gcc/gmp/mpn/$$arch/gmp-mparam.h" ]; then \ + echo "CONFIG_GMP_MPARAM=mpn/$$arch/gmp-mparam.h" >> gcc/gmp/tup.config; \ + else \ + echo "CONFIG_GMP_MPARAM=mpn/generic/gmp-mparam.h" >> gcc/gmp/tup.config; \ + fi; \ + echo "CONFIG_ASM_ENABLED=y" >> gcc/gmp/tup.config; \ + else \ + echo "CONFIG_GMP_MPARAM=mpn/generic/gmp-mparam.h" >> gcc/gmp/tup.config; \ + echo "CONFIG_NO_ASM=1" >> gcc/gmp/tup.config; \ + fi + +# Multi-variant: build for multiple platforms in parallel +# make -f Makefile.pup multi SRCDIR=../source-root +PLATFORMS ?= x86_64-linux aarch64-linux +multi: + @for p in $(PLATFORMS); do \ + $(PUTUP) configure --config configs/$$p.config -C . -S $(SRCDIR) -B $(BUILD)-$$p; \ + done + $(PUTUP) $(foreach p,$(PLATFORMS),-B $(BUILD)-$(p)) -C . -S $(SRCDIR) -j$$(nproc) + +# Download and assemble source tree. +# Source assembly: extract each tarball, rename into $(SRCDIR)/. +GCC_VERSION ?= 15.2.0 +BINUTILS_VERSION ?= 2.44 + +download-source: download-binutils + @if [ ! -d "$(SRCDIR)/gcc" ]; then \ + echo "Downloading GCC $(GCC_VERSION)..."; \ + mkdir -p $(SRCDIR)/gcc; \ + curl -L "https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz" \ + | tar xJ --strip-components=1 -C $(SRCDIR)/gcc; \ + cd $(SRCDIR)/gcc && ./contrib/download_prerequisites; \ + else \ + echo "$(SRCDIR)/gcc already exists"; \ + fi + +download-binutils: + @if [ ! -d "$(SRCDIR)/binutils" ]; then \ + echo "Downloading binutils $(BINUTILS_VERSION)..."; \ + mkdir -p $(SRCDIR)/binutils; \ + curl -L "https://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.xz" \ + | tar xJ --strip-components=1 -C $(SRCDIR)/binutils; \ + else \ + echo "$(SRCDIR)/binutils already exists"; \ + fi + +clean: + $(PUTUP) clean $(TREES) + +distclean: + $(PUTUP) distclean $(TREES) diff --git a/examples/README.md b/examples/README.md index 2843ffc..992a5f8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,6 +1,133 @@ -# Putup Examples +# BSP — Board Support Package Example -| Example | Description | -|---------|-------------| -| [helloworld](helloworld/) | Minimal single-file C project | -| [busybox](busybox/) | Cross-compile Busybox (33 Tupfiles, 403 applets) | +A complete cross-compiler toolchain built from source using putup. +Demonstrates multi-tarball, multi-package builds with 3-tree mode (`-C`, `-S`, `-B`). + +## Packages + +``` +gcc/ GCC tarball group (gcc-15.2.0) + gcc/ Compiler: cc1, cc1plus, xgcc, xg++, cpp, collect2, ... + gmp/ Math library: libgmp.a + mpfr/ Multi-precision floats: libmpfr.a + mpc/ Complex arithmetic: libmpc.a + libiberty/ Utility library: libiberty.a + libcpp/ C preprocessor: libcpp.a + libdecnumber/ Decimal floating-point: libdecnumber.a + libbacktrace/ Stack unwinding: libbacktrace.a + libcody/ C++ modules protocol: libcody.a + +binutils/ binutils tarball group (binutils-2.44) + Cross-assembler (as) + cross-archiver (ar) + +busybox/ busybox (deferred — not yet BSP-integrated) +helloworld/ test package (deferred — not yet BSP-integrated) +``` + +## Source Tree Assembly + +Each top-level config directory maps to one extracted tarball. +Assemble the source tree by extracting and renaming: + +```bash +mkdir -p source-root +# GCC (includes GMP, MPFR, MPC via download_prerequisites) +tar xf gcc-15.2.0.tar.xz +mv gcc-15.2.0 source-root/gcc +cd source-root/gcc && ./contrib/download_prerequisites && cd ../.. + +# binutils +tar xf binutils-2.44.tar.xz +mv binutils-2.44 source-root/binutils +``` + +The config tree (`-C examples/`) mirrors the source tree (`-S source-root/`): + +``` +examples/ (config tree) source-root/ (source tree) +├── gcc/ ├── gcc/ +│ ├── gcc/ │ ├── gcc/ +│ ├── gmp/ │ ├── gmp/ +│ └── ... │ └── ... +└── binutils/ └── binutils/ +``` + +## Quick Start + +```bash +cd examples + +# Assemble source tree (or use: make -f Makefile.pup download-source) +# ... see above ... + +# Build (macOS host → x86-64 Linux target) +make -f Makefile.pup SRCDIR=../source-root PLATFORM=darwin-x86_64-linux HOST=darwin + +# Or directly with putup: +putup configure --config configs/darwin-x86_64-linux.config \ + -C . -S ../source-root -B ../build-gcc +putup -C . -S ../source-root -B ../build-gcc -j8 +``` + +## Scoped Builds + +Build individual packages without rebuilding everything: + +```bash +# Just binutils +putup -C . -S ../source-root -B ../build-gcc binutils/ + +# Just the GCC compiler (assuming libraries are already built) +putup -C . -S ../source-root -B ../build-gcc gcc/gcc/ + +# Just GMP +putup -C . -S ../source-root -B ../build-gcc gcc/gmp/ +``` + +## Standalone Mode + +Each package group is independently buildable. The `?=` defaults in each +package's `Tuprules.tup` provide flat paths when there's no BSP root above: + +```bash +# Build just the GCC group (standalone) +cd gcc +putup configure -S /path/to/gcc-15.2.0 -B /path/to/build +putup -S /path/to/gcc-15.2.0 -B /path/to/build +``` + +## Makefile Targets + +| Target | Description | +|--------|-------------| +| `make -f Makefile.pup` | Full build (resolve-mpn + configure + build) | +| `make -f Makefile.pup configure` | Configure only (no build) | +| `make -f Makefile.pup download-source` | Download GCC + binutils tarballs into `SRCDIR` | +| `make -f Makefile.pup clean` | Clean build artifacts | +| `make -f Makefile.pup distclean` | Full clean (remove build directory) | +| `make -f Makefile.pup multi` | Multi-variant parallel build for `PLATFORMS` | + +**Variables:** + +| Variable | Default | Description | +|----------|---------|-------------| +| `PLATFORM` | `x86_64-linux` | Config file selector (`configs/$(PLATFORM).config`) | +| `HOST` | `linux` | Host OS (overlays `configs/host-$(HOST)/` if not linux) | +| `SRCDIR` | `../source-root` | Assembled source tree path | +| `BUILD` | `../build-gcc` | Build output directory | +| `MPN_CPU` | `generic` | GMP assembly target (`generic`, `x86_64`, `x86_64/core2`) | +| `PUTUP` | `putup` | Path to putup binary (override for CI) | +| `GCC_VERSION` | `15.2.0` | GCC tarball version for `download-source` | +| `BINUTILS_VERSION` | `2.44` | binutils tarball version for `download-source` | + +## Architecture + +- **Root `Tuprules.tup`** uses `=` (force-set) for all DIR variables (e.g. `GCC_DIR = gcc/gcc`, `BINUTILS_DIR = binutils`) +- **Group `Tuprules.tup`** uses `?=` (default) — overridden in BSP mode, effective standalone +- **Package `Tuprules.tup`** uses `?=` for toolchain vars — overridden by both root and group +- `include_rules` processes root-first; BSP root wins over group defaults + +## Known Limitations + +- putup `create_directories` crashes on symlinks in source tree +- busybox and helloworld are not yet BSP-integrated (no `Tupfile.ini` — excluded from BSP scan) diff --git a/examples/Tupfile b/examples/Tupfile new file mode 100644 index 0000000..f426d5e --- /dev/null +++ b/examples/Tupfile @@ -0,0 +1,23 @@ +include_rules + +# Root Tupfile - nothing to do here +# Packages are built by their respective Tupfiles: +# +# GCC tarball (gcc/): +# gcc/gmp/Tupfile → libgmp.a +# gcc/mpfr/src/Tupfile → libmpfr.a +# gcc/mpc/src/Tupfile → libmpc.a +# gcc/libiberty/Tupfile → libiberty.a +# gcc/libdecnumber/Tupfile → libdecnumber.a +# gcc/libbacktrace/Tupfile → libbacktrace.a +# gcc/libcpp/Tupfile → libcpp.a +# gcc/libcody/Tupfile → libcody.a +# gcc/gcc/Tupfile → cc1, cc1plus, xgcc, xg++, cpp, collect2, ... +# gcc/gcc/c/Tupfile → C frontend objects +# gcc/gcc/cp/Tupfile → C++ frontend objects +# gcc/gcc/c-family/Tupfile → C-family shared objects +# gcc/gcc/analyzer/Tupfile → Static analyzer objects +# gcc/gcc/targets/x86_64-pc-linux-gnu.tup → x86_64 target rules (included by gcc/gcc/Tupfile) +# +# binutils tarball (binutils/): +# binutils/Tupfile → as (cross-assembler), ar (cross-archiver) diff --git a/examples/Tupfile.ini b/examples/Tupfile.ini new file mode 100644 index 0000000..10c3ed8 --- /dev/null +++ b/examples/Tupfile.ini @@ -0,0 +1 @@ +# BSP - pup build configuration diff --git a/examples/Tuprules.tup b/examples/Tuprules.tup new file mode 100644 index 0000000..4111dca --- /dev/null +++ b/examples/Tuprules.tup @@ -0,0 +1,27 @@ +# Tuprules.tup - BSP root rules +# +# Sets project-wide variables from tup.config. +# Per-package rules live in each package's own Tuprules.tup. +# Uses = (force-set) so these override ?= defaults in group/package rules. + +S = $(TUP_CWD) +B = $(TUP_VARIANT_OUTPUTDIR)/$(S) + +CC = @(CC) +CXX = @(CXX) +AR = @(AR) +HOSTCC = @(HOSTCC) + +# GCC tarball group +GCC_DIR = gcc/gcc +GMP_DIR = gcc/gmp +MPFR_DIR = gcc/mpfr +MPC_DIR = gcc/mpc +LIBIBERTY_DIR = gcc/libiberty +LIBCPP_DIR = gcc/libcpp +LIBDECNUMBER_DIR = gcc/libdecnumber +LIBBACKTRACE_DIR = gcc/libbacktrace +LIBCODY_DIR = gcc/libcody + +# binutils tarball group +BINUTILS_DIR = binutils diff --git a/examples/binutils/Tupfile b/examples/binutils/Tupfile new file mode 100644 index 0000000..fba2135 --- /dev/null +++ b/examples/binutils/Tupfile @@ -0,0 +1,175 @@ +include_rules + +# ============================================================ +# binutils — cross-assembler (as) + cross-archiver (ar) +# +# Single Tupfile avoids cross-directory group issues in 3-tree mode. +# Source paths use $(BFD)/, $(GAS)/, $(OPC)/, $(BU_BIN)/ prefixes. +# ============================================================ + +BFD = $(BU)/bfd +GAS = $(BU)/gas +OPC = $(BU)/opcodes +BU_BIN = $(BU)/binutils +OUT = $(B)/$(BINUTILS_DIR) + +# --- Phase 1: Generated headers --- + +# config.h from tup.config +: |> !gen-config |> config.h + +# bfd.h — substitute autoconf placeholders in bfd-in2.h +: |> ^ GEN %o^ sed \ + -e 's/@wordsize@/64/g' \ + -e 's/@bfd_default_target_size@/64/g' \ + -e 's/@BFD_DEFAULT_TARGET_SIZE@/64/g' \ + -e 's/@BFD64@/#define BFD64 1/g' \ + -e 's/@BFD_HOST_64BIT_LONG@/1/g' \ + -e 's/@BFD_HOST_LONG_LONG@/1/g' \ + -e 's/@BFD_HOST_64_BIT@/long/g' \ + -e 's/@BFD_HOST_U_64_BIT@/unsigned long/g' \ + -e 's/@bfd_file_ptr@/long/g' \ + -e 's/@bfd_ufile_ptr@/unsigned long/g' \ + -e 's/@supports_plugins@/0/g' \ + $(BFD)/bfd-in2.h > %o |> bfd.h + +# bfd_stdint.h — trivial wrapper (modern systems have stdint.h) +: |> ^ GEN %o^ printf '%s\n' '#include ' > %o |> bfd_stdint.h + +# targmatch.h — target matching table for x86_64 ELF targets +: |> ^ GEN %o^ printf '%s\n' \ + '/* Generated — x86_64-pc-linux-gnu target */' \ + '{ "x86_64-*-linux*", &x86_64_elf64_vec },' \ + '{ "x86_64-*-elf*", &x86_64_elf64_vec },' \ + '{ "i[3-7]86-*-linux*", &i386_elf32_vec },' > %o |> targmatch.h + +# bfdver.h — substitute version placeholders in version.h +: |> ^ GEN %o^ sed \ + -e 's/@bfd_version@/244000000/g' \ + -e 's/@bfd_version_string@/"2.44"/g' \ + -e 's/@bfd_version_package@/"(GNU Binutils)"/g' \ + -e 's/@report_bugs_to@/""/g' \ + $(BFD)/version.h > %o |> bfdver.h + +# gas target headers — redirect to concrete config files for x86_64-linux-elf +: |> ^ GEN %o^ echo '#include "tc-i386.h"' > %o |> targ-cpu.h +: |> ^ GEN %o^ echo '#include "obj-elf.h"' > %o |> obj-format.h +: |> ^ GEN %o^ echo '#include "te-linux.h"' > %o |> targ-env.h + +# elf32-target.h / elf64-target.h — elfxx-target.h with NN substitution +: |> ^ GEN %o^ sed 's/elfNN/elf32/g;s/ELFNN/ELF32/g' $(BFD)/elfxx-target.h > %o |> elf32-target.h +: |> ^ GEN %o^ sed 's/elfNN/elf64/g;s/ELFNN/ELF64/g' $(BFD)/elfxx-target.h > %o |> elf64-target.h + +# --- Phase 2: BFD objects --- +# Core BFD library + ELF x86_64 backend. +# Batch compile: sources are outside the project tree, so we reference +# them only in the command (not as tup inputs). Output prefix bfd- +# avoids collisions with gas (both have hash.c, stabs.c). + +bfd_names = archive archures bfd bfdio cache +bfd_names += coffgen compress corefile format hash +bfd_names += init libbfd linker merge opncls +bfd_names += reloc section simple stab-syms stabs +bfd_names += syms targets +bfd_names += elf elf-properties elf-strtab elflink +bfd_names += elf-eh-frame elf-ifunc elf-vxworks elf-attrs elf-sframe +bfd_names += dwarf1 dwarf2 archive64 +bfd_names += elf64 elf64-x86-64 elfxx-x86 cpu-i386 +bfd_names += elf64-gen elf32-gen elf32 elf32-i386 +bfd_names += binary ihex srec tekhex verilog + +: | |> ^ CC-BFD (38 files)^ for f in $(bfd_names); do \ + $(CC) $(CFLAGS) $(BFD_INCLUDES) -c $(BFD)/$$f.c -o $(OUT)/bfd-$$f.o || exit 1; \ + done |> \ + bfd-archive.o bfd-archures.o bfd-bfd.o bfd-bfdio.o bfd-cache.o \ + bfd-coffgen.o bfd-compress.o bfd-corefile.o bfd-format.o bfd-hash.o \ + bfd-init.o bfd-libbfd.o bfd-linker.o bfd-merge.o bfd-opncls.o \ + bfd-reloc.o bfd-section.o bfd-simple.o bfd-stab-syms.o bfd-stabs.o \ + bfd-syms.o bfd-targets.o \ + bfd-elf.o bfd-elf-properties.o bfd-elf-strtab.o bfd-elflink.o \ + bfd-elf-eh-frame.o bfd-elf-ifunc.o bfd-elf-vxworks.o bfd-elf-attrs.o bfd-elf-sframe.o \ + bfd-dwarf1.o bfd-dwarf2.o bfd-archive64.o \ + bfd-elf64.o bfd-elf64-x86-64.o bfd-elfxx-x86.o bfd-cpu-i386.o \ + bfd-elf64-gen.o bfd-elf32-gen.o bfd-elf32.o bfd-elf32-i386.o \ + bfd-binary.o bfd-ihex.o bfd-srec.o bfd-tekhex.o bfd-verilog.o \ + + +# --- Phase 2b: libsframe objects --- +# SFrame stack-trace format library, needed by elf-sframe.c in BFD. + +SFRAME = $(BU)/libsframe +SFRAME_INCLUDES = -I$(B)/$(BINUTILS_DIR) -I$(SFRAME) -I$(BU)/libctf -I$(BU)/include + +sframe_names = sframe sframe-error + +: | |> ^ CC-SFRAME (2 files)^ for f in $(sframe_names); do \ + $(CC) $(CFLAGS) $(SFRAME_INCLUDES) -c $(SFRAME)/$$f.c -o $(OUT)/sframe-$$f.o || exit 1; \ + done |> \ + sframe-sframe.o sframe-sframe-error.o \ + + +# --- Phase 3: Opcodes objects --- +# x86 instruction decode/encode tables + +opc_names = dis-init disassemble dis-buf i386-dis + +: | |> ^ CC-OPC (4 files)^ for f in $(opc_names); do \ + $(CC) $(CFLAGS) $(BFD_INCLUDES) -I$(OPC) -c $(OPC)/$$f.c -o $(OUT)/opc-$$f.o || exit 1; \ + done |> \ + opc-dis-init.o opc-disassemble.o opc-dis-buf.o opc-i386-dis.o \ + + +# --- Phase 4: Gas (assembler) objects --- +# Output prefix gas- avoids collisions with bfd (hash.c, stabs.c). + +gas_names = app as atof-generic compress-debug cond +gas_names += depend dwarf2dbg dw2gencfi ecoff ehopt +gas_names += expr flonum-copy flonum-konst flonum-mult +gas_names += frags hash input-file input-scrub listing +gas_names += literal macro messages output-file read +gas_names += remap sb stabs subsegs symbols write +gas_names += ginsn scfi scfidw2gen gen-sframe sframe-opt codeview + +gas_target_names = tc-i386 obj-elf atof-ieee + +: | |> ^ CC-GAS (39 files)^ \ + for f in $(gas_names); do \ + $(CC) $(CFLAGS) $(GAS_INCLUDES) $(BFD_INCLUDES) -c $(GAS)/$$f.c -o $(OUT)/gas-$$f.o || exit 1; \ + done; \ + for f in $(gas_target_names); do \ + $(CC) $(CFLAGS) $(GAS_INCLUDES) $(BFD_INCLUDES) -c $(GAS)/config/$$f.c -o $(OUT)/gas-$$f.o || exit 1; \ + done |> \ + gas-app.o gas-as.o gas-atof-generic.o gas-compress-debug.o gas-cond.o \ + gas-depend.o gas-dwarf2dbg.o gas-dw2gencfi.o gas-ecoff.o gas-ehopt.o \ + gas-expr.o gas-flonum-copy.o gas-flonum-konst.o gas-flonum-mult.o \ + gas-frags.o gas-hash.o gas-input-file.o gas-input-scrub.o gas-listing.o \ + gas-literal.o gas-macro.o gas-messages.o gas-output-file.o gas-read.o \ + gas-remap.o gas-sb.o gas-stabs.o gas-subsegs.o gas-symbols.o gas-write.o \ + gas-ginsn.o gas-scfi.o gas-scfidw2gen.o gas-gen-sframe.o gas-sframe-opt.o gas-codeview.o \ + gas-tc-i386.o gas-obj-elf.o gas-atof-ieee.o \ + + +# --- Phase 5: Link as (cross-assembler) --- + +: $(LIBIBERTY_A) |> ^ LINK as^ \ + $(CC) % % % % $(LIBIBERTY_A) \ + -lz @(PLATFORM_LDFLAGS) -o %o |> as + +# --- Phase 6: ar (cross-archiver) objects --- + +ar_names = ar arsup not-ranlib bucomm rename binemul emul_vanilla version filemode arparse arlex + +: | |> ^ CC-BU (11 files)^ for f in $(ar_names); do \ + $(CC) $(CFLAGS) $(BINUTILS_INCLUDES) $(BFD_INCLUDES) \ + -Dbin_dummy_emulation=bin_vanilla_emulation \ + -c $(BU_BIN)/$$f.c -o $(OUT)/$$f.o || exit 1; \ + done |> \ + ar.o arsup.o not-ranlib.o bucomm.o rename.o binemul.o emul_vanilla.o \ + version.o filemode.o arparse.o arlex.o \ + + +# --- Phase 7: Link ar (cross-archiver) --- + +: $(LIBIBERTY_A) |> ^ LINK ar^ \ + $(CC) % % % $(LIBIBERTY_A) \ + -lz @(PLATFORM_LDFLAGS) -o %o |> ar diff --git a/examples/binutils/Tuprules.tup b/examples/binutils/Tuprules.tup new file mode 100644 index 0000000..edada26 --- /dev/null +++ b/examples/binutils/Tuprules.tup @@ -0,0 +1,33 @@ +# binutils build rules (self-contained with ?= defaults) +# +# Composed mode: parent sets S, B, CC, AR, LIBIBERTY_DIR, BINUTILS_DIR. +# Standalone mode: ?= defaults take effect. + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= clang +AR_CMD ?= ar +LIBIBERTY_DIR ?= libiberty +BINUTILS_DIR ?= . + +# Binutils source root — resolved via $(S)/$(BINUTILS_DIR) +BU = $(S)/$(BINUTILS_DIR) + +# Resolved library paths +LIBIBERTY_A = $(B)/$(LIBIBERTY_DIR)/libiberty.a + +# Include paths +BFD_INCLUDES = -I$(B)/$(BINUTILS_DIR) -I$(BU)/bfd -I$(BU)/include +GAS_INCLUDES = -I$(B)/$(BINUTILS_DIR) -I$(BU)/gas -I$(BU)/gas/config -I$(BU)/include -I$(BU)/bfd -I$(BU) +BINUTILS_INCLUDES = -I$(B)/$(BINUTILS_DIR) -I$(BU)/binutils -I$(BU)/include -I$(BU)/bfd + +CFLAGS = -O2 -DHAVE_CONFIG_H + +!cc-bfd = | $(S)/$(BINUTILS_DIR)/ |> ^ CC-BFD %b^ $(CC) $(CFLAGS) $(BFD_INCLUDES) -c %f -o %o |> +!cc-opcodes = | $(S)/$(BINUTILS_DIR)/ |> ^ CC-OPC %b^ $(CC) $(CFLAGS) $(BFD_INCLUDES) -I$(BU)/opcodes -c %f -o %o |> +!cc-gas = | $(S)/$(BINUTILS_DIR)/ |> ^ CC-GAS %b^ $(CC) $(CFLAGS) $(GAS_INCLUDES) $(BFD_INCLUDES) -c %f -o %o |> +!cc-binutils = | $(S)/$(BINUTILS_DIR)/ |> ^ CC-BU %b^ $(CC) $(CFLAGS) $(BINUTILS_INCLUDES) $(BFD_INCLUDES) -c %f -o %o |> + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(BINUTILS_DIR)/tup.config > %o |> diff --git a/examples/binutils/tup.config b/examples/binutils/tup.config new file mode 100644 index 0000000..2c292bb --- /dev/null +++ b/examples/binutils/tup.config @@ -0,0 +1,111 @@ +# binutils - x86_64 Linux host, x86_64-linux target +# +# BFD, opcodes, and gas share this config.h. +# Key: BFD64 for 64-bit targets, ELF backend, Linux/glibc host capabilities. + +# Package identity +CONFIG_PACKAGE="binutils" +CONFIG_PACKAGE_VERSION="2.44" + +# BFD64 required for x86_64 targets +CONFIG_BFD64=1 + +# Target selection +CONFIG_TARGET="x86_64-pc-linux-gnu" +CONFIG_TARGET_CPU="i386" +CONFIG_DEFAULT_BFD_ARCH=bfd_i386_arch +CONFIG_DEFAULT_BFD_VEC=x86_64_elf64_vec +CONFIG_SELECT_ARCHITECTURES=&bfd_i386_arch +CONFIG_TARG_ARCHS=&bfd_i386_arch +CONFIG_SELECT_VECS=&x86_64_elf64_vec,&i386_elf32_vec,&x86_64_elf32_vec + +# Host capabilities (Linux/glibc x86_64) +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_MPROTECT=1 +CONFIG_HAVE_FCNTL=1 +CONFIG_HAVE_GETPAGESIZE=1 +CONFIG_HAVE_FOPEN64=1 +CONFIG_HAVE_FSEEKO64=1 +CONFIG_HAVE_FSEEKO=1 + +# Standard headers +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_ERRNO_H=1 +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_ZLIB_H=1 + +# Type sizes (LP64) +CONFIG_SIZEOF_VOID_P=8 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_LONG_LONG=8 +CONFIG_SIZEOF_OFF_T=8 + +# Declarations +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_VASPRINTF=1 +CONFIG_HAVE_DECL_SNPRINTF=1 +CONFIG_HAVE_DECL_VSNPRINTF=1 +CONFIG_HAVE_DECL_STPCPY=1 +CONFIG_HAVE_DECL_STRNLEN=1 +CONFIG_HAVE_DECL_FFS=1 +CONFIG_HAVE_DECL_GETENV=1 +CONFIG_HAVE_DECL_BASENAME=1 +CONFIG_HAVE_DECL_MALLOC=1 +CONFIG_HAVE_DECL_REALLOC=1 +CONFIG_HAVE_DECL_SBRK=1 +CONFIG_HAVE_DECL_ENVIRON=1 +CONFIG_HAVE_DECL_STRSTR=1 + +# Functions +CONFIG_HAVE_ASPRINTF=1 +CONFIG_HAVE_VASPRINTF=1 +CONFIG_HAVE_REALPATH=1 +CONFIG_HAVE_MKDTEMP=1 +CONFIG_HAVE_MKSTEMP=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_SBRK=1 +CONFIG_HAVE_GETRLIMIT=1 + +# C standard +CONFIG_STDC_HEADERS=1 + +# Misc +CONFIG_USE_BINARY_FOPEN=n +CONFIG_NEED_DECLARATION_ENVIRON=0 +CONFIG_NEED_DECLARATION_FFS=n +CONFIG_DEFAULT_AR_DETERMINISTIC=1 +CONFIG_HAVE_UTIMES=1 + +# Gas target identity +CONFIG_TARGET_ALIAS="x86_64-pc-linux-gnu" +CONFIG_TARGET_CANONICAL="x86_64-pc-linux-gnu" +CONFIG_VERSION="2.44" + +# Gas defaults +CONFIG_DEFAULT_GENERATE_ELF_STT_COMMON=0 +CONFIG_DEFAULT_GENERATE_BUILD_NOTES=0 +CONFIG_DEFAULT_COMPRESSED_DEBUG_ALGORITHM=0 +CONFIG_HAVE_STRSIGNAL=1 +CONFIG_DEFAULT_X86_USED_NOTE=0 +CONFIG_DEFAULT_GENERATE_X86_RELAX_RELOCATIONS=1 +CONFIG_DEFAULT_X86_TLS_CHECK=0 + +# Thread-local storage keyword +CONFIG_TLS=__thread + +# Debug info directory +CONFIG_DEBUGDIR="/usr/lib/debug" diff --git a/examples/busybox/README.md b/examples/busybox/README.md index 899fe66..2a964e7 100644 --- a/examples/busybox/README.md +++ b/examples/busybox/README.md @@ -36,7 +36,6 @@ putup build-android build-freebsd -j$(nproc) | File | Purpose | |------|---------| | `Makefile.pup` | Make wrapper for putup commands | -| `Tupfile.ini` | Project root marker | | `Tuprules.tup` | Compiler flags and macros | | `Tupfile` | Config generation + source compilation rules | | `scripts/kconfig/Tupfile` | Builds kconfig conf tool | diff --git a/examples/busybox/Tupfile.ini b/examples/busybox/Tupfile.ini deleted file mode 100644 index 2b3d4f6..0000000 --- a/examples/busybox/Tupfile.ini +++ /dev/null @@ -1 +0,0 @@ -# Busybox - pup build configuration diff --git a/examples/configs/aarch64-linux.config b/examples/configs/aarch64-linux.config new file mode 100644 index 0000000..fd73b97 --- /dev/null +++ b/examples/configs/aarch64-linux.config @@ -0,0 +1,22 @@ +# GCC Libraries - AArch64 Linux cross-compile toolchain +# +# Usage: +# putup configure --config configs/aarch64-linux.config -S ../gcc-15.2.0 -B ../build-gcc-aarch64 +# +# Per-library configs live in gmp/tup.config, mpfr/tup.config, mpc/tup.config. +# Scoped config merging combines these with the toolchain vars below. + +# Toolchain (cross-compiler) +CONFIG_CC=aarch64-linux-gnu-gcc +CONFIG_CXX=aarch64-linux-gnu-g++ +CONFIG_AR=aarch64-linux-gnu-ar +CONFIG_HOSTCC=g++ + +# Platform selection (same x86_64 target, cross-compiled from Linux host) +CONFIG_TARGET=x86_64-pc-linux-gnu +CONFIG_HOST_OS=linux +CONFIG_PLATFORM_LDFLAGS=-lm -ldl -lpthread -lz +CONFIG_EXTRA_MODES_FILE=config/i386/i386-modes.def +CONFIG_DECIMAL_FORMAT=bid +CONFIG_BACKTRACE_FORMAT=elf +CONFIG_BACKTRACE_ELF_SIZE=64 diff --git a/examples/configs/darwin-x86_64-linux.config b/examples/configs/darwin-x86_64-linux.config new file mode 100644 index 0000000..bf3c1c4 --- /dev/null +++ b/examples/configs/darwin-x86_64-linux.config @@ -0,0 +1,20 @@ +# GCC Libraries - macOS host, x86-64 Linux target (cross-compiler) +# +# Usage: +# make -f Makefile.pup PLATFORM=darwin-x86_64-linux HOST=darwin +# +# Builds cc1 on macOS (Apple Silicon) that generates x86_64 Linux code. +# Host compiler is Apple Clang; target config reuses x86_64-pc-linux-gnu. + +# Toolchain (Apple Clang as host compiler) +CONFIG_CC=clang +CONFIG_CXX=clang++ +CONFIG_AR=ar +CONFIG_HOSTCC=clang++ + +# Platform selection +CONFIG_TARGET=x86_64-pc-linux-gnu +CONFIG_HOST_OS=darwin +CONFIG_PLATFORM_LDFLAGS=-lm -lpthread -lz -liconv +CONFIG_EXTRA_MODES_FILE=config/i386/i386-modes.def +CONFIG_DECIMAL_FORMAT=bid diff --git a/examples/configs/host-darwin/binutils.config b/examples/configs/host-darwin/binutils.config new file mode 100644 index 0000000..246437e --- /dev/null +++ b/examples/configs/host-darwin/binutils.config @@ -0,0 +1,111 @@ +# binutils - macOS (aarch64-apple-darwin) host, x86_64-linux target +# +# BFD, opcodes, and gas share this config.h. +# Key: BFD64 for 64-bit targets, ELF backend, macOS host capabilities. + +# Package identity +CONFIG_PACKAGE="binutils" +CONFIG_PACKAGE_VERSION="2.44" + +# BFD64 required for x86_64 targets +CONFIG_BFD64=1 + +# Target selection +CONFIG_TARGET="x86_64-pc-linux-gnu" +CONFIG_TARGET_CPU="i386" +CONFIG_DEFAULT_BFD_ARCH=bfd_i386_arch +CONFIG_DEFAULT_BFD_VEC=x86_64_elf64_vec +CONFIG_SELECT_ARCHITECTURES=&bfd_i386_arch +CONFIG_TARG_ARCHS=&bfd_i386_arch +CONFIG_SELECT_VECS=&x86_64_elf64_vec,&i386_elf32_vec,&x86_64_elf32_vec + +# Host capabilities (macOS/Darwin aarch64) +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_MPROTECT=1 +CONFIG_HAVE_FCNTL=1 +CONFIG_HAVE_GETPAGESIZE=1 +CONFIG_HAVE_FOPEN64=n +CONFIG_HAVE_FSEEKO64=n +CONFIG_HAVE_FSEEKO=1 + +# Standard headers +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_ERRNO_H=1 +CONFIG_HAVE_ALLOCA_H=n +CONFIG_HAVE_ZLIB_H=1 + +# Type sizes (LP64) +CONFIG_SIZEOF_VOID_P=8 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_LONG_LONG=8 +CONFIG_SIZEOF_OFF_T=8 + +# Declarations +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_VASPRINTF=1 +CONFIG_HAVE_DECL_SNPRINTF=1 +CONFIG_HAVE_DECL_VSNPRINTF=1 +CONFIG_HAVE_DECL_STPCPY=1 +CONFIG_HAVE_DECL_STRNLEN=1 +CONFIG_HAVE_DECL_FFS=1 +CONFIG_HAVE_DECL_GETENV=1 +CONFIG_HAVE_DECL_BASENAME=0 +CONFIG_HAVE_DECL_MALLOC=1 +CONFIG_HAVE_DECL_REALLOC=1 +CONFIG_HAVE_DECL_SBRK=0 +CONFIG_HAVE_DECL_ENVIRON=0 +CONFIG_HAVE_DECL_STRSTR=1 + +# Functions +CONFIG_HAVE_ASPRINTF=1 +CONFIG_HAVE_VASPRINTF=1 +CONFIG_HAVE_REALPATH=1 +CONFIG_HAVE_MKDTEMP=1 +CONFIG_HAVE_MKSTEMP=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_SBRK=1 +CONFIG_HAVE_GETRLIMIT=1 + +# C standard +CONFIG_STDC_HEADERS=1 + +# Misc +CONFIG_USE_BINARY_FOPEN=n +CONFIG_NEED_DECLARATION_ENVIRON=1 +CONFIG_NEED_DECLARATION_FFS=n +CONFIG_DEFAULT_AR_DETERMINISTIC=1 +CONFIG_HAVE_UTIMES=1 + +# Gas target identity +CONFIG_TARGET_ALIAS="x86_64-pc-linux-gnu" +CONFIG_TARGET_CANONICAL="x86_64-pc-linux-gnu" +CONFIG_VERSION="2.44" + +# Gas defaults +CONFIG_DEFAULT_GENERATE_ELF_STT_COMMON=0 +CONFIG_DEFAULT_GENERATE_BUILD_NOTES=0 +CONFIG_DEFAULT_COMPRESSED_DEBUG_ALGORITHM=0 +CONFIG_HAVE_STRSIGNAL=1 +CONFIG_DEFAULT_X86_USED_NOTE=0 +CONFIG_DEFAULT_GENERATE_X86_RELAX_RELOCATIONS=1 +CONFIG_DEFAULT_X86_TLS_CHECK=0 + +# Thread-local storage keyword +CONFIG_TLS=__thread + +# Debug info directory +CONFIG_DEBUGDIR="/usr/lib/debug" diff --git a/examples/configs/host-darwin/gcc.config b/examples/configs/host-darwin/gcc.config new file mode 100644 index 0000000..ab0517d --- /dev/null +++ b/examples/configs/host-darwin/gcc.config @@ -0,0 +1,87 @@ +# gcc/ - macOS (aarch64-apple-darwin) auto-host.h defines +# +# Cross-referenced with gcc/configure.ac output for macOS host. +# Differences from Linux: no mallinfo, no posix_fallocate, no *_unlocked, +# no _GNU_SOURCE, different ld/gas features. + +# Type sizes (same as Linux on 64-bit) +CONFIG_SIZEOF_SHORT=2 +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_LONG_LONG=8 +CONFIG_SIZEOF_VOID_P=8 +CONFIG_SIZEOF__BOOL=1 +CONFIG_INT64_T_IS_LONG=1 + +# Headers +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_FTW_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LANGINFO_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_RESOURCE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIMES_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_SYS_WAIT_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Functions (macOS has most POSIX, but not Linux-specific ones) +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_CLOCK=1 +CONFIG_HAVE_CLOCK_GETTIME=1 +CONFIG_HAVE_GETRLIMIT=1 +CONFIG_HAVE_GETRUSAGE=1 +CONFIG_HAVE_GETTIMEOFDAY=1 +CONFIG_HAVE_ICONV=1 +CONFIG_HAVE_LANGINFO_CODESET=1 +CONFIG_HAVE_LSTAT=1 +CONFIG_HAVE_MADVISE=1 +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_MMAP_ANON=1 +CONFIG_HAVE_MMAP_FILE=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_SETRLIMIT=1 +CONFIG_HAVE_SIGACTION=1 +CONFIG_HAVE_STRSIGNAL=1 +CONFIG_HAVE_SYSCONF=1 +CONFIG_HAVE_TIMES=1 +CONFIG_HAVE_VFORK=1 +CONFIG_HAVE_WORKING_FORK=1 +CONFIG_HAVE_WORKING_VFORK=1 + +# Declarations +CONFIG_HAVE_DECL_ABORT=1 +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_BASENAME=0 +CONFIG_HAVE_DECL_ERRNO=1 +CONFIG_HAVE_DECL_GETENV=1 +CONFIG_HAVE_DECL_GETOPT=1 +CONFIG_HAVE_DECL_LDGETNAME=0 +CONFIG_HAVE_DECL_MALLOC=1 +CONFIG_HAVE_DECL_REALLOC=1 +CONFIG_HAVE_DECL_SBRK=0 +CONFIG_HAVE_DECL_SNPRINTF=1 +CONFIG_HAVE_DECL_STRSIGNAL=1 +CONFIG_HAVE_DECL_VASPRINTF=1 +CONFIG_HAVE_DECL_VSNPRINTF=1 + +# Build options +CONFIG_GATHER_STATISTICS=0 +CONFIG_CHECKING_P=1 + +# Misc +CONFIG_STDC_HEADERS=1 +CONFIG_ENABLE_ASSERT_CHECKING=1 diff --git a/examples/configs/host-darwin/gmp.config b/examples/configs/host-darwin/gmp.config new file mode 100644 index 0000000..a280c8c --- /dev/null +++ b/examples/configs/host-darwin/gmp.config @@ -0,0 +1,101 @@ +# GMP 6.2.1 - macOS (aarch64-apple-darwin) config.h defines +# +# Key differences from Linux: no sys_sysinfo, no hidden_alias (macOS linker), +# no obstack_vprintf, host CPU is aarch64 not x86_64. + +# Architecture +CONFIG_LIMB_BITS=64 +CONFIG_NAIL_BITS=0 + +# MPN CPU target +CONFIG_MPN_CPU=generic + +# Feature detection +CONFIG_HAVE_ALARM=1 +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_ATTRIBUTE_CONST=1 +CONFIG_HAVE_ATTRIBUTE_MALLOC=1 +CONFIG_HAVE_ATTRIBUTE_MODE=1 +CONFIG_HAVE_ATTRIBUTE_NORETURN=1 +CONFIG_HAVE_CLOCK=1 +CONFIG_HAVE_CLOCK_GETTIME=1 +CONFIG_HAVE_DECL_FGETC=1 +CONFIG_HAVE_DECL_FSCANF=1 +CONFIG_HAVE_DECL_OPTARG=1 +CONFIG_HAVE_DECL_SYS_ERRLIST=0 +CONFIG_HAVE_DECL_SYS_NERR=0 +CONFIG_HAVE_DECL_UNGETC=1 +CONFIG_HAVE_DECL_VFPRINTF=1 +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_DOUBLE_IEEE_LITTLE_ENDIAN=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_FLOAT_H=1 +CONFIG_HAVE_GETPAGESIZE=1 +CONFIG_HAVE_GETRUSAGE=1 +CONFIG_HAVE_GETTIMEOFDAY=1 +CONFIG_HAVE_INTMAX_T=1 +CONFIG_HAVE_INTPTR_T=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LANGINFO_H=1 +CONFIG_HAVE_LIMB_LITTLE_ENDIAN=1 +CONFIG_HAVE_LOCALECONV=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_LONG_DOUBLE=1 +CONFIG_HAVE_LONG_LONG=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_MEMSET=1 +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_MPROTECT=1 +CONFIG_HAVE_NL_LANGINFO=1 +CONFIG_HAVE_NL_TYPES_H=1 +CONFIG_HAVE_POPEN=1 +CONFIG_HAVE_PTRDIFF_T=1 +CONFIG_HAVE_RAISE=1 +CONFIG_HAVE_SIGACTION=1 +CONFIG_HAVE_SIGALTSTACK=1 +CONFIG_HAVE_SIGNAL_H=1 +CONFIG_HAVE_STACK_T=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRCHR=1 +CONFIG_HAVE_STRERROR=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRNLEN=1 +CONFIG_HAVE_STRTOL=1 +CONFIG_HAVE_STRTOUL=1 +CONFIG_HAVE_SYSCONF=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_RESOURCE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TIMES_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_TIMES=1 +CONFIG_HAVE_UINT_LEAST32_T=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_HAVE_VSNPRINTF=1 +CONFIG_LSYM_PREFIX="_" +CONFIG_RETSIGTYPE=void +CONFIG_SIZEOF_UNSIGNED=4 +CONFIG_SIZEOF_UNSIGNED_SHORT=2 +CONFIG_SIZEOF_VOID_P=8 +CONFIG_TIME_WITH_SYS_TIME=1 +CONFIG_TUNE_SQR_TOOM2_MAX=SQR_TOOM2_MAX_GENERIC +CONFIG_PACKAGE="gmp" +CONFIG_PACKAGE_BUGREPORT="gmp-bugs@gmp.org" +CONFIG_PACKAGE_NAME="GNU MP" +CONFIG_PACKAGE_STRING="GNU MP 6.2.1" +CONFIG_PACKAGE_TARNAME="gmp" +CONFIG_PACKAGE_VERSION="6.2.1" +CONFIG_SIZEOF_MP_LIMB_T=8 +CONFIG_SIZEOF_UNSIGNED_LONG=8 +CONFIG_SIZEOF_UNSIGNED_LONG_LONG=8 +CONFIG_STDC_HEADERS=1 +CONFIG_VERSION="6.2.1" +CONFIG_WANT_FFT=1 +CONFIG_WANT_TMP_ALLOCA=1 +CONFIG_GMP_MPARAM=mpn/generic/gmp-mparam.h +CONFIG_NO_ASM=1 diff --git a/examples/configs/host-darwin/libbacktrace.config b/examples/configs/host-darwin/libbacktrace.config new file mode 100644 index 0000000..645b8cb --- /dev/null +++ b/examples/configs/host-darwin/libbacktrace.config @@ -0,0 +1,48 @@ +# libbacktrace - macOS (aarch64-apple-darwin) config.h defines +# +# Key differences from Linux: Mach-O format (not ELF), no dl_iterate_phdr, +# no link.h, no _GNU_SOURCE. + +# Object format: macho (macOS) instead of elf (Linux) +CONFIG_BACKTRACE_FORMAT=macho + +# Atomics +CONFIG_HAVE_ATOMIC_FUNCTIONS=1 +CONFIG_HAVE_SYNC_FUNCTIONS=1 + +# Functions +CONFIG_HAVE_CLOCK_GETTIME=1 +CONFIG_HAVE_FCNTL=1 +CONFIG_HAVE_LSTAT=1 +CONFIG_HAVE_READLINK=1 + +# Declarations +CONFIG_HAVE_DECL_GETPAGESIZE=1 +CONFIG_HAVE_DECL_STRNLEN=1 +CONFIG_HAVE_DECL__PGMPTR=0 + +# Headers +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Compression (optional, can link -lz) +CONFIG_HAVE_ZLIB=1 + +# Sizes +CONFIG_SIZEOF_CHAR=1 +CONFIG_SIZEOF_SHORT=2 +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_VOID_P=8 + +# Misc +CONFIG_STDC_HEADERS=1 diff --git a/examples/configs/host-darwin/libcpp.config b/examples/configs/host-darwin/libcpp.config new file mode 100644 index 0000000..771437b --- /dev/null +++ b/examples/configs/host-darwin/libcpp.config @@ -0,0 +1,64 @@ +# libcpp - macOS (aarch64-apple-darwin) config.h defines +# +# Key differences from Linux: no *_unlocked functions (glibc-specific). + +# Build options +CONFIG_ENABLE_CANONICAL_SYSTEM_HEADERS=1 + +# Headers +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_STDDEF_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Functions (macOS lacks glibc *_unlocked variants) +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_ICONV=1 +CONFIG_HAVE_LANGINFO_CODESET=1 +CONFIG_HAVE_SETLOCALE=1 + +# Declarations +CONFIG_HAVE_DECL_ABORT=1 +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_BASENAME=0 +CONFIG_HAVE_DECL_ERRNO=1 +CONFIG_HAVE_DECL_FPRINTF_UNLOCKED=0 +CONFIG_HAVE_DECL_GETOPT=1 +CONFIG_HAVE_DECL_VASPRINTF=1 + +# Types +CONFIG_HAVE_UINTPTR_T=1 + +# Sizes +CONFIG_SIZEOF_DEV_T=4 +CONFIG_SIZEOF_INO_T=8 +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 + +# Package +CONFIG_PACKAGE="cpplib" +CONFIG_PACKAGE_BUGREPORT="" +CONFIG_PACKAGE_NAME="cpplib" +CONFIG_PACKAGE_STRING="cpplib 0" +CONFIG_PACKAGE_TARNAME="cpplib" +CONFIG_PACKAGE_URL="" +CONFIG_PACKAGE_VERSION="0" + +# iconv (macOS libc uses char**, same as glibc — ICONV_CONST is empty) +CONFIG_ICONV_CONST= + +# Misc +CONFIG_STDC_HEADERS=1 +CONFIG_STRING_WITH_STRINGS=1 +CONFIG_TIME_WITH_SYS_TIME=1 diff --git a/examples/configs/host-darwin/libdecnumber.config b/examples/configs/host-darwin/libdecnumber.config new file mode 100644 index 0000000..de25363 --- /dev/null +++ b/examples/configs/host-darwin/libdecnumber.config @@ -0,0 +1,7 @@ +# libdecnumber - macOS (aarch64-apple-darwin) config.h defines +# +# Identical to Linux — libdecnumber only needs endianness and standard headers. + +CONFIG_STDC_HEADERS=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STDLIB_H=1 diff --git a/examples/configs/host-darwin/libiberty.config b/examples/configs/host-darwin/libiberty.config new file mode 100644 index 0000000..4fb2d0a --- /dev/null +++ b/examples/configs/host-darwin/libiberty.config @@ -0,0 +1,132 @@ +# libiberty - macOS (aarch64-apple-darwin) config.h defines +# +# Key differences from Linux: no canonicalize_file_name, no on_exit, +# no pipe2, no sys_prctl_h, no sys_sysinfo_h, no __fsetlocking, +# no stdio_ext.h, no sigsetmask, no strverscmp. + +# Headers +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_SPAWN_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_RESOURCE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_SYS_WAIT_H=1 +CONFIG_HAVE_TIME_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Functions +CONFIG_HAVE_ASPRINTF=1 +CONFIG_HAVE_ATEXIT=1 +CONFIG_HAVE_BASENAME=1 +CONFIG_HAVE_BCMP=1 +CONFIG_HAVE_BCOPY=1 +CONFIG_HAVE_BSEARCH=1 +CONFIG_HAVE_BZERO=1 +CONFIG_HAVE_CALLOC=1 +CONFIG_HAVE_CLOCK=1 +CONFIG_HAVE_FFS=1 +CONFIG_HAVE_FORK=1 +CONFIG_HAVE_GETCWD=1 +CONFIG_HAVE_GETPAGESIZE=1 +CONFIG_HAVE_GETRLIMIT=1 +CONFIG_HAVE_GETRUSAGE=1 +CONFIG_HAVE_GETTIMEOFDAY=1 +CONFIG_HAVE_INDEX=1 +CONFIG_HAVE_INSQUE=1 +CONFIG_HAVE_MEMCHR=1 +CONFIG_HAVE_MEMCMP=1 +CONFIG_HAVE_MEMCPY=1 +CONFIG_HAVE_MEMMEM=1 +CONFIG_HAVE_MEMMOVE=1 +CONFIG_HAVE_MEMSET=1 +CONFIG_HAVE_MKSTEMPS=1 +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_POSIX_SPAWN=1 +CONFIG_HAVE_POSIX_SPAWNP=1 +CONFIG_HAVE_PSIGNAL=1 +CONFIG_HAVE_PUTENV=1 +CONFIG_HAVE_RANDOM=1 +CONFIG_HAVE_REALPATH=1 +CONFIG_HAVE_RENAME=1 +CONFIG_HAVE_RINDEX=1 +CONFIG_HAVE_SBRK=1 +CONFIG_HAVE_SETENV=1 +CONFIG_HAVE_SETRLIMIT=1 +CONFIG_HAVE_SNPRINTF=1 +CONFIG_HAVE_STPCPY=1 +CONFIG_HAVE_STPNCPY=1 +CONFIG_HAVE_STRCASECMP=1 +CONFIG_HAVE_STRCHR=1 +CONFIG_HAVE_STRDUP=1 +CONFIG_HAVE_STRERROR=1 +CONFIG_HAVE_STRNCASECMP=1 +CONFIG_HAVE_STRNDUP=1 +CONFIG_HAVE_STRNLEN=1 +CONFIG_HAVE_STRRCHR=1 +CONFIG_HAVE_STRSIGNAL=1 +CONFIG_HAVE_STRSTR=1 +CONFIG_HAVE_STRTOD=1 +CONFIG_HAVE_STRTOL=1 +CONFIG_HAVE_STRTOLL=1 +CONFIG_HAVE_STRTOUL=1 +CONFIG_HAVE_STRTOULL=1 +CONFIG_HAVE_SYSCONF=1 +CONFIG_HAVE_TIMES=1 +CONFIG_HAVE_TMPNAM=1 +CONFIG_HAVE_VASPRINTF=1 +CONFIG_HAVE_VFORK=1 +CONFIG_HAVE_VFPRINTF=1 +CONFIG_HAVE_VPRINTF=1 +CONFIG_HAVE_VSPRINTF=1 +CONFIG_HAVE_WAIT3=1 +CONFIG_HAVE_WAIT4=1 +CONFIG_HAVE_WAITPID=1 +CONFIG_HAVE_WORKING_FORK=1 +CONFIG_HAVE_WORKING_VFORK=1 + +# Types +CONFIG_HAVE_INTPTR_T=1 +CONFIG_HAVE_UINTPTR_T=1 +CONFIG_HAVE_LONG_LONG=1 + +# Declarations +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_BASENAME=0 +CONFIG_HAVE_DECL_CALLOC=1 +CONFIG_HAVE_DECL_FFS=1 +CONFIG_HAVE_DECL_GETENV=1 +CONFIG_HAVE_DECL_GETOPT=1 +CONFIG_HAVE_DECL_MALLOC=1 +CONFIG_HAVE_DECL_REALLOC=1 +CONFIG_HAVE_DECL_SBRK=0 +CONFIG_HAVE_DECL_SNPRINTF=1 +CONFIG_HAVE_DECL_STRNLEN=1 +CONFIG_HAVE_DECL_STRTOL=1 +CONFIG_HAVE_DECL_STRTOLL=1 +CONFIG_HAVE_DECL_STRTOUL=1 +CONFIG_HAVE_DECL_STRTOULL=1 +CONFIG_HAVE_DECL_VASPRINTF=1 +CONFIG_HAVE_DECL_VSNPRINTF=1 + +# Sizes +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_LONG_LONG=8 +CONFIG_SIZEOF_SIZE_T=8 + +# Misc +CONFIG_STDC_HEADERS=1 +CONFIG_TIME_WITH_SYS_TIME=1 +CONFIG_UNSIGNED_64BIT_TYPE=unsigned long diff --git a/examples/configs/host-darwin/mpc.config b/examples/configs/host-darwin/mpc.config new file mode 100644 index 0000000..d4568ae --- /dev/null +++ b/examples/configs/host-darwin/mpc.config @@ -0,0 +1,24 @@ +# MPC 1.2.1 - macOS (aarch64-apple-darwin) config.h defines +# +# Identical to Linux — MPC is pure C with no platform-specific features. + +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_LOCALECONV=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_PACKAGE="mpc" +CONFIG_PACKAGE_NAME="mpc" +CONFIG_PACKAGE_STRING="mpc 1.2.1" +CONFIG_PACKAGE_TARNAME="mpc" +CONFIG_PACKAGE_VERSION="1.2.1" +CONFIG_STDC_HEADERS=1 +CONFIG_VERSION="1.2.1" diff --git a/examples/configs/host-darwin/mpfr.config b/examples/configs/host-darwin/mpfr.config new file mode 100644 index 0000000..f92072b --- /dev/null +++ b/examples/configs/host-darwin/mpfr.config @@ -0,0 +1,31 @@ +# MPFR 4.1.0 - macOS (aarch64-apple-darwin) config.h defines +# +# Nearly identical to Linux. Only endianness representation differs slightly. + +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_LOCALECONV=1 +CONFIG_HAVE_LONG_LONG=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_STDARG=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_HAVE_VA_COPY=1 +CONFIG_HAVE_WCHAR_H=1 +CONFIG_HAVE_LITTLE_ENDIAN=1 +CONFIG_PACKAGE="mpfr" +CONFIG_PACKAGE_NAME="MPFR" +CONFIG_PACKAGE_STRING="MPFR 4.1.0" +CONFIG_PACKAGE_TARNAME="mpfr" +CONFIG_PACKAGE_VERSION="4.1.0" +CONFIG_STDC_HEADERS=1 +CONFIG_VERSION="4.1.0" diff --git a/examples/configs/x86_64-linux.config b/examples/configs/x86_64-linux.config new file mode 100644 index 0000000..7433a5b --- /dev/null +++ b/examples/configs/x86_64-linux.config @@ -0,0 +1,23 @@ +# GCC Libraries - x86-64 Linux toolchain (native) +# +# Usage: +# putup configure --config configs/x86_64-linux.config -S ../gcc-15.2.0 -B ../build-gcc +# +# Per-library configs live in gmp/tup.config, mpfr/tup.config, mpc/tup.config. +# Scoped config merging combines these with the toolchain vars below. + +# Toolchain +CONFIG_CC=gcc +CONFIG_CXX=g++ +CONFIG_AR=ar +CONFIG_HOSTCC=g++ + +# Platform selection +CONFIG_TARGET=x86_64-pc-linux-gnu +CONFIG_HOST_OS=linux +CONFIG_PLATFORM_LDFLAGS=-lm -ldl -lpthread -lz +CONFIG_EXTRA_MODES_FILE=config/i386/i386-modes.def + +# libbacktrace: ELF format on Linux, 64-bit +CONFIG_BACKTRACE_FORMAT=elf +CONFIG_BACKTRACE_ELF_SIZE=64 diff --git a/examples/gcc/Tupfile.ini b/examples/gcc/Tupfile.ini new file mode 100644 index 0000000..3a94e71 --- /dev/null +++ b/examples/gcc/Tupfile.ini @@ -0,0 +1 @@ +# GCC tarball group diff --git a/examples/gcc/Tuprules.tup b/examples/gcc/Tuprules.tup new file mode 100644 index 0000000..71b890d --- /dev/null +++ b/examples/gcc/Tuprules.tup @@ -0,0 +1,20 @@ +# gcc group rules — ?= defaults for standalone use. +# In BSP mode, root Tuprules.tup overrides these with gcc/ prefix. + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) + +CC ?= @(CC) +CXX ?= @(CXX) +AR ?= @(AR) +HOSTCC ?= @(HOSTCC) + +GCC_DIR ?= gcc +GMP_DIR ?= gmp +MPFR_DIR ?= mpfr +MPC_DIR ?= mpc +LIBIBERTY_DIR ?= libiberty +LIBCPP_DIR ?= libcpp +LIBDECNUMBER_DIR ?= libdecnumber +LIBBACKTRACE_DIR ?= libbacktrace +LIBCODY_DIR ?= libcody diff --git a/examples/gcc/gcc/Tupfile b/examples/gcc/gcc/Tupfile new file mode 100644 index 0000000..da67912 --- /dev/null +++ b/examples/gcc/gcc/Tupfile @@ -0,0 +1,1031 @@ +include_rules + +# ============================================================ +# GCC 15.2.0 — C compiler backend +# ============================================================ +# +# Builds the GCC toolchain from source via 14 phases: +# 1-3. Config headers, generator bootstrap, RTL generators +# 4-6. Generated source, backend objects, common objects +# 7. cc1 link +# 8-14. xgcc, cc1plus, collect2, g++, cpp, lto-wrapper, gcov +# +# Platform selection (from root tup.config): +# @(TARGET) — target triple (e.g. x86_64-pc-linux-gnu) +# @(HOST_OS) — host OS for source selection (linux, darwin) +# @(EXTRA_MODES_FILE) — target modes definition file +# @(PLATFORM_LDFLAGS) — platform-specific link flags +# +# Target-specific rules (tm.h, tm_p.h, MD, gtyp entries): +# targets/@(TARGET).tup + +SRC = $(S)/$(GCC_DIR) + +# ============================================================ +# Phase 1: Config headers → +# ============================================================ + +# auto-host.h from tup.config +: |> !gen-config |> auto-host.h + +# bconfig.h — build-machine config (generators only) +: |> ^ GEN %o^ ( \ + echo '#ifndef GCC_BCONFIG_H'; \ + echo '#define GCC_BCONFIG_H'; \ + echo '#include "auto-host.h"'; \ + echo '#ifdef IN_GCC'; \ + echo '# include "ansidecl.h"'; \ + echo '#endif'; \ + echo '#endif'; \ + ) > %o |> bconfig.h + +# config.h — target config (not for generators) +: |> ^ GEN %o^ ( \ + echo '#ifndef GCC_CONFIG_H'; \ + echo '#define GCC_CONFIG_H'; \ + echo '#ifdef GENERATOR_FILE'; \ + echo '#error config.h is not for generator programs'; \ + echo '#endif'; \ + echo '#include "auto-host.h"'; \ + echo '#endif'; \ + ) > %o |> config.h + +# bversion.h +: |> ^ GEN %o^ ( \ + echo '#define BUILDING_GCC_MAJOR 15'; \ + echo '#define BUILDING_GCC_MINOR 2'; \ + echo '#define BUILDING_GCC_PATCHLEVEL 0'; \ + echo '#define BUILDING_GCC_VERSION (BUILDING_GCC_MAJOR * 1000 + BUILDING_GCC_MINOR)'; \ + ) > %o |> bversion.h + +# version.h +: |> ^ GEN %o^ ( \ + echo '#ifndef VERSION_H'; \ + echo '#define VERSION_H'; \ + echo '#define GCC_major_version 15'; \ + echo '#define version_string "15.2.0"'; \ + echo '#define pkgversion_string "(Tup) "'; \ + echo '#define bug_report_url ""'; \ + echo '#define GCOV_VERSION ((gcov_unsigned_t)0x4235322a)'; \ + echo '#endif'; \ + ) > %o |> version.h + +# configargs.h — configure arguments (stub for tup build) +: |> ^ GEN %o^ ( \ + echo 'static const char configuration_arguments[] = "tup-build @(TARGET)";'; \ + echo 'static const char thread_model[] = "posix";'; \ + echo 'static const struct { const char *name, *value; } configure_default_options[] = { { NULL, NULL } };'; \ + ) > %o |> configargs.h + +# omp-device-properties.h — offload device properties (no GPU offloading) +: |> ^ GEN %o^ ( \ + echo 'const char omp_offload_device_kind[] = "";'; \ + echo 'const char omp_offload_device_arch[] = "";'; \ + echo 'const char omp_offload_device_isa[] = "";'; \ + ) > %o |> omp-device-properties.h + +# --- Target-specific headers and configuration --- +# Sets: MD, TARGET_OPT_FILES, target_gtyp_src, target_GT_H, TARGET_DRIVER_LINK +# Generates: tm.h, tm_p.h → +# Compiles: target-specific backend + driver objects → , +TARGET_DRIVER_LINK = +include targets/@(TARGET).tup + +# --- Options pipeline --- +# .opt files → optionlist → options.h, options.cc, options-save.cc, options-urls.cc + +OPT_FILES = c-family/c.opt common.opt params.opt analyzer/analyzer.opt +OPT_FILES += lto/lang.opt +OPT_FILES += $(TARGET_OPT_FILES) + +: $(OPT_FILES) |> ^ GEN optionlist^ \ + LC_ALL=C awk -f $(SRC)/opt-gather.awk %f > %o \ + |> optionlist + +: optionlist |> ^ GEN %o^ \ + awk -f $(SRC)/opt-functions.awk -f $(SRC)/opt-read.awk \ + -f $(SRC)/opth-gen.awk < %f > %o \ + |> options.h + +: optionlist |> ^ GEN %o^ \ + awk -f $(SRC)/opt-functions.awk -f $(SRC)/opt-read.awk \ + -f $(SRC)/optc-gen.awk \ + -v header_name="config.h system.h coretypes.h options.h tm.h" < %f > %o \ + |> options.cc + +: optionlist |> ^ GEN %o^ \ + awk -f $(SRC)/opt-functions.awk -f $(SRC)/opt-read.awk \ + -f $(SRC)/optc-save-gen.awk \ + -v header_name="config.h system.h coretypes.h tm.h" < %f > %o \ + |> options-save.cc + +: optionlist |> ^ GEN %o^ \ + awk -f $(SRC)/opt-functions.awk -f $(SRC)/opt-read.awk \ + -f $(SRC)/options-urls-cc-gen.awk \ + -v header_name="config.h system.h coretypes.h tm.h" < %f > %o \ + |> options-urls.cc + +# ============================================================ +# Phase 2: Generator bootstrap +# ============================================================ +# +# Bootstrap chain: +# errors.o → genmodes → insn-modes.h +# insn-modes.h → BUILD_RTL objects +# BUILD_RTL + BUILD_MD → genconditions → gencondmd → insn-conditions.md +# insn-conditions.md → all RTL generators + +# Host support objects (prefixed to avoid collision with target objects) +BUILD_ERRORS = host-errors.o +: errors.cc |> !hostcxx |> host-errors.o + +# genmodes needs EXTRA_MODES_FILE for the target architecture +: genmodes.cc |> ^ HOSTCXX %b^ $(HOSTCC) $(HOST_CXXFLAGS) \ + -DEXTRA_MODES_FILE=\"@(EXTRA_MODES_FILE)\" -c %f -o %o \ + |> host-genmodes.o + +: host-genmodes.o host-errors.o $(LIBIBERTY_A) |> ^ LINK genmodes^ $(HOSTCC) %f -o %o |> genmodes + +: | genmodes |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genmodes -h > %o |> insn-modes.h +: | genmodes |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genmodes -i > %o |> insn-modes-inline.h +: | genmodes |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genmodes > %o |> insn-modes.cc +: | genmodes |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genmodes -m > %o |> min-insn-modes.cc + +# min-insn-modes.o (host, from generated source) +: min-insn-modes.cc |> !hostcxx |> host-min-insn-modes.o + +# BUILD_MD (no tm.h → no insn-constants.h needed) +EARLY_GEN_DEPS = insn-modes.h insn-modes-inline.h +: read-md.cc | $(EARLY_GEN_DEPS) |> !hostcxx |> host-read-md.o + +# genconstants (MD input only — early because tm.h includes insn-constants.h) +: genconstants.cc | $(EARLY_GEN_DEPS) |> !hostcxx |> host-genconstants.o +: host-genconstants.o host-read-md.o $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genconstants^ $(HOSTCC) %f -o %o |> genconstants +: $(MD) | genconstants |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genconstants %f > %o \ + |> insn-constants.h + +# BUILD_RTL objects +# IN_GCC → tm.h → insn-constants.h; GENERATOR_FILE → rtl.h → ggc.h → gtype-desc.h +BUILD_RTL_DEPS = insn-modes.h insn-modes-inline.h insn-constants.h gtype-desc.h + +: rtl.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-rtl.o +: read-rtl.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-read-rtl.o +: ggc-none.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-ggc-none.o +: vec.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-vec.o +: gensupport.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-gensupport.o +: print-rtl.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-print-rtl.o +: hash-table.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-hash-table.o +: sort.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-sort.o +: inchash.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-inchash.o + +BUILD_RTL = host-rtl.o host-read-rtl.o host-ggc-none.o host-vec.o +BUILD_RTL += host-min-insn-modes.o host-gensupport.o host-print-rtl.o +BUILD_RTL += host-hash-table.o host-sort.o +BUILD_MD = host-read-md.o + +# --- genconditions → gencondmd bootstrap --- + +: genconditions.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genconditions.o + +: host-genconditions.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) \ + $(LIBIBERTY_A) |> ^ LINK genconditions^ $(HOSTCC) %f -o %o |> genconditions + +: $(MD) | genconditions |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genconditions %f > %o |> gencondmd.cc + +: gencondmd.cc |> !hostcxx |> host-gencondmd.o + +: host-gencondmd.o $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK gencondmd^ $(HOSTCC) %f -o %o |> gencondmd + +: | gencondmd |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/gencondmd > %o |> insn-conditions.md + +# ============================================================ +# Phase 3: Generators +# ============================================================ +# +# Each generator: compile → link → run. +# RTL generators link with BUILD_RTL + BUILD_MD + BUILD_ERRORS. +# Non-RTL generators link with BUILD_ERRORS only. + +# --- Helper: compile + link an RTL generator --- +# (Each generator is hand-written for clarity) + +# gengenrtl (no MD input, uses rtl.def) +: gengenrtl.cc |> !hostcxx |> host-gengenrtl.o +: host-gengenrtl.o $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK gengenrtl^ $(HOSTCC) %f -o %o |> gengenrtl +: | gengenrtl |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/gengenrtl > %o |> genrtl.h + +# all-tree.def — aggregates tree.def + language-specific defs +# Includes cp/cp-tree.def because c-family/ shared code references C++ tree codes. +: |> ^ GEN %o^ ( \ + echo '#include "tree.def"'; \ + echo 'END_OF_BASE_TREE_CODES'; \ + echo '#include "c-family/c-common.def"'; \ + echo '#include "c/c-tree.def"'; \ + echo '#include "cp/cp-tree.def"'; \ + ) > %o |> all-tree.def + +# gencheck (uses all-tree.def + insn-modes.h via coretypes.h → tm.h) +: gencheck.cc | $(BUILD_RTL_DEPS) all-tree.def |> !hostcxx |> host-gencheck.o +: host-gencheck.o $(BUILD_ERRORS) $(LIBIBERTY_A) |> ^ LINK gencheck^ $(HOSTCC) %f -o %o |> gencheck +: | gencheck |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/gencheck > %o |> tree-check.h + +# genhooks (no MD input, produces multiple hook headers) +: genhooks.cc |> !hostcxx |> host-genhooks.o +: host-genhooks.o $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genhooks^ $(HOSTCC) %f -o %o |> genhooks +: | genhooks |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genhooks "Target Hook" > %o \ + |> target-hooks-def.h +: | genhooks |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genhooks "Common Target Hook" > %o \ + |> common/common-target-hooks-def.h + +# gencfn-macros (no MD input) +: gencfn-macros.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-gencfn-macros.o +: host-gencfn-macros.o $(BUILD_ERRORS) host-hash-table.o host-vec.o \ + host-ggc-none.o host-sort.o $(LIBIBERTY_A) |> \ + ^ LINK gencfn-macros^ $(HOSTCC) %f -o %o |> gencfn-macros +: | gencfn-macros |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/gencfn-macros -c > %o \ + |> case-cfn-macros.h +: | gencfn-macros |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/gencfn-macros -o > %o \ + |> cfn-operators.pd + +# genmatch (reads match.pd via libcpp tokenizer) +: genmatch.cc | $(BUILD_RTL_DEPS) case-cfn-macros.h |> !hostcxx |> host-genmatch.o + +: host-genmatch.o $(BUILD_ERRORS) host-vec.o host-hash-table.o host-sort.o \ + $(LIBCPP_A) $(LIBIBERTY_A) |> \ + ^ LINK genmatch^ $(HOSTCC) %f @(PLATFORM_LDFLAGS) -o %o |> genmatch + +: $(SRC)/match.pd | genmatch cfn-operators.pd |> ^ GEN gimple-match-*^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && ./genmatch --gimple \ + --header=gimple-match-auto.h --include=gimple-match-auto.h \ + $SRCDIR/match.pd \ + gimple-match-1.cc gimple-match-2.cc gimple-match-3.cc \ + gimple-match-4.cc gimple-match-5.cc gimple-match-6.cc \ + gimple-match-7.cc gimple-match-8.cc gimple-match-9.cc \ + gimple-match-10.cc \ + |> gimple-match-auto.h gimple-match-1.cc gimple-match-2.cc \ + gimple-match-3.cc gimple-match-4.cc gimple-match-5.cc \ + gimple-match-6.cc gimple-match-7.cc gimple-match-8.cc \ + gimple-match-9.cc gimple-match-10.cc + +: $(SRC)/match.pd | genmatch cfn-operators.pd |> ^ GEN generic-match-*^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && ./genmatch --generic \ + --header=generic-match-auto.h --include=generic-match-auto.h \ + $SRCDIR/match.pd \ + generic-match-1.cc generic-match-2.cc generic-match-3.cc \ + generic-match-4.cc generic-match-5.cc generic-match-6.cc \ + generic-match-7.cc generic-match-8.cc generic-match-9.cc \ + generic-match-10.cc \ + |> generic-match-auto.h generic-match-1.cc generic-match-2.cc \ + generic-match-3.cc generic-match-4.cc generic-match-5.cc \ + generic-match-6.cc generic-match-7.cc generic-match-8.cc \ + generic-match-9.cc generic-match-10.cc + +# genenums (MD input only) +: genenums.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genenums.o +: host-genenums.o $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genenums^ $(HOSTCC) %f -o %o |> genenums +: $(MD) | genenums |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genenums %f > %o |> insn-enums.cc + +# --- Simple RTL generators (MD + insn-conditions.md → header output) --- + +: genattr.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genattr.o +: host-genattr.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genattr^ $(HOSTCC) %f -o %o |> genattr +: $(MD) insn-conditions.md | genattr |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genattr %f > %o \ + |> insn-attr.h + +: genattr-common.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genattr-common.o +: host-genattr-common.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genattr-common^ $(HOSTCC) %f -o %o |> genattr-common +: $(MD) insn-conditions.md | genattr-common |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genattr-common %f > %o \ + |> insn-attr-common.h + +: gencodes.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-gencodes.o +: host-gencodes.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK gencodes^ $(HOSTCC) %f -o %o |> gencodes +: $(MD) insn-conditions.md | gencodes |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/gencodes %f > %o \ + |> insn-codes.h + +: genconfig.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genconfig.o +: host-genconfig.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genconfig^ $(HOSTCC) %f -o %o |> genconfig +: $(MD) insn-conditions.md | genconfig |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genconfig %f > %o \ + |> insn-config.h + +: genflags.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genflags.o +: host-genflags.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genflags^ $(HOSTCC) %f -o %o |> genflags +: $(MD) insn-conditions.md | genflags |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genflags %f > %o \ + |> insn-flags.h + +: gentarget-def.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-gentarget-def.o +: host-gentarget-def.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK gentarget-def^ $(HOSTCC) %f -o %o |> gentarget-def +: $(MD) insn-conditions.md | gentarget-def |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/gentarget-def %f > %o \ + |> insn-target-def.h + +# --- Simple RTL generators (MD + insn-conditions.md → source output) --- + +: genautomata.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genautomata.o +: host-genautomata.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genautomata^ $(HOSTCC) %f -o %o -lm |> genautomata +: $(MD) insn-conditions.md | genautomata |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genautomata %f > %o \ + |> insn-automata.cc + +: genextract.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genextract.o +: host-genextract.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genextract^ $(HOSTCC) %f -o %o |> genextract +: $(MD) insn-conditions.md | genextract |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genextract %f > %o \ + |> insn-extract.cc + +: genoutput.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genoutput.o +: host-genoutput.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genoutput^ $(HOSTCC) %f -o %o |> genoutput +: $(MD) insn-conditions.md | genoutput |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genoutput %f > %o \ + |> insn-output.cc + +: genpeep.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genpeep.o +: host-genpeep.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genpeep^ $(HOSTCC) %f -o %o |> genpeep +: $(MD) insn-conditions.md | genpeep |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genpeep %f > %o \ + |> insn-peep.cc + +# --- Multi-output RTL generators --- +# These cd to the output dir for writing; MD paths are prefixed with $SRCDIR. + +# genattrtab → 3 files +: genattrtab.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genattrtab.o +: host-genattrtab.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genattrtab^ $(HOSTCC) %f -o %o |> genattrtab +: $(MD) insn-conditions.md | genattrtab |> ^ GEN insn-attrtab^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && \ + MD_ARGS=""; for m in $(MD); do MD_ARGS="$MD_ARGS $SRCDIR/$m"; done && \ + ./genattrtab $MD_ARGS insn-conditions.md \ + -Ainsn-attrtab.cc -Dinsn-dfatab.cc -Linsn-latencytab.cc \ + |> insn-attrtab.cc insn-dfatab.cc insn-latencytab.cc + +# genopinit → 2 files +: genopinit.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genopinit.o +: host-genopinit.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genopinit^ $(HOSTCC) %f -o %o |> genopinit +: $(MD) insn-conditions.md | genopinit |> ^ GEN insn-opinit^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && \ + MD_ARGS=""; for m in $(MD); do MD_ARGS="$MD_ARGS $SRCDIR/$m"; done && \ + ./genopinit $MD_ARGS insn-conditions.md \ + -hinsn-opinit.h -cinsn-opinit.cc \ + |> insn-opinit.h insn-opinit.cc + +# genpreds → 3 files (separate invocations) +: genpreds.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genpreds.o +: host-genpreds.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genpreds^ $(HOSTCC) %f -o %o |> genpreds +: $(MD) | genpreds |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genpreds %f > %o |> insn-preds.cc +: $(MD) | genpreds |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genpreds -h %f > %o |> tm-preds.h +: $(MD) | genpreds |> ^ GEN %o^ $(TUP_VARIANT_OUTPUTDIR)/genpreds -c %f > %o |> tm-constrs.h + +# genemit → 10 split files +: genemit.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genemit.o +: host-genemit.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK genemit^ $(HOSTCC) %f -o %o |> genemit +: $(MD) insn-conditions.md | genemit |> ^ GEN insn-emit-*^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && \ + MD_ARGS=""; for m in $(MD); do MD_ARGS="$MD_ARGS $SRCDIR/$m"; done && \ + ./genemit $MD_ARGS insn-conditions.md \ + -Oinsn-emit-1.cc -Oinsn-emit-2.cc -Oinsn-emit-3.cc \ + -Oinsn-emit-4.cc -Oinsn-emit-5.cc -Oinsn-emit-6.cc \ + -Oinsn-emit-7.cc -Oinsn-emit-8.cc -Oinsn-emit-9.cc \ + -Oinsn-emit-10.cc \ + |> insn-emit-1.cc insn-emit-2.cc insn-emit-3.cc insn-emit-4.cc \ + insn-emit-5.cc insn-emit-6.cc insn-emit-7.cc insn-emit-8.cc \ + insn-emit-9.cc insn-emit-10.cc + +# genrecog → 10 split files + header +: genrecog.cc | $(BUILD_RTL_DEPS) |> !hostcxx |> host-genrecog.o +: host-genrecog.o $(BUILD_RTL) $(BUILD_MD) $(BUILD_ERRORS) \ + host-inchash.o $(LIBIBERTY_A) |> \ + ^ LINK genrecog^ $(HOSTCC) %f -o %o |> genrecog +: $(MD) insn-conditions.md | genrecog |> ^ GEN insn-recog-*^ \ + SRCDIR=$PWD && cd $(TUP_VARIANT_OUTPUTDIR) && \ + MD_ARGS=""; for m in $(MD); do MD_ARGS="$MD_ARGS $SRCDIR/$m"; done && \ + ./genrecog $MD_ARGS insn-conditions.md \ + -Hinsn-recog.h \ + -Oinsn-recog-1.cc -Oinsn-recog-2.cc -Oinsn-recog-3.cc \ + -Oinsn-recog-4.cc -Oinsn-recog-5.cc -Oinsn-recog-6.cc \ + -Oinsn-recog-7.cc -Oinsn-recog-8.cc -Oinsn-recog-9.cc \ + -Oinsn-recog-10.cc \ + |> insn-recog.h insn-recog-1.cc insn-recog-2.cc insn-recog-3.cc \ + insn-recog-4.cc insn-recog-5.cc insn-recog-6.cc insn-recog-7.cc \ + insn-recog-8.cc insn-recog-9.cc insn-recog-10.cc + +# --- Other generated headers --- + +# pass-instances.def from passes.def +: passes.def |> ^ GEN %o^ \ + awk -f $(SRC)/gen-pass-instances.awk %f > %o \ + |> pass-instances.def + +# --- gengtype (GC type descriptor generator) --- +# +# gengtype scans GTY-annotated source files and generates GC marking code. +# Two passes: -w writes gtype.state, -r reads it and generates output files. +# Uses -DHOST_GENERATOR_FILE (not -DGENERATOR_FILE) because gengtype needs +# full host header access for file I/O, state serialization, and regex. + +GENGTYPE_SRCS = gengtype.cc gengtype-parse.cc gengtype-state.cc gengtype-lex.cc + +: foreach $(GENGTYPE_SRCS) |> !hostcxx-gengtype |> + +: host-gengtype.o host-gengtype-parse.o host-gengtype-state.o \ + host-gengtype-lex.o $(BUILD_ERRORS) $(LIBIBERTY_A) |> \ + ^ LINK gengtype^ $(HOSTCC) %f -o %o |> gengtype + +# gtyp-input.list — generated inline (template files can't be inputs in 3-tree mode) +# Derived from GTFILES in gcc/Makefile.in, C only. +# $(SRC) is expanded at parse time, producing the correct relative paths. +# Target-specific entries come from $(target_gtyp_src) set by the target include. + +gtyp_parent = libcpp/include/line-map.h libcpp/include/rich-location.h +gtyp_parent += libcpp/include/label-text.h libcpp/include/cpplib.h +gtyp_parent += include/hashtab.h include/splay-tree.h +gtyp_parent += libcpp/include/symtab.h include/obstack.h + +gtyp_src = input.h coretypes.h +gtyp_src += bitmap.h wide-int.h alias.h coverage.cc rtl.h optabs.h +gtyp_src += tree.h tree-core.h libfuncs.h +gtyp_src += real.h function.h insn-addr.h hwint.h fixed-value.h function-abi.h +gtyp_src += output.h cfgloop.h cfg.h profile-count.h cselib.h basic-block.h +gtyp_src += ipa-ref.h cgraph.h symtab-thunks.h symtab-thunks.cc symtab-clones.h +gtyp_src += reload.h caller-save.cc symtab.cc alias.cc attribs.cc +gtyp_src += bitmap.cc cselib.cc cgraph.cc ipa-prop.cc ipa-cp.cc +gtyp_src += ipa-utils.h ipa-param-manipulation.h ipa-sra.cc +gtyp_src += ipa-modref.h ipa-modref.cc ipa-modref-tree.h ipa-locality-cloning.cc +gtyp_src += signop.h diagnostic-spec.h diagnostic-spec.cc +gtyp_src += dwarf2out.h dwarf2asm.cc dwarf2cfi.cc dwarf2codeview.cc dwarf2ctf.cc dwarf2out.cc +gtyp_src += ctfc.h ctfout.cc btfout.cc +gtyp_src += tree-vect-generic.cc gimple-isel.cc dojump.cc +gtyp_src += emit-rtl.h emit-rtl.cc except.h explow.cc expr.cc expr.h +gtyp_src += function.cc except.cc ggc-tests.cc gcse.cc godump.cc +gtyp_src += lists.cc optabs-libfuncs.cc profile.cc mcf.cc reg-stack.cc +gtyp_src += cfgrtl.cc stor-layout.cc stringpool.cc tree.cc varasm.cc +gtyp_src += gimple.h gimple-ssa.h tree-ssanames.cc tree-eh.cc +gtyp_src += tree-ssa-address.cc tree-cfg.cc tree-ssa-loop-ivopts.cc +gtyp_src += tree-dfa.cc tree-iterator.cc gimple-expr.cc tree-chrec.h +gtyp_src += tree-scalar-evolution.cc tree-ssa-operands.h +gtyp_src += tree-profile.cc tree-nested.cc path-coverage.cc prime-paths.cc +gtyp_src += omp-offload.h omp-general.h omp-general.cc omp-low.cc +gtyp_src += targhooks.cc passes.cc cgraphclones.cc +gtyp_src += tree-phinodes.cc tree-ssa-alias.h tree-ssanames.h +gtyp_src += tree-vrp.h value-range.h value-range-storage.h ipa-prop.h +gtyp_src += trans-mem.cc lto-streamer.h target-globals.h +gtyp_src += ipa-predicate.h ipa-fnsummary.h vtable-verify.cc +gtyp_src += asan.cc ubsan.cc tsan.cc sanopt.cc sancov.cc +gtyp_src += ipa-devirt.cc ipa-strub.cc internal-fn.h calls.cc +gtyp_src += analyzer/analyzer-language.cc +gtyp_src += $(target_gtyp_src) + +gtyp_c = c/c-lang.cc c/c-tree.h c/c-decl.cc +gtyp_c += c-family/c-common.cc c-family/c-common.h c-family/c-objc.h +gtyp_c += c-family/c-cppbuiltin.cc c-family/c-pragma.h c-family/c-pragma.cc +gtyp_c += c-family/c-format.cc c/c-objc-common.cc +gtyp_c += c/c-parser.h c/c-parser.cc c/c-lang.h + +gtyp_cp = cp/name-lookup.h cp/cp-tree.h cp/decl.h cp/parser.h +gtyp_cp += c-family/c-common.h c-family/c-objc.h c-family/c-pragma.h +gtyp_cp += c-family/c-common.cc c-family/c-format.cc c-family/c-cppbuiltin.cc c-family/c-pragma.cc +gtyp_cp += cp/call.cc cp/class.cc cp/constexpr.cc cp/contracts.cc cp/constraint.cc +gtyp_cp += cp/coroutines.cc cp/cp-gimplify.cc cp/cp-lang.cc cp/cp-objcp-common.cc +gtyp_cp += cp/decl.cc cp/decl2.cc cp/except.cc cp/friend.cc cp/init.cc +gtyp_cp += cp/lambda.cc cp/lex.cc cp/logic.cc cp/mangle.cc cp/method.cc cp/module.cc +gtyp_cp += cp/name-lookup.cc cp/parser.cc cp/pt.cc cp/rtti.cc +gtyp_cp += cp/semantics.cc cp/tree.cc cp/typeck2.cc cp/vtable-class-hierarchy.cc + +: |> ^ GEN %o^ { \ + for f in $(gtyp_parent); do printf '%s\n' "$(SRC)/../$f"; done; \ + for f in $(gtyp_src); do printf '%s\n' "$(SRC)/$f"; done; \ + printf '%s\n' $(TUP_VARIANT_OUTPUTDIR)/options.h; \ + echo '[c]'; \ + for f in $(gtyp_c); do printf '%s\n' "$(SRC)/$f"; done; \ + echo '[cp]'; \ + for f in $(gtyp_cp); do printf '%s\n' "$(SRC)/$f"; done; \ + } > %o |> gtyp-input.list + +# gengtype outputs: gtype-desc.cc/h, gtype-c.h, gt-*.h +GT_H = gtype-desc.h gtype-c.h +GT_H += gt-alias.h gt-asan.h gt-attribs.h gt-bitmap.h gt-btfout.h +GT_H += gt-caller-save.h gt-calls.h gt-cfgrtl.h gt-cgraph.h gt-cgraphclones.h +GT_H += gt-coverage.h gt-cselib.h gt-ctfout.h +GT_H += gt-diagnostic-spec.h gt-dojump.h +GT_H += gt-dwarf2asm.h gt-dwarf2cfi.h gt-dwarf2codeview.h gt-dwarf2ctf.h gt-dwarf2out.h +GT_H += gt-emit-rtl.h gt-except.h gt-explow.h gt-expr.h +GT_H += gt-function.h +GT_H += gt-gcse.h gt-ggc-tests.h gt-gimple-expr.h gt-gimple-isel.h gt-godump.h +GT_H += gt-ipa-cp.h gt-ipa-devirt.h gt-ipa-locality-cloning.h +GT_H += gt-ipa-modref.h gt-ipa-prop.h gt-ipa-sra.h gt-ipa-strub.h +GT_H += gt-lists.h +GT_H += gt-mcf.h +GT_H += gt-omp-general.h gt-omp-low.h gt-optabs-libfuncs.h +GT_H += gt-passes.h gt-path-coverage.h gt-prime-paths.h gt-profile.h +GT_H += gt-reg-stack.h +GT_H += gt-sancov.h gt-sanopt.h gt-stor-layout.h gt-stringpool.h +GT_H += gt-symtab.h gt-symtab-thunks.h +GT_H += gt-targhooks.h gt-trans-mem.h gt-tree.h +GT_H += gt-tree-cfg.h gt-tree-dfa.h gt-tree-eh.h gt-tree-iterator.h +GT_H += gt-tree-nested.h gt-tree-phinodes.h gt-tree-profile.h +GT_H += gt-tree-scalar-evolution.h gt-tree-ssa-address.h +GT_H += gt-tree-ssa-loop-ivopts.h gt-tree-ssanames.h +GT_H += gt-tree-vect-generic.h gt-tsan.h gt-ubsan.h +GT_H += gt-varasm.h gt-vtable-verify.h +GT_H += $(target_GT_H) +GT_H += gt-analyzer-language.h +GT_H += gt-c-c-decl.h gt-c-c-lang.h gt-c-c-objc-common.h gt-c-c-parser.h +GT_H += gt-c-family-c-common.h gt-c-family-c-cppbuiltin.h +GT_H += gt-c-family-c-format.h gt-c-family-c-objc.h gt-c-family-c-pragma.h +GT_H += gtype-cp.h +GT_H += gt-cp-call.h gt-cp-class.h gt-cp-constexpr.h gt-cp-constraint.h +GT_H += gt-cp-contracts.h gt-cp-coroutines.h gt-cp-cp-gimplify.h +GT_H += gt-cp-cp-lang.h gt-cp-cp-objcp-common.h gt-cp-decl.h gt-cp-decl2.h +GT_H += gt-cp-except.h gt-cp-friend.h gt-cp-init.h gt-cp-lambda.h +GT_H += gt-cp-lex.h gt-cp-logic.h gt-cp-mangle.h gt-cp-method.h +GT_H += gt-cp-module.h gt-cp-name-lookup.h gt-cp-parser.h gt-cp-pt.h +GT_H += gt-cp-rtti.h gt-cp-semantics.h gt-cp-tree.h gt-cp-typeck2.h +GT_H += gt-cp-vtable-class-hierarchy.h + +: gtyp-input.list | gengtype |> ^ GEN gtype-desc^ \ + $(TUP_VARIANT_OUTPUTDIR)/gengtype -S $(SRC) \ + -I $(TUP_VARIANT_OUTPUTDIR)/gtyp-input.list \ + -w $(TUP_VARIANT_OUTPUTDIR)/gtype.state && \ + cd $(TUP_VARIANT_OUTPUTDIR) && \ + ./gengtype -r gtype.state \ + |> gtype-desc.cc $(GT_H) + +# ============================================================ +# Phase 4: Generated source compilation → +# ============================================================ + +# Options pipeline outputs +: options.cc |> !cxx |> options.o +: options-save.cc |> !cxx |> options-save.o +: options-urls.cc |> !cxx |> options-urls.o + +# insn-modes (from genmodes) +: insn-modes.cc |> !cxx |> insn-modes.o + +# insn-emit split (from genemit) +: foreach insn-emit-1.cc insn-emit-2.cc insn-emit-3.cc insn-emit-4.cc \ + insn-emit-5.cc insn-emit-6.cc insn-emit-7.cc insn-emit-8.cc \ + insn-emit-9.cc insn-emit-10.cc |> !cxx |> %B.o + +# insn-recog split (from genrecog) +: foreach insn-recog-1.cc insn-recog-2.cc insn-recog-3.cc insn-recog-4.cc \ + insn-recog-5.cc insn-recog-6.cc insn-recog-7.cc insn-recog-8.cc \ + insn-recog-9.cc insn-recog-10.cc |> !cxx |> %B.o + +# Other generated sources +gen_srcs = insn-attrtab.cc insn-dfatab.cc insn-latencytab.cc +gen_srcs += insn-automata.cc insn-extract.cc insn-output.cc insn-peep.cc +gen_srcs += insn-preds.cc insn-opinit.cc insn-enums.cc +: foreach $(gen_srcs) |> !cxx |> %B.o + +# gimple-match split (from genmatch --gimple) +: foreach gimple-match-1.cc gimple-match-2.cc gimple-match-3.cc gimple-match-4.cc \ + gimple-match-5.cc gimple-match-6.cc gimple-match-7.cc gimple-match-8.cc \ + gimple-match-9.cc gimple-match-10.cc |> !cxx |> %B.o + +# generic-match split (from genmatch --generic) +: foreach generic-match-1.cc generic-match-2.cc generic-match-3.cc generic-match-4.cc \ + generic-match-5.cc generic-match-6.cc generic-match-7.cc generic-match-8.cc \ + generic-match-9.cc generic-match-10.cc |> !cxx |> %B.o + +# gimple-match-exports (hand-written API wrapper for generated match code) +: gimple-match-exports.cc |> !cxx |> gimple-match-exports.o + +# gtype-desc (from gengtype) +: gtype-desc.cc |> !cxx |> gtype-desc.o + +# ============================================================ +# Phase 5: Backend objects (OBJS from Makefile.in) +# ============================================================ +# ~445 source files from gcc/. Excludes: +# - analyzer/* (compiled in analyzer/Tupfile) +# - config/* (compiled in config/*/Tupfile) +# - Generated insn-*.cc, options*.cc, gtype-desc.cc (compiled above) + +objs = ggc-page.cc adjust-alignment.cc alias.cc alloc-pool.cc +objs += auto-inc-dec.cc auto-profile.cc +objs += bb-reorder.cc bitmap.cc builtins.cc caller-save.cc +objs += calls.cc ccmp.cc cfg.cc cfganal.cc cfgbuild.cc cfgcleanup.cc +objs += cfgexpand.cc cfghooks.cc cfgloop.cc cfgloopanal.cc +objs += cfgloopmanip.cc cfgrtl.cc +objs += ctfc.cc ctfout.cc btfout.cc +objs += symtab.cc symtab-thunks.cc symtab-clones.cc +objs += cgraph.cc cgraphbuild.cc cgraphunit.cc cgraphclones.cc +objs += combine.cc combine-stack-adj.cc compare-elim.cc context.cc +objs += convert.cc coroutine-passes.cc coverage.cc +objs += cprop.cc cse.cc cselib.cc +objs += data-streamer.cc data-streamer-in.cc data-streamer-out.cc +objs += dbgcnt.cc dce.cc ddg.cc debug.cc +objs += df-core.cc df-problems.cc df-scan.cc dfp.cc digraph.cc +objs += dojump.cc dominance.cc domwalk.cc double-int.cc dse.cc +objs += dumpfile.cc dwarf2asm.cc dwarf2cfi.cc +objs += dwarf2codeview.cc dwarf2ctf.cc dwarf2out.cc +objs += early-remat.cc emit-rtl.cc et-forest.cc except.cc +objs += explow.cc expmed.cc expr.cc ext-dce.cc +objs += fibonacci_heap.cc file-prefix-map.cc final.cc fixed-value.cc +objs += fold-const.cc fold-const-call.cc fold-mem-offsets.cc +objs += function.cc function-abi.cc function-tests.cc fwprop.cc +objs += gcc-attribute-urlifier.cc gcc-rich-location.cc gcc-urlifier.cc +objs += gcse.cc gcse-common.cc ggc-common.cc ggc-tests.cc +objs += gimple.cc gimple-array-bounds.cc gimple-builder.cc +objs += gimple-expr.cc gimple-if-to-switch.cc gimple-iterator.cc +objs += gimple-fold.cc gimple-harden-conditionals.cc +objs += gimple-harden-control-flow.cc gimple-laddress.cc +objs += gimple-loop-interchange.cc gimple-loop-jam.cc +objs += gimple-loop-versioning.cc gimple-low.cc gimple-lower-bitint.cc +objs += gimple-predicate-analysis.cc gimple-pretty-print.cc +objs += gimple-range.cc gimple-range-cache.cc gimple-range-edge.cc +objs += gimple-range-fold.cc gimple-range-gori.cc gimple-range-infer.cc +objs += gimple-range-op.cc gimple-range-phi.cc gimple-range-trace.cc +objs += gimple-ssa-backprop.cc gimple-ssa-isolate-paths.cc +objs += gimple-ssa-nonnull-compare.cc gimple-ssa-sccopy.cc +objs += gimple-ssa-split-paths.cc gimple-ssa-store-merging.cc +objs += gimple-ssa-strength-reduction.cc gimple-ssa-sprintf.cc +objs += gimple-ssa-warn-access.cc gimple-ssa-warn-alloca.cc +objs += gimple-ssa-warn-restrict.cc +objs += gimple-streamer-in.cc gimple-streamer-out.cc +objs += gimple-walk.cc gimple-warn-recursion.cc +objs += gimplify.cc gimplify-me.cc godump.cc graph.cc +objs += graphds.cc graphviz.cc +objs += graphite.cc graphite-isl-ast-to-gimple.cc +objs += graphite-dependences.cc graphite-optimize-isl.cc +objs += graphite-poly.cc graphite-scop-detection.cc +objs += graphite-sese-to-poly.cc +objs += haifa-sched.cc hash-map-tests.cc hash-set-tests.cc +objs += hw-doloop.cc hwint.cc ifcvt.cc ree.cc +objs += inchash.cc incpath.cc init-regs.cc internal-fn.cc +objs += ipa-locality-cloning.cc ipa-cp.cc ipa-sra.cc ipa-devirt.cc +objs += ipa-fnsummary.cc ipa-polymorphic-call.cc ipa-split.cc +objs += ipa-inline.cc ipa-comdats.cc ipa-free-lang-data.cc +objs += ipa-visibility.cc ipa-inline-analysis.cc ipa-inline-transform.cc +objs += ipa-modref.cc ipa-modref-tree.cc ipa-predicate.cc ipa-profile.cc +objs += ipa-prop.cc ipa-param-manipulation.cc ipa-pure-const.cc +objs += ipa-icf.cc ipa-icf-gimple.cc ipa-reference.cc +objs += ipa-ref.cc ipa-utils.cc ipa-strub.cc ipa.cc +objs += ira.cc pair-fusion.cc ira-build.cc ira-costs.cc +objs += ira-conflicts.cc ira-color.cc ira-emit.cc ira-lives.cc +objs += jump.cc langhooks.cc late-combine.cc lazy-diagnostic-path.cc +objs += lcm.cc lists.cc +objs += loop-doloop.cc loop-init.cc loop-invariant.cc loop-iv.cc +objs += loop-unroll.cc lower-subreg.cc +objs += lra.cc lra-assigns.cc lra-coalesce.cc lra-constraints.cc +objs += lra-eliminations.cc lra-lives.cc lra-remat.cc lra-spills.cc +objs += lto-cgraph.cc lto-streamer.cc lto-streamer-out.cc +objs += lto-section-in.cc lto-section-out.cc +objs += lto-opts.cc lto-compress.cc +objs += mcf.cc mode-switching.cc modulo-sched.cc multiple_target.cc +objs += omp-offload.cc omp-expand.cc omp-general.cc omp-low.cc +objs += omp-oacc-kernels-decompose.cc omp-oacc-neuter-broadcast.cc +objs += omp-simd-clone.cc opt-problem.cc +objs += optabs.cc optabs-libfuncs.cc optabs-query.cc optabs-tree.cc +objs += optinfo.cc opts-global.cc +objs += ordered-hash-map-tests.cc passes.cc prime-paths.cc path-coverage.cc +objs += plugin.cc pointer-query.cc postreload-gcse.cc postreload.cc +objs += predict.cc print-rtl.cc print-rtl-function.cc print-tree.cc +objs += profile.cc profile-count.cc +objs += range.cc range-op.cc range-op-float.cc range-op-ptr.cc +objs += read-md.cc read-rtl.cc read-rtl-function.cc +objs += real.cc realmpfr.cc recog.cc reg-stack.cc +objs += regcprop.cc reginfo.cc regrename.cc regstat.cc +objs += reload.cc reload1.cc reorg.cc resource.cc rtl-error.cc +objs += rtl-ssa/accesses.cc rtl-ssa/blocks.cc rtl-ssa/changes.cc +objs += rtl-ssa/functions.cc rtl-ssa/insns.cc rtl-ssa/movement.cc +objs += rtl-tests.cc rtl.cc rtlhash.cc rtlanal.cc rtlhooks.cc +objs += rtx-vector-builder.cc run-rtl-passes.cc +objs += sched-deps.cc sched-ebb.cc sched-rgn.cc +objs += sel-sched-ir.cc sel-sched-dump.cc sel-sched.cc +objs += selftest-rtl.cc selftest-run-tests.cc +objs += sese.cc shrink-wrap.cc simplify-rtx.cc +objs += sparseset.cc spellcheck.cc spellcheck-tree.cc +objs += splay-tree-utils.cc sreal.cc stack-ptr-mod.cc statistics.cc +objs += stmt.cc stor-layout.cc avoid-store-forwarding.cc store-motion.cc +objs += streamer-hooks.cc stringpool.cc substring-locations.cc +objs += target-globals.cc targhooks.cc timevar.cc tracer.cc +objs += trans-mem.cc tree-affine.cc +objs += asan.cc tsan.cc ubsan.cc sanopt.cc sancov.cc +objs += simple-diagnostic-path.cc +objs += tree-assume.cc tree-call-cdce.cc tree-cfg.cc tree-cfgcleanup.cc +objs += tree-chrec.cc tree-complex.cc tree-data-ref.cc tree-dfa.cc +objs += tree-diagnostic.cc +objs += tree-dump.cc tree-eh.cc tree-emutls.cc tree-if-conv.cc +objs += tree-inline.cc tree-into-ssa.cc tree-iterator.cc +objs += tree-logical-location.cc tree-loop-distribution.cc +objs += crc-verification.cc gimple-crc-optimization.cc +objs += sym-exec/sym-exec-expression.cc sym-exec/sym-exec-state.cc +objs += sym-exec/sym-exec-condition.cc +objs += tree-nested.cc tree-nrv.cc tree-object-size.cc tree-outof-ssa.cc +objs += tree-parloops.cc tree-phinodes.cc tree-predcom.cc +objs += tree-pretty-print.cc tree-profile.cc tree-scalar-evolution.cc +objs += tree-sra.cc tree-switch-conversion.cc +objs += tree-ssa-address.cc tree-ssa-alias.cc tree-ssa-ccp.cc +objs += tree-ssa-coalesce.cc tree-ssa-copy.cc tree-ssa-dce.cc +objs += tree-ssa-dom.cc tree-ssa-dse.cc tree-ssa-forwprop.cc +objs += tree-ssa-ifcombine.cc tree-ssa-live.cc tree-ssa-loop-ch.cc +objs += tree-ssa-loop-im.cc tree-ssa-loop-ivcanon.cc +objs += tree-ssa-loop-ivopts.cc tree-ssa-loop-manip.cc +objs += tree-ssa-loop-niter.cc tree-ssa-loop-prefetch.cc +objs += tree-ssa-loop-split.cc tree-ssa-loop-unswitch.cc +objs += tree-ssa-loop.cc tree-ssa-math-opts.cc tree-ssa-operands.cc +objs += gimple-range-path.cc tree-ssa-phiopt.cc tree-ssa-phiprop.cc +objs += tree-ssa-pre.cc tree-ssa-propagate.cc tree-ssa-reassoc.cc +objs += tree-ssa-sccvn.cc tree-ssa-scopedtables.cc tree-ssa-sink.cc +objs += tree-ssa-strlen.cc tree-ssa-structalias.cc +objs += tree-ssa-tail-merge.cc tree-ssa-ter.cc +objs += tree-ssa-threadbackward.cc tree-ssa-threadedge.cc +objs += tree-ssa-threadupdate.cc tree-ssa-uncprop.cc +objs += tree-ssa-uninit.cc tree-ssa.cc tree-ssanames.cc tree-stdarg.cc +objs += tree-streamer.cc tree-streamer-in.cc tree-streamer-out.cc +objs += tree-tailcall.cc tree-vect-generic.cc gimple-isel.cc +objs += tree-vect-patterns.cc tree-vect-data-refs.cc +objs += tree-vect-stmts.cc tree-vect-loop.cc tree-vect-loop-manip.cc +objs += tree-vect-slp.cc tree-vect-slp-patterns.cc tree-vectorizer.cc +objs += tree-vector-builder.cc tree-vrp.cc tree.cc +objs += tristate.cc typed-splay-tree.cc valtrack.cc +objs += value-pointer-equiv.cc value-query.cc value-range.cc +objs += value-range-pretty-print.cc value-range-storage.cc +objs += value-relation.cc value-prof.cc var-tracking.cc +objs += varasm.cc varpool.cc vec-perm-indices.cc vmsdbgout.cc +objs += vr-values.cc vtable-verify.cc warning-control.cc web.cc +objs += wide-int.cc wide-int-print.cc + +# Special -D flags for a few objects (use !cxx-defs with EXTRA_DEFS) +EXTRA_DEFS = -DTARGET_NAME=\"@(TARGET)\" +: toplev.cc |> !cxx-defs |> toplev.o + +EXTRA_DEFS = -DTARGET_MACHINE=\"@(TARGET)\" +: lto-streamer-in.cc |> !cxx-defs |> lto-streamer-in.o + +EXTRA_DEFS = -DTARGET_NAME=\"@(TARGET)\" +: optinfo-emit-json.cc |> !cxx-defs |> optinfo-emit-json.o + +EXTRA_DEFS = -DTARGET_NAME=\"@(TARGET)\" +: tree-diagnostic-client-data-hooks.cc |> !cxx-defs |> tree-diagnostic-client-data-hooks.o + +# Preprocessor search path defines (PREPROCESSOR_DEFINES in Makefile.in) +PP_DEFS = -DPREFIX=\"/usr/local/\" +PP_DEFS += -DSTANDARD_EXEC_PREFIX=\"/usr/local/lib/gcc/\" +PP_DEFS += -DGCC_INCLUDE_DIR=\"/usr/local/lib/gcc/@(TARGET)/15.2.0/include\" +PP_DEFS += -DFIXED_INCLUDE_DIR=\"/usr/local/lib/gcc/@(TARGET)/15.2.0/include-fixed\" +PP_DEFS += -DGPLUSPLUS_INCLUDE_DIR=\"/usr/local/include/c++/15.2.0\" +PP_DEFS += -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=0 +PP_DEFS += -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"/usr/local/include/c++/15.2.0/@(TARGET)\" +PP_DEFS += -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"/usr/local/include/c++/15.2.0/backward\" +PP_DEFS += -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"\" +PP_DEFS += -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=0 +PP_DEFS += -DLOCAL_INCLUDE_DIR=\"/usr/local/include\" +PP_DEFS += -DCROSS_INCLUDE_DIR=\"/usr/include\" +PP_DEFS += -DTOOL_INCLUDE_DIR=\"/usr/local/@(TARGET)/include\" +PP_DEFS += -DNATIVE_SYSTEM_HEADER_DIR=\"/usr/include\" + +EXTRA_DEFS = $(PP_DEFS) -DBASEVER=\"15.2.0\" +: cppbuiltin.cc |> !cxx-defs |> cppbuiltin.o + +EXTRA_DEFS = $(PP_DEFS) +: cppdefault.cc |> !cxx-defs |> cppdefault.o + +: foreach $(objs) |> !cxx |> %B.o + +# ============================================================ +# Phase 6: Common objects (OBJS-libcommon + OBJS-libcommon-target) +# ============================================================ +# These are utility objects shared across GCC frontends. +# For cc1, we compile them once and link directly. + +common = diagnostic-spec.cc diagnostic.cc diagnostic-color.cc +common += diagnostic-format-json.cc diagnostic-format-sarif.cc +common += diagnostic-format-text.cc diagnostic-global-context.cc +common += diagnostic-macro-unwinding.cc diagnostic-path.cc +common += diagnostic-show-locus.cc edit-context.cc +common += pretty-print.cc intl.cc json.cc json-parsing.cc +common += sbitmap.cc vec.cc input.cc hash-table.cc memory-block.cc +common += selftest.cc selftest-diagnostic.cc sort.cc +common += selftest-diagnostic-path.cc selftest-json.cc +common += selftest-logical-location.cc +common += text-art/box-drawing.cc text-art/canvas.cc text-art/ruler.cc +common += text-art/selftests.cc text-art/style.cc text-art/styled-string.cc +common += text-art/table.cc text-art/theme.cc text-art/tree-widget.cc +common += text-art/widget.cc + +# OBJS-libcommon-target (unique entries not in common or main objs) +common += opts.cc opts-common.cc opts-diagnostic.cc +common += hooks.cc file-find.cc opt-suggestions.cc + +: foreach $(common) |> !cxx |> %B.o + +EXTRA_DEFS = -DPREFIX=\"/usr/local\" -DBASEVER=\"15.2.0\" +: prefix.cc |> !cxx-defs |> prefix.o + +# Target-specific common objects (from subdirectories) +: common/common-targhooks.cc |> !cxx |> common-targhooks.o + +# Host hooks (platform-specific replaces default when available) +: config/host-@(HOST_OS).cc |> !cxx |> host-@(HOST_OS).o + +# main.o +: main.cc |> !cxx |> main.o + +# cc1-checksum.o (stub — real GCC uses genchecksum to embed a binary hash) +: |> ^ GEN %o^ echo 'extern const unsigned char executable_checksum[16] = {0};' > %o \ + |> cc1-checksum.cc +: cc1-checksum.cc |> !cxx |> cc1-checksum.o + +# attribs.o (C frontend, but compiled in gcc/) +: attribs.cc |> !cxx |> attribs.o + +# ============================================================ +# Phase 7: Link cc1 +# ============================================================ +# Collects objects from this directory and subdirectories: +# gcc/c/ → ../ (C frontend) +# gcc/c-family/ → ../ (C-family shared code) +# gcc/analyzer/ → ../ (static analyzer) +# gcc/config/*/ → ../../ (target-specific objects) + +: $(LIBCPP_A) $(LIBDECNUMBER_A) $(LIBBACKTRACE_A) \ + $(LIBIBERTY_A) $(LIBGMP_A) $(LIBMPFR_A) $(LIBMPC_A) \ + | c/ c-family/ analyzer/ |> \ + ^ LINK cc1^ sh -c '$(CXX) % \ + $(LIBCPP_A) $(LIBDECNUMBER_A) $(LIBBACKTRACE_A) \ + $(LIBMPC_A) $(LIBMPFR_A) $(LIBGMP_A) $(LIBIBERTY_A) \ + @(PLATFORM_LDFLAGS) -o %o' |> cc1 + +# ============================================================ +# Phase 8: xgcc driver +# ============================================================ +# The `gcc` command that users invoke. Dispatches to cc1/cc1plus/as/ld +# based on file extensions and flags. Links against shared utility +# objects (already compiled for cc1) + its own driver-specific objects. + +# multilib.h — multilib configuration (no multilib for cross-compiler) +: |> ^ GEN %o^ sh $(SRC)/genmultilib '' '' '' '' '' '' '' '' '' '' no > %o \ + |> multilib.h + +# specs.h — additional language spec entries for default_compilers[] +# C specs are built into gcc.cc; other languages add via this header. +# Includes cp/lang-specs.h for C++ file extension recognition. +: |> ^ GEN %o^ echo '#include "cp/lang-specs.h"' > %o |> specs.h + +# Driver path defines (embedded installation paths) +DRIVER_DEFS = -DSTANDARD_STARTFILE_PREFIX=\"../lib/\" +DRIVER_DEFS += -DSTANDARD_EXEC_PREFIX=\"/usr/local/lib/gcc/\" +DRIVER_DEFS += -DSTANDARD_LIBEXEC_PREFIX=\"/usr/local/libexec/gcc/\" +DRIVER_DEFS += -DDEFAULT_TARGET_VERSION=\"15.2.0\" +DRIVER_DEFS += -DDEFAULT_REAL_TARGET_MACHINE=\"@(TARGET)\" +DRIVER_DEFS += -DDEFAULT_TARGET_MACHINE=\"@(TARGET)\" +DRIVER_DEFS += -DSTANDARD_BINDIR_PREFIX=\"/usr/local/bin/\" +DRIVER_DEFS += -DTOOLDIR_BASE_PREFIX=\"../../\" +DRIVER_DEFS += -DACCEL_DIR_SUFFIX=\"\" +DRIVER_DEFS += -DCONFIGURE_SPECS=\"\" +DRIVER_DEFS += -DTOOL_INCLUDE_DIR=\"/usr/local/@(TARGET)/include\" +DRIVER_DEFS += -DNATIVE_SYSTEM_HEADER_DIR=\"/usr/include\" +DRIVER_DEFS += -DOFFLOAD_TARGETS=\"\" + +EXTRA_DEFS = $(DRIVER_DEFS) -DBASEVER=\"15.2.0\" +: gcc.cc | specs.h |> !cxx-defs |> gcc-driver.o + +EXTRA_DEFS = +: gcc-main.cc |> !cxx |> gcc-main-driver.o +: ggc-none.cc |> !cxx |> xgcc-ggc-none.o +: c/gccspec.cc |> !cxx |> gccspec.o + +# Shared objects for driver-like binaries (xgcc, collect2, g++). +# Equivalent to libcommon.a + libcommon-target.a in the autotools build. +D = $(TUP_VARIANT_OUTPUTDIR) +LIBCOMMON_OBJS = $(D)/diagnostic-spec.o $(D)/diagnostic.o $(D)/diagnostic-color.o +LIBCOMMON_OBJS += $(D)/diagnostic-format-json.o $(D)/diagnostic-format-sarif.o +LIBCOMMON_OBJS += $(D)/diagnostic-format-text.o $(D)/diagnostic-global-context.o +LIBCOMMON_OBJS += $(D)/diagnostic-macro-unwinding.o $(D)/diagnostic-path.o +LIBCOMMON_OBJS += $(D)/diagnostic-show-locus.o $(D)/edit-context.o $(D)/pretty-print.o +LIBCOMMON_OBJS += $(D)/intl.o $(D)/json.o $(D)/json-parsing.o $(D)/sbitmap.o +LIBCOMMON_OBJS += $(D)/vec.o $(D)/input.o $(D)/hash-table.o $(D)/memory-block.o +LIBCOMMON_OBJS += $(D)/selftest.o $(D)/selftest-diagnostic.o $(D)/sort.o +LIBCOMMON_OBJS += $(D)/selftest-diagnostic-path.o $(D)/selftest-json.o +LIBCOMMON_OBJS += $(D)/selftest-logical-location.o +LIBCOMMON_OBJS += $(D)/box-drawing.o $(D)/canvas.o $(D)/ruler.o $(D)/selftests.o +LIBCOMMON_OBJS += $(D)/style.o $(D)/styled-string.o $(D)/table.o $(D)/theme.o +LIBCOMMON_OBJS += $(D)/tree-widget.o $(D)/widget.o +LIBCOMMON_OBJS += $(D)/i386-common.o $(D)/prefix.o $(D)/opts.o $(D)/opts-common.o +LIBCOMMON_OBJS += $(D)/opts-diagnostic.o $(D)/options.o $(D)/hooks.o +LIBCOMMON_OBJS += $(D)/common-targhooks.o $(D)/file-find.o $(D)/spellcheck.o +LIBCOMMON_OBJS += $(D)/opt-suggestions.o $(D)/options-urls.o $(D)/gcc-urlifier.o + +DRIVER_LIBS = $(LIBCPP_A) $(LIBBACKTRACE_A) $(LIBDECNUMBER_A) $(LIBIBERTY_A) + +# Link xgcc +: $(DRIVER_LIBS) \ + | |> ^ LINK xgcc^ sh -c '$(CXX) % \ + $(LIBCOMMON_OBJS) $(DRIVER_LIBS) \ + @(PLATFORM_LDFLAGS) -o %o' |> xgcc + +# ============================================================ +# Phase 9: cc1plus (C++ compiler) +# ============================================================ +# Same backend as cc1, swapping C frontend (c/) for C++ frontend (cp/). +# Adds libcody for C++ modules protocol support. + +# Link cc1plus — backend + C++ frontend + shared frontends + libraries. +# Uses for the shared backend (includes main.o, cc1-checksum.o). +# The checksum stub is identical for both compilers. +: $(LIBCPP_A) $(LIBDECNUMBER_A) $(LIBBACKTRACE_A) \ + $(LIBIBERTY_A) $(LIBGMP_A) $(LIBMPFR_A) $(LIBMPC_A) $(LIBCODY_A) \ + | cp/ c-family/ analyzer/ |> \ + ^ LINK cc1plus^ sh -c '$(CXX) % \ + $(TUP_VARIANT_OUTPUTDIR)/cp/*.o \ + $(LIBCPP_A) $(LIBDECNUMBER_A) $(LIBBACKTRACE_A) \ + $(LIBMPC_A) $(LIBMPFR_A) $(LIBGMP_A) $(LIBCODY_A) $(LIBIBERTY_A) \ + @(PLATFORM_LDFLAGS) -o %o' |> cc1plus + +# ============================================================ +# Phase 10: collect2 (linker wrapper) +# ============================================================ +# Intercepts linker invocations to collect C++ static constructors/destructors. +# Standalone binary with its own main() — not a driver variant. + +EXTRA_DEFS = -DTARGET_MACHINE=\"@(TARGET)\" +: collect2.cc |> !cxx-defs |> collect2-main.o + +EXTRA_DEFS = +: collect2-aix.cc |> !cxx |> collect2-aix.o +: collect-utils.cc |> !cxx |> collect-utils.o +: ggc-none.cc |> !cxx |> collect2-ggc-none.o + +: $(DRIVER_LIBS) \ + | |> ^ LINK collect2^ sh -c '$(CXX) % \ + $(LIBCOMMON_OBJS) $(DRIVER_LIBS) \ + @(PLATFORM_LDFLAGS) -o %o' |> collect2 + +# ============================================================ +# Phase 11: g++ driver (xg++) +# ============================================================ +# C++ driver — same as xgcc but links g++spec.o instead of gccspec.o. +# Defaults to C++ mode, adds -lstdc++ and C++ library paths. + +EXTRA_DEFS = $(DRIVER_DEFS) +: cp/g++spec.cc |> !cxx-defs |> g++spec.o + +EXTRA_DEFS = +: $(DRIVER_LIBS) \ + | |> ^ LINK xg++^ sh -c '$(CXX) \ + $(D)/gcc-driver.o $(D)/gcc-main-driver.o $(D)/xgcc-ggc-none.o $(TARGET_DRIVER_LINK) % \ + $(LIBCOMMON_OBJS) $(DRIVER_LIBS) \ + @(PLATFORM_LDFLAGS) -o %o' |> xg++ + +# ============================================================ +# Phase 12: cpp (C preprocessor) +# ============================================================ +# Same as xgcc but with cppspec.o — invokes cc1 with -E flag. + +EXTRA_DEFS = $(DRIVER_DEFS) +: c-family/cppspec.cc |> !cxx-defs |> cppspec.o + +EXTRA_DEFS = +: $(DRIVER_LIBS) \ + | |> ^ LINK cpp^ sh -c '$(CXX) \ + $(D)/gcc-driver.o $(D)/gcc-main-driver.o $(D)/xgcc-ggc-none.o $(TARGET_DRIVER_LINK) % \ + $(LIBCOMMON_OBJS) $(DRIVER_LIBS) \ + @(PLATFORM_LDFLAGS) -o %o' |> cpp + +# ============================================================ +# Phase 13: lto-wrapper (LTO linker plugin interface) +# ============================================================ + +: lto-wrapper.cc |> !cxx |> lto-wrapper.o +: lockfile.cc |> !cxx |> lockfile.o +: lto-ltrans-cache.cc |> !cxx |> lto-ltrans-cache.o + +: $(DRIVER_LIBS) \ + | |> ^ LINK lto-wrapper^ sh -c '$(CXX) % \ + $(D)/collect-utils.o $(D)/collect2-ggc-none.o \ + $(LIBCOMMON_OBJS) $(DRIVER_LIBS) \ + @(PLATFORM_LDFLAGS) -o %o' |> lto-wrapper + +# ============================================================ +# Phase 14: gcov + gcov-dump (code coverage analysis) +# ============================================================ + +: gcov.cc |> !cxx |> gcov.o + +: $(DRIVER_LIBS) \ + | |> ^ LINK gcov^ sh -c '$(CXX) % \ + $(D)/graphds.o $(D)/prime-paths.o $(D)/bitmap.o \ + $(D)/xgcc-ggc-none.o $(LIBCOMMON_OBJS) $(DRIVER_LIBS) \ + -lz @(PLATFORM_LDFLAGS) -o %o' |> gcov + +: gcov-dump.cc |> !cxx |> gcov-dump.o + +: $(DRIVER_LIBS) \ + | |> ^ LINK gcov-dump^ sh -c '$(CXX) % \ + $(D)/xgcc-ggc-none.o $(LIBCOMMON_OBJS) $(DRIVER_LIBS) \ + @(PLATFORM_LDFLAGS) -o %o' |> gcov-dump diff --git a/examples/gcc/gcc/Tuprules.tup b/examples/gcc/gcc/Tuprules.tup new file mode 100644 index 0000000..5202954 --- /dev/null +++ b/examples/gcc/gcc/Tuprules.tup @@ -0,0 +1,79 @@ +# gcc/ build rules (self-contained with ?= defaults) +# +# Two compilation modes: +# HOST — generator programs (run on build machine) +# TARGET — cc1 backend objects (run on target) + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= gcc +CXX ?= g++ +AR ?= ar +HOSTCC ?= g++ +GCC_DIR ?= . +GMP_DIR ?= gmp +MPFR_DIR ?= mpfr +MPC_DIR ?= mpc +LIBIBERTY_DIR ?= libiberty +LIBCPP_DIR ?= libcpp +LIBDECNUMBER_DIR ?= libdecnumber +LIBBACKTRACE_DIR ?= libbacktrace +LIBCODY_DIR ?= libcody + +# Resolved library paths +LIBIBERTY_A = $(B)/$(LIBIBERTY_DIR)/libiberty.a +LIBCPP_A = $(B)/$(LIBCPP_DIR)/libcpp.a +LIBDECNUMBER_A = $(B)/$(LIBDECNUMBER_DIR)/libdecnumber.a +LIBBACKTRACE_A = $(B)/$(LIBBACKTRACE_DIR)/libbacktrace.a +LIBGMP_A = $(B)/$(GMP_DIR)/libgmp.a +LIBMPFR_A = $(B)/$(MPFR_DIR)/src/libmpfr.a +LIBMPC_A = $(B)/$(MPC_DIR)/src/libmpc.a +LIBCODY_A = $(B)/$(LIBCODY_DIR)/libcody.a + +# Common include paths +GCC_INCLUDES = -I$(B)/$(GCC_DIR) -I$(S)/$(GCC_DIR) +GCC_INCLUDES += -I$(S)/$(GCC_DIR)/../include +GCC_INCLUDES += -I$(S)/$(LIBCPP_DIR)/include +GCC_INCLUDES += -I$(B)/$(LIBDECNUMBER_DIR) -I$(S)/$(LIBDECNUMBER_DIR) +GCC_INCLUDES += -I$(S)/$(LIBDECNUMBER_DIR)/@(DECIMAL_FORMAT) +GCC_INCLUDES += -I$(B)/$(LIBBACKTRACE_DIR) -I$(S)/$(LIBBACKTRACE_DIR) +GCC_INCLUDES += -I$(B)/$(GMP_DIR) -I$(S)/$(GMP_DIR) +GCC_INCLUDES += -I$(B)/$(MPFR_DIR)/src -I$(S)/$(MPFR_DIR)/src +GCC_INCLUDES += -I$(B)/$(MPC_DIR)/src -I$(S)/$(MPC_DIR)/src +GCC_INCLUDES += -I$(S)/$(LIBCODY_DIR) + +# --- HOST compilation (generators) --- + +HOST_CXXFLAGS = -O0 -std=gnu++14 +HOST_CXXFLAGS += -DIN_GCC -DGENERATOR_FILE -DHAVE_CONFIG_H +HOST_CXXFLAGS += $(GCC_INCLUDES) + +!hostcxx = | $(S)/$(GCC_DIR)/ |> \ + ^ HOSTCXX %b^ $(HOSTCC) $(HOST_CXXFLAGS) -c %f -o %o |> %B.o + +# gengtype uses -DHOST_GENERATOR_FILE (not -DGENERATOR_FILE) for full host header access +GENGTYPE_CXXFLAGS = -O0 -std=gnu++14 +GENGTYPE_CXXFLAGS += -DIN_GCC -DHOST_GENERATOR_FILE -DHAVE_CONFIG_H +GENGTYPE_CXXFLAGS += $(GCC_INCLUDES) + +!hostcxx-gengtype = | $(S)/$(GCC_DIR)/ |> \ + ^ HOSTCXX %b^ $(HOSTCC) $(GENGTYPE_CXXFLAGS) -c %f -o %o |> host-%B.o + +# --- TARGET compilation (cc1 objects) --- + +TARGET_CXXFLAGS = -O2 -std=gnu++14 +TARGET_CXXFLAGS += -DIN_GCC -DHAVE_CONFIG_H +TARGET_CXXFLAGS += $(GCC_INCLUDES) + +!cxx = | $(S)/$(GCC_DIR)/ $(S)/$(GCC_DIR)/ \ + $(S)/$(GCC_DIR)/ |> \ + ^ CXX %b^ $(CXX) $(TARGET_CXXFLAGS) -c %f -o %o |> + +# Like !cxx but with $(EXTRA_DEFS) for per-file -D flags +!cxx-defs = | $(S)/$(GCC_DIR)/ $(S)/$(GCC_DIR)/ \ + $(S)/$(GCC_DIR)/ |> \ + ^ CXX %b^ $(CXX) $(TARGET_CXXFLAGS) $(EXTRA_DEFS) -c %f -o %o |> + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(GCC_DIR)/tup.config > %o |> diff --git a/examples/gcc/gcc/analyzer/Tupfile b/examples/gcc/gcc/analyzer/Tupfile new file mode 100644 index 0000000..ec845af --- /dev/null +++ b/examples/gcc/gcc/analyzer/Tupfile @@ -0,0 +1,29 @@ +include_rules + +# ============================================================ +# gcc/analyzer/ — Static analyzer (GCC 15.2.0) +# ============================================================ +# Objects contribute to for the cc1 link. +# Parent references this group as analyzer/ in order-only deps. +# Source list from ANALYZER_OBJS in Makefile.in. + +srcs = access-diagram.cc analysis-plan.cc analyzer.cc +srcs += analyzer-language.cc analyzer-logging.cc analyzer-pass.cc +srcs += analyzer-selftests.cc bar-chart.cc bounds-checking.cc +srcs += call-details.cc call-info.cc call-string.cc call-summary.cc +srcs += checker-event.cc checker-path.cc complexity.cc +srcs += constraint-manager.cc diagnostic-manager.cc +srcs += engine.cc feasible-graph.cc function-set.cc +srcs += infinite-loop.cc infinite-recursion.cc +srcs += kf.cc kf-analyzer.cc kf-lang-cp.cc +srcs += known-function-manager.cc pending-diagnostic.cc +srcs += program-point.cc program-state.cc +srcs += ranges.cc record-layout.cc region.cc region-model.cc +srcs += region-model-asm.cc region-model-manager.cc +srcs += region-model-reachability.cc +srcs += sm.cc sm-file.cc sm-fd.cc sm-malloc.cc +srcs += sm-pattern-test.cc sm-sensitive.cc sm-signal.cc sm-taint.cc +srcs += state-purge.cc store.cc supergraph.cc +srcs += svalue.cc symbol.cc trimmed-graph.cc varargs.cc + +: foreach $(srcs) |> !cxx |> %B.o diff --git a/examples/gcc/gcc/c-family/Tupfile b/examples/gcc/gcc/c-family/Tupfile new file mode 100644 index 0000000..3cde7a4 --- /dev/null +++ b/examples/gcc/gcc/c-family/Tupfile @@ -0,0 +1,23 @@ +include_rules + +# ============================================================ +# gcc/c-family/ — C language family shared code (GCC 15.2.0) +# ============================================================ +# Objects contribute to for the cc1 link. +# Parent references this group as c-family/ in order-only deps. +# Source list from C_COMMON_OBJS + stub-objc. + +srcs = stub-objc.cc +srcs += c-common.cc c-cppbuiltin.cc c-dump.cc c-format.cc +srcs += c-gimplify.cc c-indentation.cc c-lex.cc c-omp.cc +srcs += c-opts.cc c-pch.cc c-ppoutput.cc c-pragma.cc +srcs += c-pretty-print.cc c-semantics.cc c-ada-spec.cc c-ubsan.cc +srcs += known-headers.cc c-attribs.cc c-warn.cc c-spellcheck.cc +srcs += c-type-mismatch.cc + +: foreach $(srcs) |> !cxx |> %B.o + +# c-target-hooks-def.h (generated by genhooks in parent dir) +: | $(S)/$(GCC_DIR)/ |> ^ GEN %o^ \ + $(B)/$(GCC_DIR)/genhooks "C Target Hook" > %o \ + |> c-target-hooks-def.h diff --git a/examples/gcc/gcc/c/Tupfile b/examples/gcc/gcc/c/Tupfile new file mode 100644 index 0000000..f5ffcd7 --- /dev/null +++ b/examples/gcc/gcc/c/Tupfile @@ -0,0 +1,13 @@ +include_rules + +# ============================================================ +# gcc/c/ — C language frontend (GCC 15.2.0) +# ============================================================ +# Objects contribute to for the cc1 link. +# Parent references this group as c/ in order-only deps. + +srcs = c-lang.cc c-errors.cc c-decl.cc c-typeck.cc +srcs += c-convert.cc c-aux-info.cc c-objc-common.cc +srcs += c-parser.cc c-fold.cc gimple-parser.cc + +: foreach $(srcs) |> !cxx |> %B.o diff --git a/examples/gcc/gcc/cp/Tupfile b/examples/gcc/gcc/cp/Tupfile new file mode 100644 index 0000000..9dc99a6 --- /dev/null +++ b/examples/gcc/gcc/cp/Tupfile @@ -0,0 +1,24 @@ +include_rules + +# ============================================================ +# gcc/cp/ -- C++ language frontend (GCC 15.2.0) +# ============================================================ +# Objects contribute to for the cc1plus link. +# Parent references this group as cp/ in order-only deps. +# Source list from CXX_AND_OBJCXX_OBJS + cp-lang.cc in cp/Make-lang.in. + +srcs = cp-lang.cc +srcs += call.cc class.cc constexpr.cc constraint.cc contracts.cc +srcs += coroutines.cc cp-gimplify.cc cp-objcp-common.cc cp-ubsan.cc cvt.cc +srcs += cxx-pretty-print.cc decl.cc decl2.cc dump.cc error.cc except.cc +srcs += expr.cc friend.cc init.cc lambda.cc lex.cc logic.cc mangle.cc +srcs += mapper-client.cc mapper-resolver.cc method.cc +srcs += name-lookup.cc optimize.cc parser.cc pt.cc ptree.cc +srcs += rtti.cc search.cc semantics.cc tree.cc typeck.cc typeck2.cc +srcs += vtable-class-hierarchy.cc + +: foreach $(srcs) |> !cxx |> %B.o + +# module.cc needs special defines for C++ modules support +EXTRA_DEFS = -DHOST_MACHINE=\"@(TARGET)\" -DTARGET_MACHINE=\"@(TARGET)\" +: module.cc |> !cxx-defs |> module.o diff --git a/examples/gcc/gcc/targets/x86_64-pc-linux-gnu.tup b/examples/gcc/gcc/targets/x86_64-pc-linux-gnu.tup new file mode 100644 index 0000000..0f7d60f --- /dev/null +++ b/examples/gcc/gcc/targets/x86_64-pc-linux-gnu.tup @@ -0,0 +1,126 @@ +# targets/x86_64-pc-linux-gnu.tup — x86_64 Linux with glibc +# +# Target-specific configuration for the cc1 build. +# Included by gcc/Tupfile via: include targets/@(TARGET).tup +# +# Provides: +# MD — machine description inputs +# TARGET_OPT_FILES — target-specific .opt files +# target_gtyp_src — gengtype source entries for this target +# target_GT_H — gengtype output headers for this target +# Generates: +# tm.h, tm_p.h — target machine headers → +# Compiles: +# i386-common.cc — target-specific common object → + +# Machine description inputs +MD = common.md config/i386/i386.md + +# Target-specific .opt files +TARGET_OPT_FILES = config/i386/i386.opt config/fused-madd.opt config/linux.opt config/linux-android.opt + +# tm_p.h — target machine prototypes +: |> ^ GEN %o^ ( \ + echo '#ifndef GCC_TM_P_H'; \ + echo '#define GCC_TM_P_H'; \ + echo '#ifdef IN_GCC'; \ + echo '# include "config/i386/i386-protos.h"'; \ + echo '# include "config/linux-protos.h"'; \ + echo '# include "tm-preds.h"'; \ + echo '#endif'; \ + echo '#endif'; \ + ) > %o |> tm_p.h + +# tm.h — target machine description +# Matches the real configure-generated tm.h layout. +: |> ^ GEN %o^ ( \ + echo '#ifndef GCC_TM_H'; \ + echo '#define GCC_TM_H'; \ + echo '#ifndef LIBC_GLIBC'; \ + echo '# define LIBC_GLIBC 1'; \ + echo '#endif'; \ + echo '#ifndef LIBC_UCLIBC'; \ + echo '# define LIBC_UCLIBC 2'; \ + echo '#endif'; \ + echo '#ifndef LIBC_BIONIC'; \ + echo '# define LIBC_BIONIC 3'; \ + echo '#endif'; \ + echo '#ifndef LIBC_MUSL'; \ + echo '# define LIBC_MUSL 4'; \ + echo '#endif'; \ + echo '#ifndef DEFAULT_LIBC'; \ + echo '# define DEFAULT_LIBC LIBC_GLIBC'; \ + echo '#endif'; \ + echo '#ifndef ANDROID_DEFAULT'; \ + echo '# define ANDROID_DEFAULT 0'; \ + echo '#endif'; \ + echo '#ifndef HEAP_TRAMPOLINES_INIT'; \ + echo '# define HEAP_TRAMPOLINES_INIT 0'; \ + echo '#endif'; \ + echo '#ifdef IN_GCC'; \ + echo '# include "options.h"'; \ + echo '# include "insn-constants.h"'; \ + echo '# include "config/vxworks-dummy.h"'; \ + echo '# include "config/i386/biarch64.h"'; \ + echo '# include "config/i386/i386.h"'; \ + echo '# include "config/i386/unix.h"'; \ + echo '# include "config/i386/att.h"'; \ + echo '# include "config/elfos.h"'; \ + echo '# include "config/gnu-user.h"'; \ + echo '# include "config/glibc-stdint.h"'; \ + echo '# include "config/i386/x86-64.h"'; \ + echo '# include "config/i386/gnu-user-common.h"'; \ + echo '# include "config/i386/gnu-user64.h"'; \ + echo '# include "config/linux.h"'; \ + echo '# include "config/linux-android.h"'; \ + echo '# include "config/i386/linux-common.h"'; \ + echo '# include "config/i386/linux64.h"'; \ + echo '# include "config/initfini-array.h"'; \ + echo '#endif'; \ + echo '#if defined IN_GCC && !defined GENERATOR_FILE && !defined USED_FOR_TARGET'; \ + echo '# include "insn-flags.h"'; \ + echo '#endif'; \ + echo '#if defined IN_GCC && !defined GENERATOR_FILE'; \ + echo '# include "insn-modes.h"'; \ + echo '#endif'; \ + echo '# include "defaults.h"'; \ + echo '#endif'; \ + ) > %o |> tm.h + +# Target-specific gtyp_src entries (appended by main Tupfile) +target_gtyp_src = config/i386/i386.h config/i386/unix.h config/i386/att.h +target_gtyp_src += config/elfos.h config/gnu-user.h config/glibc-stdint.h +target_gtyp_src += config/i386/x86-64.h config/i386/gnu-user-common.h config/i386/gnu-user64.h +target_gtyp_src += config/linux.h config/linux-android.h config/i386/linux-common.h +target_gtyp_src += config/i386/linux64.h config/initfini-array.h +target_gtyp_src += config/i386/i386.cc +target_gtyp_src += config/i386/i386-builtins.cc config/i386/i386-expand.cc config/i386/i386-options.cc + +# Target-specific GT_H entries +target_GT_H = gt-i386.h gt-i386-builtins.h gt-i386-expand.h gt-i386-options.h + +# i386-builtin-types.inc — generated from .def via AWK +: $(SRC)/config/i386/i386-builtin-types.def |> ^ GEN %o^ \ + awk -f $(SRC)/config/i386/i386-builtin-types.awk %f > %o \ + |> i386-builtin-types.inc + +# Target-specific common object (config.gcc: i386_common_objs) +: common/config/i386/i386-common.cc |> !cxx |> i386-common.o + +# i386 backend objects (config.gcc: out_file + extra_objs + c_target_objs) +target_srcs = config/i386/i386.cc +target_srcs += config/i386/i386-c.cc config/i386/i386-options.cc +target_srcs += config/i386/i386-builtins.cc config/i386/i386-expand.cc +target_srcs += config/i386/i386-features.cc +target_srcs += config/i386/x86-tune-sched.cc config/i386/x86-tune-sched-bd.cc +target_srcs += config/i386/x86-tune-sched-atom.cc config/i386/x86-tune-sched-core.cc +target_srcs += config/i386/gnu-property.cc + +target_srcs += config/linux.cc +target_srcs += config/glibc-c.cc + +: foreach $(target_srcs) |> !cxx |> %B.o + +# x86_64 host CPU detection for the driver (gcc.cc references host_detect_local_cpu) +: config/i386/driver-i386.cc |> !cxx |> driver-i386.o +TARGET_DRIVER_LINK = $(TUP_VARIANT_OUTPUTDIR)/driver-i386.o diff --git a/examples/gcc/gcc/tup.config b/examples/gcc/gcc/tup.config new file mode 100644 index 0000000..2a7159f --- /dev/null +++ b/examples/gcc/gcc/tup.config @@ -0,0 +1,132 @@ +# gcc/ - x86_64-linux auto-host.h defines + +# Platform (shared with root config) +CONFIG_HOST_OS=linux +CONFIG_DECIMAL_FORMAT=bid + +# Type sizes +CONFIG_SIZEOF_SHORT=2 +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_LONG_LONG=8 +CONFIG_SIZEOF_VOID_P=8 +CONFIG_SIZEOF__BOOL=1 +CONFIG_INT64_T_IS_LONG=1 + +# Headers +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_FTW_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LANGINFO_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_RESOURCE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIMES_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_SYS_WAIT_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Functions (Linux/glibc — has mallinfo, posix_fallocate, etc.) +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_CLOCK=1 +CONFIG_HAVE_CLOCK_GETTIME=1 +CONFIG_HAVE_GETRLIMIT=1 +CONFIG_HAVE_GETRUSAGE=1 +CONFIG_HAVE_GETTIMEOFDAY=1 +CONFIG_HAVE_ICONV=1 +CONFIG_HAVE_LANGINFO_CODESET=1 +CONFIG_HAVE_LSTAT=1 +CONFIG_HAVE_MADVISE=1 +CONFIG_HAVE_MALLINFO=1 +CONFIG_HAVE_MALLINFO2=1 +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_MMAP_ANON=1 +CONFIG_HAVE_MMAP_FILE=1 +CONFIG_HAVE_POSIX_FALLOCATE=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_SETRLIMIT=1 +CONFIG_HAVE_SIGACTION=1 +CONFIG_HAVE_STRSIGNAL=1 +CONFIG_HAVE_SYSCONF=1 +CONFIG_HAVE_TIMES=1 +CONFIG_HAVE_VFORK=1 +CONFIG_HAVE_WORKING_FORK=1 +CONFIG_HAVE_WORKING_VFORK=1 + +# Declarations (Linux/glibc — basename and sbrk are declared) +CONFIG_HAVE_DECL_ABORT=1 +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_BASENAME=1 +CONFIG_HAVE_DECL_ERRNO=1 +CONFIG_HAVE_DECL_GETENV=1 +CONFIG_HAVE_DECL_GETOPT=1 +CONFIG_HAVE_DECL_LDGETNAME=0 +CONFIG_HAVE_DECL_MALLOC=1 +CONFIG_HAVE_DECL_REALLOC=1 +CONFIG_HAVE_DECL_SBRK=1 +CONFIG_HAVE_DECL_SNPRINTF=1 +CONFIG_HAVE_DECL_STRSIGNAL=1 +CONFIG_HAVE_DECL_VASPRINTF=1 +CONFIG_HAVE_DECL_VSNPRINTF=1 +CONFIG_HAVE_DECL_STRVERSCMP=1 + +# Build options +CONFIG_GATHER_STATISTICS=0 +CONFIG_CHECKING_P=1 +CONFIG_ENABLE_ANALYZER=1 +CONFIG_ENABLE_OFFLOADING=0 +CONFIG_ENABLE_DECIMAL_FLOAT=1 +CONFIG_ENABLE_DECIMAL_BID_FORMAT=1 + +# Target toolchain +CONFIG_HAVE_GNU_AS=1 +CONFIG_HAVE_GNU_LD=1 +CONFIG_PLUGIN_LD_SUFFIX="ld" + +# Target assembler/linker features (GNU binutils for x86_64-linux) +CONFIG_HAVE_COMDAT_GROUP=1 +CONFIG_HAVE_AS_GOTOFF_IN_DATA=1 +CONFIG_HAVE_AS_IX86_GOT32X=1 +CONFIG_HAVE_AS_IX86_INTERUNIT_MOVQ=1 +CONFIG_HAVE_AS_IX86_TLSLDM=1 +CONFIG_HAVE_AS_IX86_TLSLDMPLT=1 +CONFIG_HAVE_AS_IX86_TLS_GET_ADDR_GOT=1 +CONFIG_HAVE_AS_R_X86_64_CODE_6_GOTTPOFF=0 +CONFIG_HAVE_LD_NOW_SUPPORT=1 +CONFIG_HAVE_LD_PIE_COPYRELOC=1 +CONFIG_HAVE_LD_RELRO_SUPPORT=1 +CONFIG_HAVE_GAS_SHF_MERGE=1 +CONFIG_HAVE_GAS_SECTION_LINK_ORDER=1 +CONFIG_HAVE_GNU_INDIRECT_FUNCTION=1 +CONFIG_ENABLE_FIXED_POINT=0 +CONFIG_HAVE_AS_LEB128=1 +CONFIG_HAVE_GAS_CFI_PERSONALITY_DIRECTIVE=1 +CONFIG_HAVE_GAS_CFI_SECTIONS_DIRECTIVE=1 +CONFIG_HAVE_FHARDENED_SUPPORT=0 +CONFIG_ENABLE_EXTRA_CHECKING=0 +CONFIG_HAVE_GAS_CFI_DIRECTIVE=1 +CONFIG_HAVE_LTO_PLUGIN=0 +CONFIG_CHANGES_ROOT_URL="https://gcc.gnu.org/changes.html" +CONFIG_DOCUMENTATION_ROOT_URL="https://gcc.gnu.org/onlinedocs/" + +# Target glibc version (x86_64-linux with modern glibc) +CONFIG_TARGET_GLIBC_MAJOR=2 +CONFIG_TARGET_GLIBC_MINOR=35 + +# Misc +CONFIG_STDC_HEADERS=1 +CONFIG_ENABLE_ASSERT_CHECKING=1 +CONFIG_DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_AUTO +CONFIG_DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_AUTO diff --git a/examples/gcc/gmp/Tupfile b/examples/gcc/gmp/Tupfile new file mode 100644 index 0000000..110756b --- /dev/null +++ b/examples/gcc/gmp/Tupfile @@ -0,0 +1,70 @@ +include_rules + +# ============================================================ +# GMP 6.2.1 +# ============================================================ + +# --- Phase 1: Generate config.h, gmp-mparam.h, gmp.h, and config.m4 --- + +: |> !gen-config |> config.h + +: @(GMP_MPARAM) |> ^ GEN %o^ cp %f %o |> gmp-mparam.h + +ifeq (@(ASM_ENABLED),y) +: |> ^ GEN %o^ ( \ + echo 'changequote(<,>)ifdef(<__CONFIG_M4_INCLUDED__>,,)'; \ + echo 'define(,<$(LIMB_BITS)>)'; \ + echo 'define(,<$(NAIL_BITS)>)'; \ + echo 'define(,)define(,1)>)' \ + ) > %o |> config.m4 +endif + +: gmp-h.in |> ^ GEN %o^ sed \ + -e 's/@HAVE_HOST_CPU_FAMILY_power@/0/g' \ + -e 's/@HAVE_HOST_CPU_FAMILY_powerpc@/0/g' \ + -e 's/@GMP_LIMB_BITS@/@(LIMB_BITS)/g' \ + -e 's/@GMP_NAIL_BITS@/@(NAIL_BITS)/g' \ + -e 's/@DEFN_LONG_LONG_LIMB@//g' \ + -e 's/@LIBGMP_DLL@/0/g' \ + -e 's/@CC@/@(CC)/g' \ + -e 's/@CFLAGS@//g' \ + %f > %o |> gmp.h + +# --- Phase 2: Build table generators (self-contained via mini-gmp) --- + +: gen-fac.c |> ^ HOSTCC %o^ $(HOSTCC) %f -o %o |> gen-fac +: gen-fib.c |> ^ HOSTCC %o^ $(HOSTCC) %f -o %o |> gen-fib +: gen-bases.c |> ^ HOSTCC %o^ $(HOSTCC) %f -o %o -lm |> gen-bases +: gen-trialdivtab.c |> ^ HOSTCC %o^ $(HOSTCC) %f -o %o -lm |> gen-trialdivtab +: gen-jacobitab.c |> ^ HOSTCC %o^ $(HOSTCC) %f -o %o |> gen-jacobitab +: gen-psqr.c |> ^ HOSTCC %o^ $(HOSTCC) %f -o %o -lm |> gen-psqr + +# --- Phase 3: Generate table headers and sources --- + +: gen-fac |> ^ GEN %o^ %f $(LIMB_BITS) $(NAIL_BITS) > %o |> fac_table.h +: gen-fib |> ^ GEN %o^ %f header $(LIMB_BITS) $(NAIL_BITS) > %o |> fib_table.h +: gen-fib |> ^ GEN %o^ %f table $(LIMB_BITS) $(NAIL_BITS) > %o |> mpn/fib_table.c +: gen-bases |> ^ GEN %o^ %f header $(LIMB_BITS) $(NAIL_BITS) > %o |> mp_bases.h +: gen-bases |> ^ GEN %o^ %f table $(LIMB_BITS) $(NAIL_BITS) > %o |> mpn/mp_bases.c +: gen-trialdivtab |> ^ GEN %o^ %f $(LIMB_BITS) 8000 > %o |> trialdivtab.h +: gen-jacobitab |> ^ GEN %o^ %f > %o |> jacobitab.h +: gen-psqr |> ^ GEN %o^ %f $(LIMB_BITS) $(NAIL_BITS) > %o |> perfsqr.h + +# --- Phase 4: Compile top-level GMP sources --- + +srcs = assert.c compat.c errno.c extract-dbl.c invalid.c memory.c +srcs += mp_bpl.c mp_clz_tab.c mp_dv_tab.c mp_minv_tab.c +srcs += mp_get_fns.c mp_set_fns.c +srcs += version.c nextprime.c primesieve.c +srcs += tal-reent.c + +: foreach $(srcs) |> !cc |> %B.o + +# --- Phase 5: Archive all GMP objects into libgmp.a --- +# Use shell glob to collect objects from all subdirectories. +# Order-only deps on subdirectory groups ensure correct build order. + +: | mpn/ mpz/ mpq/ mpf/ \ + printf/ scanf/ rand/ |> \ + ^ AR %o^ sh -c '$(AR) rcs %o % $(TUP_VARIANT_OUTPUTDIR)/mpn/*.o $(TUP_VARIANT_OUTPUTDIR)/mpz/*.o $(TUP_VARIANT_OUTPUTDIR)/mpq/*.o $(TUP_VARIANT_OUTPUTDIR)/mpf/*.o $(TUP_VARIANT_OUTPUTDIR)/printf/*.o $(TUP_VARIANT_OUTPUTDIR)/scanf/*.o $(TUP_VARIANT_OUTPUTDIR)/rand/*.o' \ + |> libgmp.a $(S)/ diff --git a/examples/gcc/gmp/Tuprules.tup b/examples/gcc/gmp/Tuprules.tup new file mode 100644 index 0000000..c49acfe --- /dev/null +++ b/examples/gcc/gmp/Tuprules.tup @@ -0,0 +1,32 @@ +# GMP build rules (self-contained with ?= defaults) +# +# Composed mode: parent sets S, B, CC, AR, HOSTCC, GMP_DIR before this runs. +# Standalone mode: ?= defaults take effect. + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= gcc +AR ?= ar +HOSTCC ?= gcc +LIMB_BITS ?= @(LIMB_BITS) +NAIL_BITS ?= @(NAIL_BITS) +GMP_DIR ?= . + +CFLAGS = -O2 -std=gnu11 +CFLAGS += -D__GMP_WITHIN_GMP -DHAVE_CONFIG_H +CFLAGS += -I$(B)/$(GMP_DIR) -I$(S)/$(GMP_DIR) + +!cc = | $(S)/$(GMP_DIR)/ |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> %B.o + +!m4asm = | $(S)/$(GMP_DIR)/ |> ^ M4ASM %b^ \ + m4 -DPIC -DOPERATION_%B \ + -I$(S)/$(GMP_DIR)/mpn \ + -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 \ + $(S)/$(GMP_DIR)/mpn/asm-defs.m4 \ + %f \ + | $(CC) -c -x assembler - -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(GMP_DIR)/tup.config > %o |> diff --git a/examples/gcc/gmp/mpf/Tupfile b/examples/gcc/gmp/mpf/Tupfile new file mode 100644 index 0000000..5936c8e --- /dev/null +++ b/examples/gcc/gmp/mpf/Tupfile @@ -0,0 +1,20 @@ +include_rules + +# MPF - multiprecision floating-point + +srcs = abs.c add.c add_ui.c ceilfloor.c clear.c clears.c +srcs += cmp.c cmp_d.c cmp_si.c cmp_ui.c cmp_z.c +srcs += div.c div_2exp.c div_ui.c dump.c eq.c +srcs += fits_sint.c fits_slong.c fits_sshort.c +srcs += fits_uint.c fits_ulong.c fits_ushort.c +srcs += get_d.c get_d_2exp.c get_dfl_prec.c get_prc.c get_si.c get_str.c get_ui.c +srcs += init.c init2.c inits.c inp_str.c int_p.c +srcs += iset.c iset_d.c iset_si.c iset_str.c iset_ui.c +srcs += mul.c mul_2exp.c mul_ui.c neg.c out_str.c +srcs += pow_ui.c random2.c reldiff.c +srcs += set.c set_d.c set_dfl_prec.c set_prc.c set_prc_raw.c +srcs += set_q.c set_si.c set_str.c set_ui.c set_z.c +srcs += size.c sqrt.c sqrt_ui.c sub.c sub_ui.c swap.c trunc.c +srcs += ui_div.c ui_sub.c urandomb.c + +: foreach $(srcs) |> !cc |> %B.o diff --git a/examples/gcc/gmp/mpn/Tupfile b/examples/gcc/gmp/mpn/Tupfile new file mode 100644 index 0000000..a5f0d83 --- /dev/null +++ b/examples/gcc/gmp/mpn/Tupfile @@ -0,0 +1,232 @@ +include_rules + +# MPN — low-level multiprecision arithmetic +# +# Source selection is config-driven via gmp/mpn/tup.config (generated by +# scripts/resolve-mpn.sh). In generic mode, all sources are C with template +# functions enabled. In assembly mode, .asm files replace selected C sources +# and the foo-y pattern toggles individual template outputs. + +# --- Bang macros --- + +!cc-op = | $(S)/$(GMP_DIR)/ |> ^ CC %b^ $(CC) $(CFLAGS) -DOPERATION_%B -c %f -o %o |> %B.o + +# --- Bulk sources (foreach over config lists) --- + +: foreach @(C_SOURCES) |> !cc-op |> +: foreach @(ASM_SOURCES) |> !m4asm |> %B.o + +# ===================================================================== +# Multi-function assembly (foo-y pattern) +# +# Each .asm is compiled multiple times with different -DOPERATION_ to +# produce separate .o files. The variable name encodes the toggle: +# varname-@(FLAG) = path +# When FLAG=y, $(varname-y) expands to the path. Otherwise it's empty. +# ===================================================================== + +# aors_n.asm → add_n, sub_n +aors_add_n-@(ASM_add_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_n.asm +aors_sub_n-@(ASM_sub_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_n.asm + +: foreach $(aors_add_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM add_n^ \ + m4 -DPIC -DOPERATION_add_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> add_n.o + +: foreach $(aors_sub_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM sub_n^ \ + m4 -DPIC -DOPERATION_sub_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> sub_n.o + +# aorsmul_1.asm → addmul_1, submul_1 +aorsmul_addmul_1-@(ASM_addmul_1) = @(MPN_ARCH)/@(MPN_SUBDIR)/aorsmul_1.asm +aorsmul_submul_1-@(ASM_submul_1) = @(MPN_ARCH)/@(MPN_SUBDIR)/aorsmul_1.asm + +: foreach $(aorsmul_addmul_1-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM addmul_1^ \ + m4 -DPIC -DOPERATION_addmul_1 -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> addmul_1.o + +: foreach $(aorsmul_submul_1-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM submul_1^ \ + m4 -DPIC -DOPERATION_submul_1 -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> submul_1.o + +# aors_err1_n.asm → add_err1_n, sub_err1_n +aors_err1_add-@(ASM_add_err1_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_err1_n.asm +aors_err1_sub-@(ASM_sub_err1_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_err1_n.asm + +: foreach $(aors_err1_add-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM add_err1_n^ \ + m4 -DPIC -DOPERATION_add_err1_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> add_err1_n.o + +: foreach $(aors_err1_sub-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM sub_err1_n^ \ + m4 -DPIC -DOPERATION_sub_err1_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> sub_err1_n.o + +# aors_err2_n.asm → add_err2_n, sub_err2_n +aors_err2_add-@(ASM_add_err2_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_err2_n.asm +aors_err2_sub-@(ASM_sub_err2_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_err2_n.asm + +: foreach $(aors_err2_add-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM add_err2_n^ \ + m4 -DPIC -DOPERATION_add_err2_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> add_err2_n.o + +: foreach $(aors_err2_sub-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM sub_err2_n^ \ + m4 -DPIC -DOPERATION_sub_err2_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> sub_err2_n.o + +# aors_err3_n.asm → add_err3_n, sub_err3_n +aors_err3_add-@(ASM_add_err3_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_err3_n.asm +aors_err3_sub-@(ASM_sub_err3_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/aors_err3_n.asm + +: foreach $(aors_err3_add-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM add_err3_n^ \ + m4 -DPIC -DOPERATION_add_err3_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> add_err3_n.o + +: foreach $(aors_err3_sub-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM sub_err3_n^ \ + m4 -DPIC -DOPERATION_sub_err3_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> sub_err3_n.o + +# logops_n.asm → and_n, andn_n, ior_n, iorn_n, nand_n, nior_n, xnor_n, xor_n +logops_asm_and_n-@(ASM_and_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm +logops_asm_andn_n-@(ASM_andn_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm +logops_asm_ior_n-@(ASM_ior_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm +logops_asm_iorn_n-@(ASM_iorn_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm +logops_asm_nand_n-@(ASM_nand_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm +logops_asm_nior_n-@(ASM_nior_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm +logops_asm_xnor_n-@(ASM_xnor_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm +logops_asm_xor_n-@(ASM_xor_n) = @(MPN_ARCH)/@(MPN_SUBDIR)/logops_n.asm + +: foreach $(logops_asm_and_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM and_n^ \ + m4 -DPIC -DOPERATION_and_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> and_n.o + +: foreach $(logops_asm_andn_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM andn_n^ \ + m4 -DPIC -DOPERATION_andn_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> andn_n.o + +: foreach $(logops_asm_ior_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM ior_n^ \ + m4 -DPIC -DOPERATION_ior_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> ior_n.o + +: foreach $(logops_asm_iorn_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM iorn_n^ \ + m4 -DPIC -DOPERATION_iorn_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> iorn_n.o + +: foreach $(logops_asm_nand_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM nand_n^ \ + m4 -DPIC -DOPERATION_nand_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> nand_n.o + +: foreach $(logops_asm_nior_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM nior_n^ \ + m4 -DPIC -DOPERATION_nior_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> nior_n.o + +: foreach $(logops_asm_xnor_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM xnor_n^ \ + m4 -DPIC -DOPERATION_xnor_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> xnor_n.o + +: foreach $(logops_asm_xor_n-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM xor_n^ \ + m4 -DPIC -DOPERATION_xor_n -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> xor_n.o + +# popham.asm → popcount, hamdist +popham_asm_popcount-@(ASM_popcount) = @(MPN_ARCH)/@(MPN_SUBDIR)/popham.asm +popham_asm_hamdist-@(ASM_hamdist) = @(MPN_ARCH)/@(MPN_SUBDIR)/popham.asm + +: foreach $(popham_asm_popcount-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM popcount^ \ + m4 -DPIC -DOPERATION_popcount -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> popcount.o + +: foreach $(popham_asm_hamdist-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM hamdist^ \ + m4 -DPIC -DOPERATION_hamdist -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> hamdist.o + +# sec_aors_1.asm → sec_add_1, sec_sub_1 +sec_aors_1_asm_add-@(ASM_sec_add_1) = @(MPN_ARCH)/@(MPN_SUBDIR)/sec_aors_1.asm +sec_aors_1_asm_sub-@(ASM_sec_sub_1) = @(MPN_ARCH)/@(MPN_SUBDIR)/sec_aors_1.asm + +: foreach $(sec_aors_1_asm_add-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM sec_add_1^ \ + m4 -DPIC -DOPERATION_sec_add_1 -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> sec_add_1.o + +: foreach $(sec_aors_1_asm_sub-y) | $(S)/$(GMP_DIR)/ |> ^ M4ASM sec_sub_1^ \ + m4 -DPIC -DOPERATION_sec_sub_1 -I$(S)/$(GMP_DIR)/mpn -I$(S)/$(GMP_DIR)/mpn/@(MPN_ARCH) \ + $(B)/$(GMP_DIR)/config.m4 $(S)/$(GMP_DIR)/mpn/asm-defs.m4 %f \ + | $(CC) -c -x assembler - -o %o |> sec_sub_1.o + +# ===================================================================== +# Template C rules (foo-y pattern) +# +# Each template .c is compiled with different -DOPERATION_ values. +# In generic mode all are enabled (CONFIG_C_=y). In assembly +# mode, functions with .asm replacements are disabled (CONFIG_C_=n). +# ===================================================================== + +# logops_n.c → and_n, andn_n, ior_n, iorn_n, nand_n, nior_n, xnor_n, xor_n +logops_and_n-@(C_and_n) = generic/logops_n.c +logops_andn_n-@(C_andn_n) = generic/logops_n.c +logops_ior_n-@(C_ior_n) = generic/logops_n.c +logops_iorn_n-@(C_iorn_n) = generic/logops_n.c +logops_nand_n-@(C_nand_n) = generic/logops_n.c +logops_nior_n-@(C_nior_n) = generic/logops_n.c +logops_xnor_n-@(C_xnor_n) = generic/logops_n.c +logops_xor_n-@(C_xor_n) = generic/logops_n.c + +: foreach $(logops_and_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC and_n^ $(CC) $(CFLAGS) -DOPERATION_and_n -c %f -o %o |> and_n.o +: foreach $(logops_andn_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC andn_n^ $(CC) $(CFLAGS) -DOPERATION_andn_n -c %f -o %o |> andn_n.o +: foreach $(logops_ior_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC ior_n^ $(CC) $(CFLAGS) -DOPERATION_ior_n -c %f -o %o |> ior_n.o +: foreach $(logops_iorn_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC iorn_n^ $(CC) $(CFLAGS) -DOPERATION_iorn_n -c %f -o %o |> iorn_n.o +: foreach $(logops_nand_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC nand_n^ $(CC) $(CFLAGS) -DOPERATION_nand_n -c %f -o %o |> nand_n.o +: foreach $(logops_nior_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC nior_n^ $(CC) $(CFLAGS) -DOPERATION_nior_n -c %f -o %o |> nior_n.o +: foreach $(logops_xnor_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC xnor_n^ $(CC) $(CFLAGS) -DOPERATION_xnor_n -c %f -o %o |> xnor_n.o +: foreach $(logops_xor_n-y) | $(S)/$(GMP_DIR)/ |> ^ CC xor_n^ $(CC) $(CFLAGS) -DOPERATION_xor_n -c %f -o %o |> xor_n.o + +# popham.c → popcount, hamdist +popham_popcount-@(C_popcount) = generic/popham.c +popham_hamdist-@(C_hamdist) = generic/popham.c + +: foreach $(popham_popcount-y) | $(S)/$(GMP_DIR)/ |> ^ CC popcount^ $(CC) $(CFLAGS) -DOPERATION_popcount -c %f -o %o |> popcount.o +: foreach $(popham_hamdist-y) | $(S)/$(GMP_DIR)/ |> ^ CC hamdist^ $(CC) $(CFLAGS) -DOPERATION_hamdist -c %f -o %o |> hamdist.o + +# sec_aors_1.c → sec_add_1, sec_sub_1 +sec_aors_1_add-@(C_sec_add_1) = generic/sec_aors_1.c +sec_aors_1_sub-@(C_sec_sub_1) = generic/sec_aors_1.c + +: foreach $(sec_aors_1_add-y) | $(S)/$(GMP_DIR)/ |> ^ CC sec_add_1^ $(CC) $(CFLAGS) -DOPERATION_sec_add_1 -c %f -o %o |> sec_add_1.o +: foreach $(sec_aors_1_sub-y) | $(S)/$(GMP_DIR)/ |> ^ CC sec_sub_1^ $(CC) $(CFLAGS) -DOPERATION_sec_sub_1 -c %f -o %o |> sec_sub_1.o + +# sec_div.c → sec_div_qr, sec_div_r (always C, no asm variant) +sec_div_qr-@(C_sec_div_qr) = generic/sec_div.c +sec_div_r-@(C_sec_div_r) = generic/sec_div.c + +: foreach $(sec_div_qr-y) | $(S)/$(GMP_DIR)/ |> ^ CC sec_div_qr^ $(CC) $(CFLAGS) -DOPERATION_sec_div_qr -c %f -o %o |> sec_div_qr.o +: foreach $(sec_div_r-y) | $(S)/$(GMP_DIR)/ |> ^ CC sec_div_r^ $(CC) $(CFLAGS) -DOPERATION_sec_div_r -c %f -o %o |> sec_div_r.o + +# sec_pi1_div.c → sec_pi1_div_qr, sec_pi1_div_r (always C, no asm variant) +sec_pi1_div_qr-@(C_sec_pi1_div_qr) = generic/sec_pi1_div.c +sec_pi1_div_r-@(C_sec_pi1_div_r) = generic/sec_pi1_div.c + +: foreach $(sec_pi1_div_qr-y) | $(S)/$(GMP_DIR)/ |> ^ CC sec_pi1_div_qr^ $(CC) $(CFLAGS) -DOPERATION_sec_pi1_div_qr -c %f -o %o |> sec_pi1_div_qr.o +: foreach $(sec_pi1_div_r-y) | $(S)/$(GMP_DIR)/ |> ^ CC sec_pi1_div_r^ $(CC) $(CFLAGS) -DOPERATION_sec_pi1_div_r -c %f -o %o |> sec_pi1_div_r.o + +# --- Generated table sources (produced by gmp/Tupfile generators) --- +: foreach fib_table.c mp_bases.c |> !cc-op |> diff --git a/examples/gcc/gmp/mpn/tup.config b/examples/gcc/gmp/mpn/tup.config new file mode 100644 index 0000000..d8a5628 --- /dev/null +++ b/examples/gcc/gmp/mpn/tup.config @@ -0,0 +1,20 @@ +CONFIG_MPN_ARCH=generic +CONFIG_MPN_SUBDIR=generic +CONFIG_C_SOURCES=generic/add_1.c generic/add.c generic/add_err1_n.c generic/add_err2_n.c generic/add_err3_n.c generic/addmul_1.c generic/add_n.c generic/add_n_sub_n.c generic/bdiv_dbm1c.c generic/bdiv_q_1.c generic/bdiv_q.c generic/bdiv_qr.c generic/binvert.c generic/broot.c generic/brootinv.c generic/bsqrt.c generic/bsqrtinv.c generic/cmp.c generic/cnd_add_n.c generic/cnd_sub_n.c generic/cnd_swap.c generic/comb_tables.c generic/com.c generic/compute_powtab.c generic/copyd.c generic/copyi.c generic/dcpi1_bdiv_q.c generic/dcpi1_bdiv_qr.c generic/dcpi1_divappr_q.c generic/dcpi1_div_q.c generic/dcpi1_div_qr.c generic/dive_1.c generic/diveby3.c generic/divexact.c generic/divis.c generic/div_q.c generic/div_qr_1.c generic/div_qr_1n_pi1.c generic/div_qr_1n_pi2.c generic/div_qr_1u_pi2.c generic/div_qr_2.c generic/div_qr_2n_pi1.c generic/div_qr_2u_pi1.c generic/divrem_1.c generic/divrem_2.c generic/divrem.c generic/dump.c generic/fib2m.c generic/fib2_ui.c generic/gcd_11.c generic/gcd_1.c generic/gcd_22.c generic/gcd.c generic/gcdext_1.c generic/gcdext.c generic/gcdext_lehmer.c generic/gcd_subdiv_step.c generic/get_d.c generic/get_str.c generic/hgcd2.c generic/hgcd2_jacobi.c generic/hgcd_appr.c generic/hgcd.c generic/hgcd_jacobi.c generic/hgcd_matrix.c generic/hgcd_reduce.c generic/hgcd_step.c generic/invertappr.c generic/invert.c generic/jacbase.c generic/jacobi_2.c generic/jacobi.c generic/lshift.c generic/lshiftc.c generic/matrix22_mul1_inverse_vector.c generic/matrix22_mul.c generic/mod_1_1.c generic/mod_1_2.c generic/mod_1_3.c generic/mod_1_4.c generic/mod_1.c generic/mod_34lsub1.c generic/mode1o.c generic/mu_bdiv_q.c generic/mu_bdiv_qr.c generic/mu_divappr_q.c generic/mu_div_q.c generic/mu_div_qr.c generic/mul_1.c generic/mul_basecase.c generic/mul.c generic/mul_fft.c generic/mullo_basecase.c generic/mullo_n.c generic/mulmid_basecase.c generic/mulmid.c generic/mulmid_n.c generic/mulmod_bnm1.c generic/mul_n.c generic/neg.c generic/nussbaumer_mul.c generic/perfpow.c generic/perfsqr.c generic/pow_1.c generic/powlo.c generic/powm.c generic/pre_divrem_1.c generic/pre_mod_1.c generic/random2.c generic/random.c generic/redc_1.c generic/redc_2.c generic/redc_n.c generic/remove.c generic/rootrem.c generic/rshift.c generic/sbpi1_bdiv_q.c generic/sbpi1_bdiv_qr.c generic/sbpi1_bdiv_r.c generic/sbpi1_divappr_q.c generic/sbpi1_div_q.c generic/sbpi1_div_qr.c generic/scan0.c generic/scan1.c generic/sec_invert.c generic/sec_mul.c generic/sec_powm.c generic/sec_sqr.c generic/sec_tabselect.c generic/set_str.c generic/sizeinbase.c generic/sqr_basecase.c generic/sqr.c generic/sqrlo_basecase.c generic/sqrlo.c generic/sqrmod_bnm1.c generic/sqrtrem.c generic/strongfibo.c generic/sub_1.c generic/sub.c generic/sub_err1_n.c generic/sub_err2_n.c generic/sub_err3_n.c generic/submul_1.c generic/sub_n.c generic/tdiv_qr.c generic/toom22_mul.c generic/toom2_sqr.c generic/toom32_mul.c generic/toom33_mul.c generic/toom3_sqr.c generic/toom42_mul.c generic/toom42_mulmid.c generic/toom43_mul.c generic/toom44_mul.c generic/toom4_sqr.c generic/toom52_mul.c generic/toom53_mul.c generic/toom54_mul.c generic/toom62_mul.c generic/toom63_mul.c generic/toom6h_mul.c generic/toom6_sqr.c generic/toom8h_mul.c generic/toom8_sqr.c generic/toom_couple_handling.c generic/toom_eval_dgr3_pm1.c generic/toom_eval_dgr3_pm2.c generic/toom_eval_pm1.c generic/toom_eval_pm2.c generic/toom_eval_pm2exp.c generic/toom_eval_pm2rexp.c generic/toom_interpolate_12pts.c generic/toom_interpolate_16pts.c generic/toom_interpolate_5pts.c generic/toom_interpolate_6pts.c generic/toom_interpolate_7pts.c generic/toom_interpolate_8pts.c generic/trialdiv.c generic/zero.c generic/zero_p.c +CONFIG_ASM_SOURCES= +CONFIG_C_and_n=y +CONFIG_C_andn_n=y +CONFIG_C_ior_n=y +CONFIG_C_iorn_n=y +CONFIG_C_nand_n=y +CONFIG_C_nior_n=y +CONFIG_C_xnor_n=y +CONFIG_C_xor_n=y +CONFIG_C_popcount=y +CONFIG_C_hamdist=y +CONFIG_C_sec_add_1=y +CONFIG_C_sec_sub_1=y +CONFIG_C_sec_div_qr=y +CONFIG_C_sec_div_r=y +CONFIG_C_sec_pi1_div_qr=y +CONFIG_C_sec_pi1_div_r=y diff --git a/examples/gcc/gmp/mpq/Tupfile b/examples/gcc/gmp/mpq/Tupfile new file mode 100644 index 0000000..8fd3c7b --- /dev/null +++ b/examples/gcc/gmp/mpq/Tupfile @@ -0,0 +1,12 @@ +include_rules + +# MPQ - multiprecision rationals + +srcs = abs.c aors.c canonicalize.c clear.c clears.c +srcs += cmp.c cmp_si.c cmp_ui.c div.c equal.c +srcs += get_d.c get_den.c get_num.c get_str.c +srcs += init.c inits.c inp_str.c inv.c md_2exp.c mul.c neg.c out_str.c +srcs += set.c set_d.c set_den.c set_f.c set_num.c +srcs += set_si.c set_str.c set_ui.c set_z.c swap.c + +: foreach $(srcs) |> !cc |> %B.o diff --git a/examples/gcc/gmp/mpz/Tupfile b/examples/gcc/gmp/mpz/Tupfile new file mode 100644 index 0000000..9bf276c --- /dev/null +++ b/examples/gcc/gmp/mpz/Tupfile @@ -0,0 +1,45 @@ +include_rules + +# MPZ - multiprecision integers + +srcs = 2fac_ui.c abs.c add.c add_ui.c aorsmul.c aorsmul_i.c and.c +srcs += array_init.c bin_ui.c bin_uiui.c +srcs += cdiv_q.c cdiv_q_ui.c cdiv_qr.c cdiv_qr_ui.c +srcs += cdiv_r.c cdiv_r_ui.c cdiv_ui.c +srcs += cfdiv_q_2exp.c cfdiv_r_2exp.c +srcs += clear.c clears.c clrbit.c +srcs += cmp.c cmp_d.c cmp_si.c cmp_ui.c cmpabs.c cmpabs_d.c cmpabs_ui.c +srcs += com.c combit.c cong.c cong_2exp.c cong_ui.c +srcs += divexact.c divegcd.c dive_ui.c divis.c divis_ui.c divis_2exp.c +srcs += dump.c export.c +srcs += fac_ui.c fdiv_q.c fdiv_q_ui.c fdiv_qr.c fdiv_qr_ui.c +srcs += fdiv_r.c fdiv_r_ui.c fdiv_ui.c +srcs += fib_ui.c fib2_ui.c +srcs += fits_sint.c fits_slong.c fits_sshort.c +srcs += fits_uint.c fits_ulong.c fits_ushort.c +srcs += gcd.c gcd_ui.c gcdext.c +srcs += get_d.c get_d_2exp.c get_si.c get_str.c get_ui.c getlimbn.c +srcs += hamdist.c import.c +srcs += init.c init2.c inits.c inp_raw.c inp_str.c invert.c +srcs += ior.c iset.c iset_d.c iset_si.c iset_str.c iset_ui.c +srcs += jacobi.c kronsz.c kronuz.c kronzs.c kronzu.c +srcs += lcm.c lcm_ui.c limbs_finish.c limbs_modify.c limbs_read.c limbs_write.c +srcs += lucmod.c lucnum_ui.c lucnum2_ui.c +srcs += mfac_uiui.c millerrabin.c mod.c mul.c mul_2exp.c mul_si.c mul_ui.c +srcs += n_pow_ui.c neg.c nextprime.c +srcs += oddfac_1.c out_raw.c out_str.c +srcs += perfpow.c perfsqr.c popcount.c +srcs += pow_ui.c powm.c powm_sec.c powm_ui.c +srcs += pprime_p.c primorial_ui.c prodlimbs.c +srcs += random.c random2.c realloc.c realloc2.c remove.c roinit_n.c +srcs += root.c rootrem.c rrandomb.c +srcs += scan0.c scan1.c set.c set_d.c set_f.c set_q.c set_si.c set_str.c set_ui.c +srcs += setbit.c size.c sizeinbase.c +srcs += sqrt.c sqrtrem.c stronglucas.c +srcs += sub.c sub_ui.c swap.c +srcs += tdiv_q.c tdiv_q_2exp.c tdiv_q_ui.c +srcs += tdiv_qr.c tdiv_qr_ui.c +srcs += tdiv_r.c tdiv_r_2exp.c tdiv_r_ui.c tdiv_ui.c +srcs += tstbit.c ui_pow_ui.c ui_sub.c urandomb.c urandomm.c xor.c + +: foreach $(srcs) |> !cc |> %B.o diff --git a/examples/gcc/gmp/printf/Tupfile b/examples/gcc/gmp/printf/Tupfile new file mode 100644 index 0000000..ada4013 --- /dev/null +++ b/examples/gcc/gmp/printf/Tupfile @@ -0,0 +1,11 @@ +include_rules + +# GMP printf functions + +srcs = asprintf.c asprntffuns.c doprnt.c doprntf.c doprnti.c fprintf.c +srcs += obprintf.c obprntffuns.c obvprintf.c +srcs += printf.c printffuns.c repl-vsnprintf.c +srcs += snprintf.c snprntffuns.c sprintf.c sprintffuns.c +srcs += vasprintf.c vfprintf.c vprintf.c vsnprintf.c vsprintf.c + +: foreach $(srcs) |> !cc |> %B.o diff --git a/examples/gcc/gmp/rand/Tupfile b/examples/gcc/gmp/rand/Tupfile new file mode 100644 index 0000000..e508739 --- /dev/null +++ b/examples/gcc/gmp/rand/Tupfile @@ -0,0 +1,9 @@ +include_rules + +# GMP random number generation + +srcs = rand.c randbui.c randclr.c randdef.c randiset.c +srcs += randlc2s.c randlc2x.c randmt.c randmts.c randmui.c +srcs += rands.c randsd.c randsdui.c + +: foreach $(srcs) |> !cc |> %B.o diff --git a/examples/gcc/gmp/scanf/Tupfile b/examples/gcc/gmp/scanf/Tupfile new file mode 100644 index 0000000..eb6ec36 --- /dev/null +++ b/examples/gcc/gmp/scanf/Tupfile @@ -0,0 +1,8 @@ +include_rules + +# GMP scanf functions + +srcs = doscan.c fscanf.c fscanffuns.c scanf.c sscanf.c sscanffuns.c +srcs += vfscanf.c vscanf.c vsscanf.c + +: foreach $(srcs) |> !cc |> %B.o diff --git a/examples/gcc/gmp/tup.config b/examples/gcc/gmp/tup.config new file mode 100644 index 0000000..a280c8c --- /dev/null +++ b/examples/gcc/gmp/tup.config @@ -0,0 +1,101 @@ +# GMP 6.2.1 - macOS (aarch64-apple-darwin) config.h defines +# +# Key differences from Linux: no sys_sysinfo, no hidden_alias (macOS linker), +# no obstack_vprintf, host CPU is aarch64 not x86_64. + +# Architecture +CONFIG_LIMB_BITS=64 +CONFIG_NAIL_BITS=0 + +# MPN CPU target +CONFIG_MPN_CPU=generic + +# Feature detection +CONFIG_HAVE_ALARM=1 +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_ATTRIBUTE_CONST=1 +CONFIG_HAVE_ATTRIBUTE_MALLOC=1 +CONFIG_HAVE_ATTRIBUTE_MODE=1 +CONFIG_HAVE_ATTRIBUTE_NORETURN=1 +CONFIG_HAVE_CLOCK=1 +CONFIG_HAVE_CLOCK_GETTIME=1 +CONFIG_HAVE_DECL_FGETC=1 +CONFIG_HAVE_DECL_FSCANF=1 +CONFIG_HAVE_DECL_OPTARG=1 +CONFIG_HAVE_DECL_SYS_ERRLIST=0 +CONFIG_HAVE_DECL_SYS_NERR=0 +CONFIG_HAVE_DECL_UNGETC=1 +CONFIG_HAVE_DECL_VFPRINTF=1 +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_DOUBLE_IEEE_LITTLE_ENDIAN=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_FLOAT_H=1 +CONFIG_HAVE_GETPAGESIZE=1 +CONFIG_HAVE_GETRUSAGE=1 +CONFIG_HAVE_GETTIMEOFDAY=1 +CONFIG_HAVE_INTMAX_T=1 +CONFIG_HAVE_INTPTR_T=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LANGINFO_H=1 +CONFIG_HAVE_LIMB_LITTLE_ENDIAN=1 +CONFIG_HAVE_LOCALECONV=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_LONG_DOUBLE=1 +CONFIG_HAVE_LONG_LONG=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_MEMSET=1 +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_MPROTECT=1 +CONFIG_HAVE_NL_LANGINFO=1 +CONFIG_HAVE_NL_TYPES_H=1 +CONFIG_HAVE_POPEN=1 +CONFIG_HAVE_PTRDIFF_T=1 +CONFIG_HAVE_RAISE=1 +CONFIG_HAVE_SIGACTION=1 +CONFIG_HAVE_SIGALTSTACK=1 +CONFIG_HAVE_SIGNAL_H=1 +CONFIG_HAVE_STACK_T=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRCHR=1 +CONFIG_HAVE_STRERROR=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRNLEN=1 +CONFIG_HAVE_STRTOL=1 +CONFIG_HAVE_STRTOUL=1 +CONFIG_HAVE_SYSCONF=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_RESOURCE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TIMES_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_TIMES=1 +CONFIG_HAVE_UINT_LEAST32_T=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_HAVE_VSNPRINTF=1 +CONFIG_LSYM_PREFIX="_" +CONFIG_RETSIGTYPE=void +CONFIG_SIZEOF_UNSIGNED=4 +CONFIG_SIZEOF_UNSIGNED_SHORT=2 +CONFIG_SIZEOF_VOID_P=8 +CONFIG_TIME_WITH_SYS_TIME=1 +CONFIG_TUNE_SQR_TOOM2_MAX=SQR_TOOM2_MAX_GENERIC +CONFIG_PACKAGE="gmp" +CONFIG_PACKAGE_BUGREPORT="gmp-bugs@gmp.org" +CONFIG_PACKAGE_NAME="GNU MP" +CONFIG_PACKAGE_STRING="GNU MP 6.2.1" +CONFIG_PACKAGE_TARNAME="gmp" +CONFIG_PACKAGE_VERSION="6.2.1" +CONFIG_SIZEOF_MP_LIMB_T=8 +CONFIG_SIZEOF_UNSIGNED_LONG=8 +CONFIG_SIZEOF_UNSIGNED_LONG_LONG=8 +CONFIG_STDC_HEADERS=1 +CONFIG_VERSION="6.2.1" +CONFIG_WANT_FFT=1 +CONFIG_WANT_TMP_ALLOCA=1 +CONFIG_GMP_MPARAM=mpn/generic/gmp-mparam.h +CONFIG_NO_ASM=1 diff --git a/examples/gcc/libbacktrace/Tupfile b/examples/gcc/libbacktrace/Tupfile new file mode 100644 index 0000000..2a4e143 --- /dev/null +++ b/examples/gcc/libbacktrace/Tupfile @@ -0,0 +1,29 @@ +include_rules + +# ============================================================ +# libbacktrace - stack trace support (GCC 15.2.0) +# ============================================================ + +# --- Phase 1: Generate config.h and backtrace-supported.h --- + +: |> !gen-config |> config.h + +: backtrace-supported.h.in |> ^ GEN %o^ sed \ + -e 's/@BACKTRACE_SUPPORTED@/1/g' \ + -e 's/@BACKTRACE_USES_MALLOC@/0/g' \ + -e 's/@BACKTRACE_SUPPORTS_THREADS@/1/g' \ + -e 's/@BACKTRACE_SUPPORTS_DATA@/1/g' \ + %f > %o |> backtrace-supported.h + +# --- Phase 2: Compile sources --- +# Format selection: @(BACKTRACE_FORMAT) = elf (Linux) or macho (macOS) + +srcs = atomic.c dwarf.c fileline.c +srcs += mmapio.c mmap.c posix.c print.c sort.c state.c +srcs += @(BACKTRACE_FORMAT).c backtrace.c simple.c + +: foreach $(srcs) |> !cc |> %B.o + +# --- Phase 3: Archive --- + +: |> ^ AR %o^ $(AR) rcs %o % |> libbacktrace.a $(S)/ diff --git a/examples/gcc/libbacktrace/Tuprules.tup b/examples/gcc/libbacktrace/Tuprules.tup new file mode 100644 index 0000000..3ba259b --- /dev/null +++ b/examples/gcc/libbacktrace/Tuprules.tup @@ -0,0 +1,18 @@ +# libbacktrace build rules (self-contained with ?= defaults) + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= gcc +AR ?= ar +LIBBACKTRACE_DIR ?= . + +CFLAGS = -O2 -std=gnu11 +CFLAGS += -DHAVE_CONFIG_H +CFLAGS += -I$(B)/$(LIBBACKTRACE_DIR) -I$(S)/$(LIBBACKTRACE_DIR) +CFLAGS += -I$(S)/$(LIBBACKTRACE_DIR)/../include + +!cc = | $(S)/$(LIBBACKTRACE_DIR)/ |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(LIBBACKTRACE_DIR)/tup.config > %o |> diff --git a/examples/gcc/libbacktrace/tup.config b/examples/gcc/libbacktrace/tup.config new file mode 100644 index 0000000..9adf7c8 --- /dev/null +++ b/examples/gcc/libbacktrace/tup.config @@ -0,0 +1,47 @@ +# libbacktrace config.h defines +# Object format selected by platform config (elf on Linux, macho on macOS) + +# Object format: elf (Linux default), overridden by platform config +CONFIG_BACKTRACE_FORMAT=elf +CONFIG_BACKTRACE_ELF_SIZE=64 + +# Atomics +CONFIG_HAVE_ATOMIC_FUNCTIONS=1 +CONFIG_HAVE_SYNC_FUNCTIONS=1 + +# Functions +CONFIG_HAVE_CLOCK_GETTIME=1 +CONFIG_HAVE_FCNTL=1 +CONFIG_HAVE_LSTAT=1 +CONFIG_HAVE_READLINK=1 + +# Declarations +CONFIG_HAVE_DECL_GETPAGESIZE=1 +CONFIG_HAVE_DECL_STRNLEN=1 +CONFIG_HAVE_DECL__PGMPTR=0 + +# Headers +CONFIG_HAVE_DLFCN_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Compression (optional, can link -lz) +CONFIG_HAVE_ZLIB=1 + +# Sizes +CONFIG_SIZEOF_CHAR=1 +CONFIG_SIZEOF_SHORT=2 +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_VOID_P=8 + +# Misc +CONFIG_STDC_HEADERS=1 diff --git a/examples/gcc/libcody/Tupfile b/examples/gcc/libcody/Tupfile new file mode 100644 index 0000000..68488f0 --- /dev/null +++ b/examples/gcc/libcody/Tupfile @@ -0,0 +1,21 @@ +include_rules + +# ============================================================ +# libcody - C++ modules protocol library +# ============================================================ + +# --- Phase 1: Generate config.h --- + +: |> !gen-config |> config.h + +# --- Phase 2: Compile sources --- + +srcs = buffer.cc client.cc fatal.cc +srcs += netclient.cc netserver.cc packet.cc +srcs += resolver.cc server.cc + +: foreach $(srcs) |> !cxx |> %B.o + +# --- Phase 3: Archive --- + +: |> ^ AR %o^ $(AR) rcs %o % |> libcody.a $(S)/ diff --git a/examples/gcc/libcody/Tuprules.tup b/examples/gcc/libcody/Tuprules.tup new file mode 100644 index 0000000..a175d26 --- /dev/null +++ b/examples/gcc/libcody/Tuprules.tup @@ -0,0 +1,18 @@ +# libcody build rules (self-contained with ?= defaults) + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CXX ?= g++ +AR ?= ar +LIBCODY_DIR ?= . + +CXXFLAGS = -O2 -std=gnu++14 -fno-exceptions +CXXFLAGS += -include $(B)/$(LIBCODY_DIR)/config.h +CXXFLAGS += -I$(S)/$(LIBCODY_DIR) +CXXFLAGS += -DSRCDIR=\"\" + +!cxx = | $(S)/$(LIBCODY_DIR)/ |> ^ CXX %b^ $(CXX) $(CXXFLAGS) -c %f -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(LIBCODY_DIR)/tup.config > %o |> diff --git a/examples/gcc/libcody/tup.config b/examples/gcc/libcody/tup.config new file mode 100644 index 0000000..b4578e4 --- /dev/null +++ b/examples/gcc/libcody/tup.config @@ -0,0 +1,11 @@ +# libcody - C++ modules protocol library (minimal config) +# +# libcody's config.h.in defines _GNU_SOURCE unconditionally. +# No other significant configure-time detection needed. + +CONFIG_PACKAGE_NAME="libcody" +CONFIG_PACKAGE_VERSION="0.1" +CONFIG_PACKAGE_STRING="libcody 0.1" +CONFIG_PACKAGE_BUGREPORT="" +CONFIG_PACKAGE_TARNAME="libcody" +CONFIG_PACKAGE_URL="" diff --git a/examples/gcc/libcpp/Tupfile b/examples/gcc/libcpp/Tupfile new file mode 100644 index 0000000..6d995c6 --- /dev/null +++ b/examples/gcc/libcpp/Tupfile @@ -0,0 +1,24 @@ +include_rules + +# ============================================================ +# libcpp - C preprocessor library (GCC 15.2.0) +# ============================================================ + +# --- Phase 1: Generate config.h + localedir.h --- + +: |> !gen-config |> config.h + +: |> ^ GEN %o^ echo '#define LOCALEDIR ""' > %o |> localedir.h + +# --- Phase 2: Compile sources --- +# Source list from libcpp/Makefile.in libcpp_a_OBJS. + +srcs = charset.cc directives.cc errors.cc expr.cc files.cc +srcs += identifiers.cc init.cc lex.cc line-map.cc macro.cc +srcs += mkdeps.cc pch.cc symtab.cc traditional.cc + +: foreach $(srcs) |> !cxx |> %B.o + +# --- Phase 3: Archive --- + +: |> ^ AR %o^ $(AR) rcs %o % |> libcpp.a $(S)/ diff --git a/examples/gcc/libcpp/Tuprules.tup b/examples/gcc/libcpp/Tuprules.tup new file mode 100644 index 0000000..d570df7 --- /dev/null +++ b/examples/gcc/libcpp/Tuprules.tup @@ -0,0 +1,19 @@ +# libcpp build rules (self-contained with ?= defaults) + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CXX ?= g++ +AR ?= ar +LIBCPP_DIR ?= . +LIBIBERTY_DIR ?= libiberty + +CXXFLAGS = -O2 -std=gnu++14 -fno-exceptions -fno-rtti +CXXFLAGS += -DHAVE_CONFIG_H +CXXFLAGS += -I$(B)/$(LIBCPP_DIR) -I$(S)/$(LIBCPP_DIR) -I$(S)/$(LIBCPP_DIR)/include +CXXFLAGS += -I$(S)/$(LIBCPP_DIR)/../include + +!cxx = | $(S)/$(LIBCPP_DIR)/ |> ^ CXX %b^ $(CXX) $(CXXFLAGS) -c %f -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(LIBCPP_DIR)/tup.config > %o |> diff --git a/examples/gcc/libcpp/tup.config b/examples/gcc/libcpp/tup.config new file mode 100644 index 0000000..29d9180 --- /dev/null +++ b/examples/gcc/libcpp/tup.config @@ -0,0 +1,66 @@ +# libcpp - x86_64-linux config.h defines + +# Build options +CONFIG_ENABLE_CANONICAL_SYSTEM_HEADERS=1 + +# Headers +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_STDDEF_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Functions (glibc has *_unlocked variants) +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_ICONV=1 +CONFIG_HAVE_LANGINFO_CODESET=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_PUTCHAR_UNLOCKED=1 +CONFIG_HAVE_FPUTS_UNLOCKED=1 +CONFIG_HAVE_FWRITE_UNLOCKED=1 +CONFIG_HAVE_FPUTC_UNLOCKED=1 + +# Declarations +CONFIG_HAVE_DECL_ABORT=1 +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_BASENAME=1 +CONFIG_HAVE_DECL_ERRNO=1 +CONFIG_HAVE_DECL_FPRINTF_UNLOCKED=0 +CONFIG_HAVE_DECL_GETOPT=1 +CONFIG_HAVE_DECL_VASPRINTF=1 + +# Types +CONFIG_HAVE_UINTPTR_T=1 + +# Sizes +CONFIG_SIZEOF_DEV_T=8 +CONFIG_SIZEOF_INO_T=8 +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 + +# Package +CONFIG_PACKAGE="cpplib" +CONFIG_PACKAGE_BUGREPORT="" +CONFIG_PACKAGE_NAME="cpplib" +CONFIG_PACKAGE_STRING="cpplib 0" +CONFIG_PACKAGE_TARNAME="cpplib" +CONFIG_PACKAGE_URL="" +CONFIG_PACKAGE_VERSION="0" + +# iconv (glibc uses char**, ICONV_CONST is empty) +CONFIG_ICONV_CONST= + +# Misc +CONFIG_STDC_HEADERS=1 +CONFIG_STRING_WITH_STRINGS=1 +CONFIG_TIME_WITH_SYS_TIME=1 diff --git a/examples/gcc/libdecnumber/Tupfile b/examples/gcc/libdecnumber/Tupfile new file mode 100644 index 0000000..ff74081 --- /dev/null +++ b/examples/gcc/libdecnumber/Tupfile @@ -0,0 +1,28 @@ +include_rules + +# ============================================================ +# libdecnumber - BID decimal floating-point (GCC 15.2.0) +# ============================================================ + +# --- Phase 1: Generate config.h --- +# dconfig.h includes config.h (when not IN_LIBGCC2). +# x86-64 is little-endian so WORDS_BIGENDIAN is not defined. + +: |> !gen-config |> config.h + +# gstdint.h — configure-generated wrapper around system +: |> ^ GEN %o^ echo '#include ' > %o |> gstdint.h + +# --- Phase 2: Compile sources --- +# BID variant (Binary Integer Decimal) — x86/x86_64 use BID per dfp.m4. + +srcs = decNumber.c decContext.c +srcs += bid/decimal32.c bid/decimal64.c bid/decimal128.c +srcs += bid/bid2dpd_dpd2bid.c bid/host-ieee32.c +srcs += bid/host-ieee64.c bid/host-ieee128.c + +: foreach $(srcs) |> !cc |> %B.o + +# --- Phase 3: Archive --- + +: |> ^ AR %o^ $(AR) rcs %o % |> libdecnumber.a $(S)/ diff --git a/examples/gcc/libdecnumber/Tuprules.tup b/examples/gcc/libdecnumber/Tuprules.tup new file mode 100644 index 0000000..877e17d --- /dev/null +++ b/examples/gcc/libdecnumber/Tuprules.tup @@ -0,0 +1,17 @@ +# libdecnumber build rules (self-contained with ?= defaults) + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= gcc +AR ?= ar +LIBDECNUMBER_DIR ?= . + +CFLAGS = -O2 -std=gnu11 +CFLAGS += -DHAVE_CONFIG_H +CFLAGS += -I$(B)/$(LIBDECNUMBER_DIR) -I$(S)/$(LIBDECNUMBER_DIR) + +!cc = | $(S)/$(LIBDECNUMBER_DIR)/ |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(LIBDECNUMBER_DIR)/tup.config > %o |> diff --git a/examples/gcc/libdecnumber/tup.config b/examples/gcc/libdecnumber/tup.config new file mode 100644 index 0000000..de25363 --- /dev/null +++ b/examples/gcc/libdecnumber/tup.config @@ -0,0 +1,7 @@ +# libdecnumber - macOS (aarch64-apple-darwin) config.h defines +# +# Identical to Linux — libdecnumber only needs endianness and standard headers. + +CONFIG_STDC_HEADERS=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STDLIB_H=1 diff --git a/examples/gcc/libiberty/Tupfile b/examples/gcc/libiberty/Tupfile new file mode 100644 index 0000000..18ae4a3 --- /dev/null +++ b/examples/gcc/libiberty/Tupfile @@ -0,0 +1,41 @@ +include_rules + +# ============================================================ +# libiberty - GCC utility library +# ============================================================ + +# --- Phase 1: Generate config.h --- + +: |> !gen-config |> config.h + +# --- Phase 2: Compile REQUIRED_OFILES --- +# Source list from libiberty/Makefile.in REQUIRED_OFILES. +# @pexecute@ = pex-unix on Linux. + +srcs = regex.c cplus-dem.c cp-demangle.c md5.c sha1.c alloca.c +srcs += argv.c bsearch_r.c +srcs += choose-temp.c concat.c cp-demint.c crc32.c d-demangle.c +srcs += dwarfnames.c dyn-string.c +srcs += fdmatch.c fibheap.c filedescriptor.c filename_cmp.c floatformat.c +srcs += fnmatch.c fopen_unlocked.c +srcs += getopt.c getopt1.c getpwd.c getruntime.c +srcs += hashtab.c hex.c +srcs += lbasename.c ldirname.c lrealpath.c +srcs += make-relative-prefix.c make-temp-file.c +srcs += objalloc.c obstack.c +srcs += partition.c pexecute.c physmem.c pex-common.c pex-one.c pex-unix.c +srcs += vprintf-support.c rust-demangle.c +srcs += safe-ctype.c +srcs += simple-object.c simple-object-coff.c simple-object-elf.c +srcs += simple-object-mach-o.c simple-object-xcoff.c +srcs += sort.c spaces.c splay-tree.c stack-limit.c +srcs += strerror.c strsignal.c strverscmp.c +srcs += timeval-utils.c unlink-if-ordinary.c +srcs += xasprintf.c xatexit.c xexit.c xmalloc.c xmemdup.c xstrdup.c +srcs += xstrerror.c xstrndup.c xvasprintf.c + +: foreach $(srcs) |> !cc |> %B.o + +# --- Phase 3: Archive --- + +: |> ^ AR %o^ $(AR) rcs %o % |> libiberty.a $(S)/ diff --git a/examples/gcc/libiberty/Tuprules.tup b/examples/gcc/libiberty/Tuprules.tup new file mode 100644 index 0000000..fcff533 --- /dev/null +++ b/examples/gcc/libiberty/Tuprules.tup @@ -0,0 +1,21 @@ +# libiberty build rules (self-contained with ?= defaults) +# +# Composed mode: parent sets S, B, CC, AR, HOSTCC, LIBIBERTY_DIR. +# Standalone mode: ?= defaults take effect. + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= gcc +AR ?= ar +HOSTCC ?= gcc +LIBIBERTY_DIR ?= . + +CFLAGS = -O2 -std=gnu11 +CFLAGS += -DHAVE_CONFIG_H +CFLAGS += -I$(B)/$(LIBIBERTY_DIR) -I$(S)/$(LIBIBERTY_DIR)/../include + +!cc = | $(S)/$(LIBIBERTY_DIR)/ |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(LIBIBERTY_DIR)/tup.config > %o |> diff --git a/examples/gcc/libiberty/tup.config b/examples/gcc/libiberty/tup.config new file mode 100644 index 0000000..4fb2d0a --- /dev/null +++ b/examples/gcc/libiberty/tup.config @@ -0,0 +1,132 @@ +# libiberty - macOS (aarch64-apple-darwin) config.h defines +# +# Key differences from Linux: no canonicalize_file_name, no on_exit, +# no pipe2, no sys_prctl_h, no sys_sysinfo_h, no __fsetlocking, +# no stdio_ext.h, no sigsetmask, no strverscmp. + +# Headers +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_FCNTL_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LIMITS_H=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_SPAWN_H=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_SYS_FILE_H=1 +CONFIG_HAVE_SYS_MMAN_H=1 +CONFIG_HAVE_SYS_PARAM_H=1 +CONFIG_HAVE_SYS_RESOURCE_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_SYS_WAIT_H=1 +CONFIG_HAVE_TIME_H=1 +CONFIG_HAVE_UNISTD_H=1 + +# Functions +CONFIG_HAVE_ASPRINTF=1 +CONFIG_HAVE_ATEXIT=1 +CONFIG_HAVE_BASENAME=1 +CONFIG_HAVE_BCMP=1 +CONFIG_HAVE_BCOPY=1 +CONFIG_HAVE_BSEARCH=1 +CONFIG_HAVE_BZERO=1 +CONFIG_HAVE_CALLOC=1 +CONFIG_HAVE_CLOCK=1 +CONFIG_HAVE_FFS=1 +CONFIG_HAVE_FORK=1 +CONFIG_HAVE_GETCWD=1 +CONFIG_HAVE_GETPAGESIZE=1 +CONFIG_HAVE_GETRLIMIT=1 +CONFIG_HAVE_GETRUSAGE=1 +CONFIG_HAVE_GETTIMEOFDAY=1 +CONFIG_HAVE_INDEX=1 +CONFIG_HAVE_INSQUE=1 +CONFIG_HAVE_MEMCHR=1 +CONFIG_HAVE_MEMCMP=1 +CONFIG_HAVE_MEMCPY=1 +CONFIG_HAVE_MEMMEM=1 +CONFIG_HAVE_MEMMOVE=1 +CONFIG_HAVE_MEMSET=1 +CONFIG_HAVE_MKSTEMPS=1 +CONFIG_HAVE_MMAP=1 +CONFIG_HAVE_POSIX_SPAWN=1 +CONFIG_HAVE_POSIX_SPAWNP=1 +CONFIG_HAVE_PSIGNAL=1 +CONFIG_HAVE_PUTENV=1 +CONFIG_HAVE_RANDOM=1 +CONFIG_HAVE_REALPATH=1 +CONFIG_HAVE_RENAME=1 +CONFIG_HAVE_RINDEX=1 +CONFIG_HAVE_SBRK=1 +CONFIG_HAVE_SETENV=1 +CONFIG_HAVE_SETRLIMIT=1 +CONFIG_HAVE_SNPRINTF=1 +CONFIG_HAVE_STPCPY=1 +CONFIG_HAVE_STPNCPY=1 +CONFIG_HAVE_STRCASECMP=1 +CONFIG_HAVE_STRCHR=1 +CONFIG_HAVE_STRDUP=1 +CONFIG_HAVE_STRERROR=1 +CONFIG_HAVE_STRNCASECMP=1 +CONFIG_HAVE_STRNDUP=1 +CONFIG_HAVE_STRNLEN=1 +CONFIG_HAVE_STRRCHR=1 +CONFIG_HAVE_STRSIGNAL=1 +CONFIG_HAVE_STRSTR=1 +CONFIG_HAVE_STRTOD=1 +CONFIG_HAVE_STRTOL=1 +CONFIG_HAVE_STRTOLL=1 +CONFIG_HAVE_STRTOUL=1 +CONFIG_HAVE_STRTOULL=1 +CONFIG_HAVE_SYSCONF=1 +CONFIG_HAVE_TIMES=1 +CONFIG_HAVE_TMPNAM=1 +CONFIG_HAVE_VASPRINTF=1 +CONFIG_HAVE_VFORK=1 +CONFIG_HAVE_VFPRINTF=1 +CONFIG_HAVE_VPRINTF=1 +CONFIG_HAVE_VSPRINTF=1 +CONFIG_HAVE_WAIT3=1 +CONFIG_HAVE_WAIT4=1 +CONFIG_HAVE_WAITPID=1 +CONFIG_HAVE_WORKING_FORK=1 +CONFIG_HAVE_WORKING_VFORK=1 + +# Types +CONFIG_HAVE_INTPTR_T=1 +CONFIG_HAVE_UINTPTR_T=1 +CONFIG_HAVE_LONG_LONG=1 + +# Declarations +CONFIG_HAVE_DECL_ASPRINTF=1 +CONFIG_HAVE_DECL_BASENAME=0 +CONFIG_HAVE_DECL_CALLOC=1 +CONFIG_HAVE_DECL_FFS=1 +CONFIG_HAVE_DECL_GETENV=1 +CONFIG_HAVE_DECL_GETOPT=1 +CONFIG_HAVE_DECL_MALLOC=1 +CONFIG_HAVE_DECL_REALLOC=1 +CONFIG_HAVE_DECL_SBRK=0 +CONFIG_HAVE_DECL_SNPRINTF=1 +CONFIG_HAVE_DECL_STRNLEN=1 +CONFIG_HAVE_DECL_STRTOL=1 +CONFIG_HAVE_DECL_STRTOLL=1 +CONFIG_HAVE_DECL_STRTOUL=1 +CONFIG_HAVE_DECL_STRTOULL=1 +CONFIG_HAVE_DECL_VASPRINTF=1 +CONFIG_HAVE_DECL_VSNPRINTF=1 + +# Sizes +CONFIG_SIZEOF_INT=4 +CONFIG_SIZEOF_LONG=8 +CONFIG_SIZEOF_LONG_LONG=8 +CONFIG_SIZEOF_SIZE_T=8 + +# Misc +CONFIG_STDC_HEADERS=1 +CONFIG_TIME_WITH_SYS_TIME=1 +CONFIG_UNSIGNED_64BIT_TYPE=unsigned long diff --git a/examples/gcc/mpc/Tupfile b/examples/gcc/mpc/Tupfile new file mode 100644 index 0000000..1bc5ab6 --- /dev/null +++ b/examples/gcc/mpc/Tupfile @@ -0,0 +1,5 @@ +include_rules + +# MPC 1.2.1 - generated files + +: |> !gen-config |> config.h diff --git a/examples/gcc/mpc/Tuprules.tup b/examples/gcc/mpc/Tuprules.tup new file mode 100644 index 0000000..6bcb51a --- /dev/null +++ b/examples/gcc/mpc/Tuprules.tup @@ -0,0 +1,20 @@ +# MPC build rules (self-contained with ?= defaults) + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= gcc +AR ?= ar +GMP_DIR ?= ../gmp +MPFR_DIR ?= ../mpfr +MPC_DIR ?= . + +CFLAGS = -O2 -std=gnu11 -DHAVE_CONFIG_H +CFLAGS += -I$(B)/$(MPC_DIR) -I$(S)/$(MPC_DIR)/src +CFLAGS += -I$(B)/$(MPFR_DIR) -I$(B)/$(MPFR_DIR)/src -I$(S)/$(MPFR_DIR)/src +CFLAGS += -I$(B)/$(GMP_DIR) -I$(S)/$(GMP_DIR) + +!cc = | $(S)/$(GMP_DIR)/ $(S)/$(MPFR_DIR)/ $(S)/$(MPC_DIR)/ |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(MPC_DIR)/tup.config > %o |> diff --git a/examples/gcc/mpc/src/Tupfile b/examples/gcc/mpc/src/Tupfile new file mode 100644 index 0000000..b0c5fea --- /dev/null +++ b/examples/gcc/mpc/src/Tupfile @@ -0,0 +1,25 @@ +include_rules + +# MPC 1.2.1 - all library sources + +srcs = abs.c acos.c acosh.c add.c add_fr.c add_si.c add_ui.c arg.c +srcs += asin.c asinh.c atan.c atanh.c +srcs += clear.c cmp.c cmp_abs.c cmp_si_si.c conj.c cos.c cosh.c +srcs += div.c div_2si.c div_2ui.c div_fr.c div_ui.c dot.c +srcs += exp.c fma.c fr_div.c fr_sub.c +srcs += get_prec.c get_prec2.c get_version.c get_x.c +srcs += imag.c init2.c init3.c inp_str.c +srcs += log.c log10.c mem.c +srcs += mul.c mul_2si.c mul_2ui.c mul_fr.c mul_i.c mul_si.c mul_ui.c +srcs += neg.c norm.c out_str.c +srcs += pow.c pow_d.c pow_fr.c pow_ld.c pow_si.c pow_ui.c pow_z.c +srcs += proj.c real.c rootofunity.c +srcs += set.c set_prec.c set_str.c set_x.c set_x_x.c +srcs += sin.c sin_cos.c sinh.c sqr.c sqrt.c strtoc.c +srcs += sub.c sub_fr.c sub_ui.c sum.c swap.c +srcs += tan.c tanh.c uceil_log2.c ui_div.c ui_ui_sub.c urandom.c + +: foreach $(srcs) |> !cc |> + +# Archive +: |> ^ AR %o^ $(AR) rcs %o % |> libmpc.a $(S)/ diff --git a/examples/gcc/mpc/tup.config b/examples/gcc/mpc/tup.config new file mode 100644 index 0000000..d4568ae --- /dev/null +++ b/examples/gcc/mpc/tup.config @@ -0,0 +1,24 @@ +# MPC 1.2.1 - macOS (aarch64-apple-darwin) config.h defines +# +# Identical to Linux — MPC is pure C with no platform-specific features. + +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_LOCALECONV=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_PACKAGE="mpc" +CONFIG_PACKAGE_NAME="mpc" +CONFIG_PACKAGE_STRING="mpc 1.2.1" +CONFIG_PACKAGE_TARNAME="mpc" +CONFIG_PACKAGE_VERSION="1.2.1" +CONFIG_STDC_HEADERS=1 +CONFIG_VERSION="1.2.1" diff --git a/examples/gcc/mpfr/Tupfile b/examples/gcc/mpfr/Tupfile new file mode 100644 index 0000000..60db22c --- /dev/null +++ b/examples/gcc/mpfr/Tupfile @@ -0,0 +1,10 @@ +include_rules + +# MPFR 4.1.0 - generated files + +: |> !gen-config |> config.h + +# mparam.h - architecture-specific tuning (auto-selects via compiler macros) +: src/mparam_h.in |> ^ GEN %o^ cp %f %o |> src/mparam.h + +# get_patches.c is generated in src/Tupfile (same directory as compilation) diff --git a/examples/gcc/mpfr/Tuprules.tup b/examples/gcc/mpfr/Tuprules.tup new file mode 100644 index 0000000..b7d15f4 --- /dev/null +++ b/examples/gcc/mpfr/Tuprules.tup @@ -0,0 +1,18 @@ +# MPFR build rules (self-contained with ?= defaults) + +S ?= $(TUP_CWD) +B ?= $(TUP_VARIANT_OUTPUTDIR)/$(S) +CC ?= gcc +AR ?= ar +GMP_DIR ?= ../gmp +MPFR_DIR ?= . + +CFLAGS = -O2 -std=gnu11 -DHAVE_CONFIG_H +CFLAGS += -I$(B)/$(MPFR_DIR) -I$(B)/$(MPFR_DIR)/src -I$(S)/$(MPFR_DIR)/src +CFLAGS += -I$(B)/$(GMP_DIR) -I$(S)/$(GMP_DIR) + +!cc = | $(S)/$(GMP_DIR)/ $(S)/$(MPFR_DIR)/ |> ^ CC %b^ $(CC) $(CFLAGS) -c %f -o %o |> %B.o + +!gen-config = |> ^ GEN %o^ awk -F= \ + '/^CONFIG_/{k=substr($1,8);v=substr($0,length($1)+2);if(v!="n")print "#define " k " " (v=="y"?1:v)}' \ + $(B)/$(MPFR_DIR)/tup.config > %o |> diff --git a/examples/gcc/mpfr/src/Tupfile b/examples/gcc/mpfr/src/Tupfile new file mode 100644 index 0000000..88b2c2c --- /dev/null +++ b/examples/gcc/mpfr/src/Tupfile @@ -0,0 +1,57 @@ +include_rules + +# MPFR 4.1.0 - all library sources + +srcs = abort_prec_max.c acos.c acosh.c add.c add1.c add1sp.c add_d.c add_ui.c +srcs += agm.c ai.c asin.c asinh.c atan.c atan2.c atanh.c +srcs += bernoulli.c beta.c buildopt.c +srcs += cache.c cbrt.c check.c clear.c clears.c +srcs += cmp.c cmp2.c cmpabs.c cmpabs_ui.c cmp_d.c cmp_ld.c cmp_si.c cmp_ui.c +srcs += comparisons.c constant.c const_catalan.c const_euler.c const_log2.c const_pi.c +srcs += copysign.c cos.c cosh.c cot.c coth.c csc.c csch.c +srcs += d_div.c d_sub.c digamma.c dim.c +srcs += div.c div_2exp.c div_2si.c div_2ui.c div_d.c div_ui.c dot.c dump.c +srcs += eint.c eq.c erandom.c erf.c erfc.c exceptions.c +srcs += exp.c exp10.c exp_2.c exp2.c exp3.c expm1.c extract.c +srcs += factorial.c fits_intmax.c fits_sint.c fits_slong.c fits_sshort.c +srcs += fits_uint.c fits_uintmax.c fits_ulong.c fits_ushort.c +srcs += fma.c fmma.c fms.c fpif.c frac.c free_cache.c frexp.c +srcs += gamma.c gamma_inc.c gammaonethird.c get_d.c get_d128.c get_d64.c +srcs += get_exp.c get_f.c get_float128.c get_flt.c get_ld.c get_q.c +srcs += get_si.c get_sj.c get_str.c get_ui.c get_uj.c get_z.c get_z_exp.c +srcs += gmp_op.c grandom.c hypot.c +srcs += init.c init2.c inits.c inits2.c inp_str.c int_ceil_log2.c +srcs += isinf.c isinteger.c isnan.c isnum.c isqrt.c isregular.c iszero.c +srcs += jn.c li2.c lngamma.c +srcs += log.c log10.c log1p.c log2.c log_ui.c logging.c +srcs += min_prec.c minmax.c modf.c mp_clz_tab.c mpfr-gmp.c mpfr-mini-gmp.c mpn_exp.c +srcs += mul.c mul_2exp.c mul_2si.c mul_2ui.c mul_d.c mulders.c mul_ui.c +srcs += nbits_ulong.c neg.c next.c nrandom.c odd_p.c out_str.c pool.c +srcs += pow.c pow_si.c pow_ui.c pow_z.c powerof2.c +srcs += printf.c print_raw.c print_rnd_mode.c +srcs += random_deviate.c rec_sqrt.c reldiff.c rem1.c rint.c rndna.c root.c +srcs += round_near_x.c round_p.c round_prec.c +srcs += scale2.c sec.c sech.c +srcs += set.c set_d.c set_d128.c set_d64.c set_dfl_prec.c set_exp.c set_f.c +srcs += set_float128.c set_flt.c set_inf.c set_ld.c +srcs += set_nan.c set_prc_raw.c set_prec.c set_q.c set_rnd.c +srcs += set_si.c set_si_2exp.c set_sj.c set_str.c set_str_raw.c +srcs += set_ui.c set_ui_2exp.c set_uj.c set_z.c set_z_exp.c set_zero.c +srcs += setmax.c setmin.c setsign.c sgn.c signbit.c +srcs += si_op.c sin.c sin_cos.c sinh.c sinh_cosh.c sqr.c sqrt.c sqrt_ui.c +srcs += stack_interface.c strtofr.c sub.c sub1.c sub1sp.c sub_d.c sub_ui.c +srcs += subnormal.c sum.c swap.c +srcs += tan.c tanh.c total_order.c ubf.c +srcs += uceil_exp2.c uceil_log2.c ufloor_log2.c +srcs += ui_div.c ui_pow.c ui_pow_ui.c ui_sub.c +srcs += urandom.c urandomb.c vasprintf.c version.c volatile.c +srcs += yn.c zeta.c zeta_ui.c + +# get_patches.c - empty patch list (generated here, not from source tree) +: |> ^ GEN %o^ printf '#include \nconst char * const mpfr_patches[] = { NULL };\n' > %o |> get_patches.c +: get_patches.c |> !cc |> + +: foreach $(srcs) |> !cc |> + +# Archive +: |> ^ AR %o^ $(AR) rcs %o % |> libmpfr.a $(S)/ diff --git a/examples/gcc/mpfr/tup.config b/examples/gcc/mpfr/tup.config new file mode 100644 index 0000000..f92072b --- /dev/null +++ b/examples/gcc/mpfr/tup.config @@ -0,0 +1,31 @@ +# MPFR 4.1.0 - macOS (aarch64-apple-darwin) config.h defines +# +# Nearly identical to Linux. Only endianness representation differs slightly. + +CONFIG_HAVE_ALLOCA=1 +CONFIG_HAVE_ALLOCA_H=1 +CONFIG_HAVE_INTTYPES_H=1 +CONFIG_HAVE_LOCALE_H=1 +CONFIG_HAVE_LOCALECONV=1 +CONFIG_HAVE_LONG_LONG=1 +CONFIG_HAVE_MEMORY_H=1 +CONFIG_HAVE_SETLOCALE=1 +CONFIG_HAVE_STDARG=1 +CONFIG_HAVE_STDINT_H=1 +CONFIG_HAVE_STDLIB_H=1 +CONFIG_HAVE_STRING_H=1 +CONFIG_HAVE_STRINGS_H=1 +CONFIG_HAVE_SYS_STAT_H=1 +CONFIG_HAVE_SYS_TIME_H=1 +CONFIG_HAVE_SYS_TYPES_H=1 +CONFIG_HAVE_UNISTD_H=1 +CONFIG_HAVE_VA_COPY=1 +CONFIG_HAVE_WCHAR_H=1 +CONFIG_HAVE_LITTLE_ENDIAN=1 +CONFIG_PACKAGE="mpfr" +CONFIG_PACKAGE_NAME="MPFR" +CONFIG_PACKAGE_STRING="MPFR 4.1.0" +CONFIG_PACKAGE_TARNAME="mpfr" +CONFIG_PACKAGE_VERSION="4.1.0" +CONFIG_STDC_HEADERS=1 +CONFIG_VERSION="4.1.0" diff --git a/examples/scripts/resolve-mpn.sh b/examples/scripts/resolve-mpn.sh new file mode 100755 index 0000000..ec0d2ed --- /dev/null +++ b/examples/scripts/resolve-mpn.sh @@ -0,0 +1,177 @@ +#!/bin/sh +# resolve-mpn.sh — Resolve GMP mpn sources for a given CPU target +# +# Usage: resolve-mpn.sh +# +# Outputs tup.config entries to stdout for gmp/mpn/tup.config. +# Generic mode emits all C sources with template functions enabled. +# Assembly mode walks the priority chain, emitting per-function y/n +# toggles for the foo-y conditional compilation pattern. + +set -e + +cpu="$1" +mpn_src="$2" + +if [ -z "$cpu" ] || [ -z "$mpn_src" ]; then + echo "Usage: resolve-mpn.sh " >&2 + exit 1 +fi + +# --- Multi-function file → output function mapping --- +# Static across all architectures. Only the directory changes. + +multi_funcs() { + case "$1" in + aors_n) echo "add_n sub_n" ;; + aorsmul_1) echo "addmul_1 submul_1" ;; + aors_err1_n) echo "add_err1_n sub_err1_n" ;; + aors_err2_n) echo "add_err2_n sub_err2_n" ;; + aors_err3_n) echo "add_err3_n sub_err3_n" ;; + logops_n) echo "and_n andn_n ior_n iorn_n nand_n nior_n xnor_n xor_n" ;; + popham) echo "popcount hamdist" ;; + sec_aors_1) echo "sec_add_1 sec_sub_1" ;; + esac +} + +is_multi_asm() { + case "$1" in + aors_n|aorsmul_1|aors_err1_n|aors_err2_n|aors_err3_n) return 0 ;; + logops_n|popham|sec_aors_1) return 0 ;; + *) return 1 ;; + esac +} + +is_template_file() { + case "$1" in + logops_n|popham|sec_aors_1|sec_div|sec_pi1_div) return 0 ;; + *) return 1 ;; + esac +} + +# All template output functions (16 total) +all_template_funcs="and_n andn_n ior_n iorn_n nand_n nior_n xnor_n xor_n +popcount hamdist sec_add_1 sec_sub_1 sec_div_qr sec_div_r sec_pi1_div_qr sec_pi1_div_r" + +# --- Generic mode --- + +is_arch_specific() { + case "$1" in + udiv_w_sdiv) return 0 ;; # requires sdiv_qrnnd (68k/PowerPC only) + *) return 1 ;; + esac +} + +if [ "$cpu" = "generic" ]; then + c_files="" + for f in "$mpn_src"/generic/*.c; do + [ -f "$f" ] || continue + func=$(basename "$f" .c) + is_template_file "$func" && continue + is_arch_specific "$func" && continue + c_files="${c_files:+$c_files }generic/$(basename "$f")" + done + + echo "CONFIG_MPN_ARCH=generic" + echo "CONFIG_MPN_SUBDIR=generic" + echo "CONFIG_C_SOURCES=$c_files" + echo "CONFIG_ASM_SOURCES=" + for func in $all_template_funcs; do + echo "CONFIG_C_$func=y" + done + exit 0 +fi + +# --- Assembly mode --- + +arch="${cpu%%/*}" +if [ "$cpu" = "$arch" ]; then + cpu_subdir="" +else + cpu_subdir="${cpu#*/}" +fi + +# Walk priority chain: cpu-specific dir → arch dir. +# Higher priority wins; once a function is resolved, lower levels skip it. +asm_funcs="" # all functions with asm (for C exclusion) +single_asm_files="" # single-function .asm paths (for ASM_SOURCES) +multi_asm_funcs="" # functions from multi-function .asm (for CONFIG_ASM_ entries) + +collect_asm() { + dir="$1" + full="$mpn_src/$dir" + [ -d "$full" ] || return 0 + for f in "$full"/*.asm; do + [ -f "$f" ] || continue + base=$(basename "$f" .asm) + + if is_multi_asm "$base"; then + funcs=$(multi_funcs "$base") + any_new=false + for func in $funcs; do + case " $asm_funcs " in + *" $func "*) ;; + *) any_new=true; break ;; + esac + done + $any_new || continue + + for func in $funcs; do + case " $asm_funcs " in + *" $func "*) ;; + *) asm_funcs="$asm_funcs $func" + multi_asm_funcs="$multi_asm_funcs $func" ;; + esac + done + else + case " $asm_funcs " in + *" $base "*) continue ;; + esac + asm_funcs="$asm_funcs $base" + single_asm_files="${single_asm_files:+$single_asm_files }$dir/$(basename "$f")" + fi + done +} + +if [ -n "$cpu_subdir" ]; then + collect_asm "$arch/$cpu_subdir" +fi +collect_asm "$arch" + +# Collect generic C sources, excluding: +# - Functions replaced by asm (single or multi-function) +# - Template source files (handled by foo-y rules) +c_files="" +for f in "$mpn_src"/generic/*.c; do + [ -f "$f" ] || continue + func=$(basename "$f" .c) + is_template_file "$func" && continue + skip=false + for af in $asm_funcs; do + if [ "$func" = "$af" ]; then + skip=true + break + fi + done + $skip || c_files="${c_files:+$c_files }generic/$(basename "$f")" +done + +# --- Output tup.config entries --- + +echo "CONFIG_MPN_ARCH=$arch" +echo "CONFIG_MPN_SUBDIR=$cpu_subdir" +echo "CONFIG_C_SOURCES=$c_files" +echo "CONFIG_ASM_SOURCES=$single_asm_files" + +# Per-function asm toggles (multi-function asm outputs only) +for func in $multi_asm_funcs; do + echo "CONFIG_ASM_$func=y" +done + +# Template C toggles: y when no asm, n when asm replaces it +for func in $all_template_funcs; do + case " $asm_funcs " in + *" $func "*) echo "CONFIG_C_$func=n" ;; + *) echo "CONFIG_C_$func=y" ;; + esac +done diff --git a/include/pup/cli/context.hpp b/include/pup/cli/context.hpp index 051c5eb..73fbf21 100644 --- a/include/pup/cli/context.hpp +++ b/include/pup/cli/context.hpp @@ -53,6 +53,7 @@ struct BuildContextOptions { bool auto_init = false; bool root_config_only = false; bool require_config = false; + std::vector parse_scopes = {}; graph::DepScannerRegistry* scanner_registry = nullptr; graph::RulePatternRegistry* pattern_registry = nullptr; VarAssignedCallback on_var_assigned = {}; diff --git a/include/pup/graph/dag.hpp b/include/pup/graph/dag.hpp index fe6a833..5d58d4b 100644 --- a/include/pup/graph/dag.hpp +++ b/include/pup/graph/dag.hpp @@ -10,6 +10,7 @@ #include "pup/graph/rule_pattern.hpp" #include +#include #include #include #include @@ -386,6 +387,17 @@ auto get_name(Graph const& graph, NodeId id) -> std::string_view; [[nodiscard]] auto expand_instruction(Graph const& graph, NodeId cmd_id, PathCache& cache) -> std::string; +/// Expand instruction with canonical path resolution for symlinked source trees. +/// When source_root is provided, build-tree paths are computed relative to the +/// canonical (physical) CWD instead of the logical CWD. +[[nodiscard]] +auto expand_instruction( + Graph const& graph, + NodeId cmd_id, + PathCache& cache, + std::filesystem::path const& source_root +) -> std::string; + /// Expand instruction pattern (convenience overload, creates temporary cache) [[nodiscard]] auto expand_instruction(Graph const& graph, NodeId cmd_id) -> std::string; diff --git a/src/cli/cmd_build.cpp b/src/cli/cmd_build.cpp index 8abce74..171f2f4 100644 --- a/src/cli/cmd_build.cpp +++ b/src/cli/cmd_build.cpp @@ -936,12 +936,25 @@ auto build_single_variant( vprint(variant_name, "Implicit dependency tracking enabled\n"); } + auto layout = discover_layout(make_layout_options(opts)); + if (!layout) { + veprint(variant_name, "Error: %s\n", layout.error().message.c_str()); + return EXIT_FAILURE; + } + auto scopes = compute_build_scopes(opts, *layout); + + // Only scope parsing when explicit targets are given. + // CWD-derived scoping should still parse all Tupfiles so that + // out-of-scope Tupfile changes are detected for incremental builds. + auto parse_scopes = opts.targets.empty() ? std::vector {} : scopes; + auto ctx_opts = BuildContextOptions { .verbose = opts.verbose, .keep_going = opts.keep_going, .auto_init = true, .root_config_only = false, .require_config = true, + .parse_scopes = parse_scopes, .scanner_registry = scanner_ptr, }; @@ -985,7 +998,6 @@ auto build_single_variant( auto cmd_index_elapsed = std::chrono::high_resolution_clock::now() - cmd_index_start; pup::thread_metrics().command_index_time = std::chrono::duration_cast(cmd_index_elapsed); - auto scopes = compute_build_scopes(opts, ctx.layout()); auto upstream_files = std::set {}; if (opts.include_all_deps && !scopes.empty()) { upstream_files = collect_upstream_files(ctx.graph(), scopes); diff --git a/src/cli/cmd_configure.cpp b/src/cli/cmd_configure.cpp index 6395589..c2abac7 100644 --- a/src/cli/cmd_configure.cpp +++ b/src/cli/cmd_configure.cpp @@ -47,10 +47,10 @@ auto install_source_configs( ProjectLayout const& layout, std::string_view variant_name, bool verbose -) -> int +) -> void { if (layout.config_root == layout.output_root) { - return 0; + return; } auto config_canonical = std::filesystem::weakly_canonical(layout.config_root); @@ -60,8 +60,9 @@ auto install_source_configs( for (auto it = std::filesystem::recursive_directory_iterator(config_canonical, ec); it != std::filesystem::recursive_directory_iterator(); - ++it) { + it.increment(ec)) { if (ec) { + fprintf(stderr, "[%.*s] Warning: error scanning configs: %s\n", static_cast(variant_name.size()), variant_name.data(), ec.message().c_str()); break; } @@ -91,7 +92,6 @@ auto install_source_configs( if (count > 0) { printf("[%.*s] Installed %d source config(s)\n", static_cast(variant_name.size()), variant_name.data(), count); } - return count; } auto configure_single_variant( @@ -118,11 +118,13 @@ auto configure_single_variant( install_source_configs(*layout, variant_name, opts.verbose); // Step 3: Run config-generating rules + auto scopes = compute_build_scopes(opts, *layout); auto ctx_opts = BuildContextOptions { .verbose = opts.verbose, .keep_going = opts.keep_going, .auto_init = false, // Configure pass should not create .pup .root_config_only = true, // Configure uses only root tup.config + .parse_scopes = scopes, .scanner_registry = nullptr, }; @@ -153,7 +155,6 @@ auto configure_single_variant( } // Filter config commands by scope if specified - auto scopes = compute_build_scopes(opts, ctx.layout()); auto config_commands = std::set {}; for (auto const& cfg : configs) { auto const* node = ctx.graph().get_command_node(cfg.cmd_id); diff --git a/src/cli/cmd_parse.cpp b/src/cli/cmd_parse.cpp index 084630e..183b5c0 100644 --- a/src/cli/cmd_parse.cpp +++ b/src/cli/cmd_parse.cpp @@ -17,8 +17,15 @@ namespace { auto parse_single_variant(Options const& opts, std::string_view variant_name) -> int { + auto layout = discover_layout(make_layout_options(opts)); + if (!layout) { + fprintf(stderr, "[%.*s] Error: %s\n", static_cast(variant_name.size()), variant_name.data(), layout.error().message.c_str()); + return EXIT_FAILURE; + } + auto ctx_opts = BuildContextOptions { .verbose = opts.verbose, + .parse_scopes = compute_build_scopes(opts, *layout), }; auto result = pup::Result { build_context(opts, ctx_opts) }; @@ -44,10 +51,11 @@ auto parse_single_variant(Options const& opts, std::string_view variant_name) -> if (opts.verbose && !commands.empty()) { printf("[%.*s] Commands:\n", static_cast(variant_name.size()), variant_name.data()); + auto cache = pup::graph::PathCache {}; for (auto id : commands) { if (ctx.graph().get_command_node(id)) { auto display_sv = pup::graph::get_display_str(ctx.graph().graph(), id); - auto cmd_sv = pup::graph::expand_instruction(ctx.graph().graph(), id); + auto cmd_sv = pup::graph::expand_instruction(ctx.graph().graph(), id, cache, ctx.layout().source_root); auto label = display_sv.empty() ? cmd_sv : display_sv; printf("[%.*s] %.*s\n", static_cast(variant_name.size()), variant_name.data(), static_cast(label.size()), label.data()); } diff --git a/src/cli/context.cpp b/src/cli/context.cpp index 6c915fe..79ec85c 100644 --- a/src/cli/context.cpp +++ b/src/cli/context.cpp @@ -118,7 +118,11 @@ auto compute_tup_variantdir( if (!output_root.empty() && source_root != output_root) { auto output_dir = output_root / source_dir; auto src_dir = source_root / source_dir; - auto rel = std::filesystem::relative(output_dir, src_dir); + // Canonicalize to resolve symlinks — commands run from physical paths, + // so the relative path must work from the physical location. + auto src_canonical = std::filesystem::weakly_canonical(src_dir); + auto out_canonical = std::filesystem::weakly_canonical(output_dir); + auto rel = std::filesystem::relative(out_canonical, src_canonical); return rel.generic_string(); } @@ -378,8 +382,8 @@ auto parse_directory(std::filesystem::path const& rel_dir, ParseContext& ctx) -> // For variant builds: e.g., "../../build/coreutils" from source/coreutils/ auto tup_outdir = std::string { "." }; if (ctx.source_root != ctx.output_root) { - auto source_dir = join_path(ctx.source_root, rel_dir_normalized); - auto output_dir = join_path(ctx.output_root, rel_dir_normalized); + auto source_dir = std::filesystem::weakly_canonical(join_path(ctx.source_root, rel_dir_normalized)); + auto output_dir = std::filesystem::weakly_canonical(join_path(ctx.output_root, rel_dir_normalized)); tup_outdir = std::filesystem::relative(output_dir, source_dir).generic_string(); } @@ -686,6 +690,7 @@ auto build_context( .output_root = ctx.impl_->layout.output_root, .config_path = config_path, .expand_globs = true, + .verbose = ctx_opts.verbose, .scanner_registry = ctx_opts.scanner_registry, .pattern_registry = ctx_opts.pattern_registry, .cached_env_vars = std::move(cached_env_vars), @@ -709,6 +714,10 @@ auto build_context( if (ctx.impl_->state.parsed.contains(dir)) { continue; } + if (!ctx_opts.parse_scopes.empty() + && !pup::is_path_in_any_scope(dir.generic_string(), ctx_opts.parse_scopes)) { + continue; + } auto result = Result { parse_directory(dir, parse_ctx) }; if (!result && !ctx_opts.keep_going) { return unexpected(result.error()); diff --git a/src/core/path_utils.cpp b/src/core/path_utils.cpp index 7d79f81..0659574 100644 --- a/src/core/path_utils.cpp +++ b/src/core/path_utils.cpp @@ -70,6 +70,15 @@ auto is_path_in_scope( return true; } + // Strip trailing separators from scope + while (!scope.empty() && (scope.back() == '/' || scope.back() == '\\')) { + scope.remove_suffix(1); + } + + if (scope.empty()) { + return true; + } + if (!path.starts_with(scope)) { return false; } diff --git a/src/exec/scheduler.cpp b/src/exec/scheduler.cpp index 9a7ab0e..bca3163 100644 --- a/src/exec/scheduler.cpp +++ b/src/exec/scheduler.cpp @@ -787,6 +787,7 @@ auto Scheduler::build_job_list( } auto jobs = std::vector {}; + auto cache = graph::PathCache {}; for (auto id : topo_result.order) { if (!node_id::is_command(id)) { @@ -820,7 +821,7 @@ auto Scheduler::build_job_list( } // Expand command from instruction pattern + operands - auto cmd_str = expand_instruction(graph.graph(), id); + auto cmd_str = expand_instruction(graph.graph(), id, cache, impl_->options.source_root); auto display_str = std::string { get_display_str(graph.graph(), id) }; // Convert exported_vars from StringIds to strings diff --git a/src/graph/builder.cpp b/src/graph/builder.cpp index e1b944d..9895645 100644 --- a/src/graph/builder.cpp +++ b/src/graph/builder.cpp @@ -59,15 +59,18 @@ auto normalize_group_dir( ) -> std::string { auto cleaned = strip_trailing_slashes(path_str); - auto path = fs::path { cleaned }.lexically_normal(); + auto raw_path = fs::path { cleaned }; + auto path = raw_path.lexically_normal(); if (path.is_absolute()) { path = fs::relative(path, source_root); } else if (!current_dir.empty() && !path.empty()) { - // Only combine with current_dir if path needs parent resolution (starts with ..) - // Paths like $(ROOT)/foo expand to root-relative and should NOT be combined - auto first = *path.begin(); - if (first == "..") { + // Check the pre-normalization first component to distinguish: + // "./" prefix (e.g. $(S)/foo/) → root-relative, do NOT combine + // "../" prefix → parent traversal, combine with current_dir + // bare name (e.g. mpn/) → subdirectory reference, combine with current_dir + auto first = *raw_path.begin(); + if (first != ".") { path = (current_dir / path).lexically_normal(); } } @@ -155,18 +158,35 @@ struct PathTransformContext { std::string current_dir_str; fs::path source_root; fs::path output_root; + fs::path canonical_cwd; // Canonical source CWD for symlink-safe path resolution }; auto make_transform_context(BuilderContext const& ctx) -> PathTransformContext { + auto canonical_cwd = fs::path {}; + if (!ctx.options.source_root.empty() && !ctx.options.output_root.empty() + && ctx.options.source_root != ctx.options.output_root) { + canonical_cwd = fs::weakly_canonical(ctx.options.source_root / ctx.current_dir); + } + return PathTransformContext { .source_to_root = pup::compute_source_to_root(ctx.current_dir.generic_string()), .current_dir_str = ctx.current_dir.generic_string(), .source_root = ctx.options.source_root, .output_root = ctx.options.output_root, + .canonical_cwd = std::move(canonical_cwd), }; } +/// Compute a canonical relative path from the source CWD to a build-tree file. +/// Resolves symlinks in the source tree so that `../` components in command paths +/// navigate correctly from the physical CWD (which the OS uses after resolving symlinks). +auto make_canonical_relative(PathTransformContext const& tc, std::string const& path) -> std::string +{ + auto abs = fs::weakly_canonical(tc.source_root / path); + return abs.lexically_relative(tc.canonical_cwd).generic_string(); +} + /// Transform an input path to Tupfile-relative for command expansion. /// Input paths are source-relative. For Generated/Ghost files under BUILD_ROOT_ID, /// we need to use get_full_path() to get the path including the build root prefix. @@ -181,6 +201,9 @@ auto transform_input_path( if (auto node_id = graph.find_by_path(inp, BUILD_ROOT_ID)) { auto full_path = graph.get_full_path(*node_id); if (!full_path.empty()) { + if (!tc.canonical_cwd.empty() && full_path.starts_with("..")) { + return make_canonical_relative(tc, full_path); + } return pup::make_source_relative(full_path, tc.source_to_root, tc.current_dir_str); } } @@ -192,6 +215,9 @@ auto transform_input_path( auto build_path = tc.output_root / inp; if (fs::exists(build_path)) { auto full_path = build_root_name + "/" + inp; + if (!tc.canonical_cwd.empty() && full_path.starts_with("..")) { + return make_canonical_relative(tc, full_path); + } return pup::make_source_relative(full_path, tc.source_to_root, tc.current_dir_str); } } @@ -208,8 +234,9 @@ auto transform_output_path( std::string const& out ) -> std::string { - // Outputs are already variant-mapped (stored under BUILD_ROOT_ID by expand_outputs). - // Just make the path relative to the Tupfile directory. + if (!tc.canonical_cwd.empty() && out.starts_with("..")) { + return make_canonical_relative(tc, out); + } return pup::make_source_relative(out, tc.source_to_root, tc.current_dir_str); } @@ -2467,11 +2494,17 @@ auto resolve_deferred_order_only_edges( } auto source_dir_str = std::string { graph.str(cmd_node->source_dir) }; + auto canonical_cwd = fs::path {}; + if (!state.options.source_root.empty() && !state.options.output_root.empty() + && state.options.source_root != state.options.output_root) { + canonical_cwd = fs::weakly_canonical(state.options.source_root / source_dir_str); + } auto tc = PathTransformContext { .source_to_root = pup::compute_source_to_root(source_dir_str), .current_dir_str = source_dir_str, .source_root = state.options.source_root, .output_root = state.options.output_root, + .canonical_cwd = std::move(canonical_cwd), }; auto replacement = std::string {}; diff --git a/src/graph/dag.cpp b/src/graph/dag.cpp index ac23cfa..5be39f9 100644 --- a/src/graph/dag.cpp +++ b/src/graph/dag.cpp @@ -690,7 +690,14 @@ auto path_extension(std::string_view name) -> std::string_view } // namespace -auto expand_instruction(Graph const& graph, NodeId cmd_id, PathCache& cache) -> std::string +/// Core expansion logic parameterized on the path resolver. +template +auto expand_instruction_impl( + Graph const& graph, + NodeId cmd_id, + PathCache& cache, + PathResolver const& get_operand_path +) -> std::string { auto const* cmd = get_command_node(graph, cmd_id); if (!cmd) { @@ -703,12 +710,6 @@ auto expand_instruction(Graph const& graph, NodeId cmd_id, PathCache& cache) -> } auto source_dir = graph.strings.get(cmd->source_dir); - auto source_to_root = pup::compute_source_to_root(source_dir); - - auto get_operand_path = [&](NodeId id) -> std::string { - auto full = get_full_path(graph, id, cache); - return pup::make_source_relative(full, source_to_root, source_dir); - }; auto get_operand_name = [&](NodeId id) -> std::string_view { return get_name(graph, id); @@ -834,6 +835,48 @@ auto expand_instruction(Graph const& graph, NodeId cmd_id, PathCache& cache) -> return result; } +auto expand_instruction(Graph const& graph, NodeId cmd_id, PathCache& cache) -> std::string +{ + auto const* cmd = get_command_node(graph, cmd_id); + if (!cmd) { + return {}; + } + auto source_dir = graph.strings.get(cmd->source_dir); + auto source_to_root = pup::compute_source_to_root(source_dir); + + return expand_instruction_impl(graph, cmd_id, cache, [&](NodeId id) -> std::string { + auto full = get_full_path(graph, id, cache); + return pup::make_source_relative(full, source_to_root, source_dir); + }); +} + +auto expand_instruction( + Graph const& graph, + NodeId cmd_id, + PathCache& cache, + std::filesystem::path const& source_root +) -> std::string +{ + auto const* cmd = get_command_node(graph, cmd_id); + if (!cmd) { + return {}; + } + auto source_dir = graph.strings.get(cmd->source_dir); + auto source_to_root = pup::compute_source_to_root(source_dir); + auto canonical_cwd = source_root.empty() + ? std::filesystem::path {} + : std::filesystem::weakly_canonical(source_root / std::string { source_dir }); + + return expand_instruction_impl(graph, cmd_id, cache, [&](NodeId id) -> std::string { + auto full = get_full_path(graph, id, cache); + if (!canonical_cwd.empty() && full.starts_with("..")) { + auto abs = std::filesystem::weakly_canonical(source_root / full); + return abs.lexically_relative(canonical_cwd).generic_string(); + } + return pup::make_source_relative(full, source_to_root, source_dir); + }); +} + auto expand_instruction(Graph const& graph, NodeId cmd_id) -> std::string { auto cache = PathCache {}; diff --git a/src/graph/scanners/gcc.cpp b/src/graph/scanners/gcc.cpp index 17ef59d..b10b14d 100644 --- a/src/graph/scanners/gcc.cpp +++ b/src/graph/scanners/gcc.cpp @@ -155,9 +155,11 @@ auto is_source_file(std::string const& word) -> bool } /// Regex to match GCC/Clang compile commands +/// Requires compiler name followed by whitespace (not /) to avoid matching +/// directory names like "build-gcc/gcc/genpreds" auto gcc_pattern() -> std::regex const& { - static auto const pattern = std::regex { R"((gcc|g\+\+|clang|clang\+\+|cc|c\+\+).*\s-c\s)" }; + static auto const pattern = std::regex { R"((?:^|/|\s)(gcc|g\+\+|clang|clang\+\+|cc|c\+\+)\s(?:.*\s)?-c(?:\s|$))" }; return pattern; } diff --git a/src/parser/eval.cpp b/src/parser/eval.cpp index 74eabdd..6ec11b1 100644 --- a/src/parser/eval.cpp +++ b/src/parser/eval.cpp @@ -274,6 +274,13 @@ auto expand(EvalContext& ctx, std::string_view text) -> Result // Add text before the variable result += text.substr(pos, next - pos); + // Handle $$ escape → literal $ for shell commands + if (text[next] == '$' && next + 1 < text.size() && text[next + 1] == '$') { + result += '$'; + pos = next + 2; + continue; + } + // Check for variable reference pattern: X(name) if (next + 1 < text.size() && text[next + 1] == '(') { auto close = text.find(')', next + 2); diff --git a/test/e2e/fixtures/dollar_escape/Tupfile b/test/e2e/fixtures/dollar_escape/Tupfile new file mode 100644 index 0000000..1a94a84 --- /dev/null +++ b/test/e2e/fixtures/dollar_escape/Tupfile @@ -0,0 +1 @@ +: |> VAR=hello; echo $$VAR > %o |> output.txt diff --git a/examples/helloworld/Tupfile.ini b/test/e2e/fixtures/groups_cross_dir_3tree/config/Tupfile.ini similarity index 100% rename from examples/helloworld/Tupfile.ini rename to test/e2e/fixtures/groups_cross_dir_3tree/config/Tupfile.ini diff --git a/test/e2e/fixtures/groups_cross_dir_3tree/config/Tuprules.tup b/test/e2e/fixtures/groups_cross_dir_3tree/config/Tuprules.tup new file mode 100644 index 0000000..925a536 --- /dev/null +++ b/test/e2e/fixtures/groups_cross_dir_3tree/config/Tuprules.tup @@ -0,0 +1,2 @@ +S = $(TUP_CWD) +LIB_DIR = gcc diff --git a/test/e2e/fixtures/groups_cross_dir_3tree/config/gcc/Tupfile b/test/e2e/fixtures/groups_cross_dir_3tree/config/gcc/Tupfile new file mode 100644 index 0000000..4bab9d0 --- /dev/null +++ b/test/e2e/fixtures/groups_cross_dir_3tree/config/gcc/Tupfile @@ -0,0 +1,5 @@ +include_rules + +: |> ^ GEN config.h^ echo '#define HAVE_CONFIG 1' > %o |> config.h +: foreach *.c |> !cc |> +: *.o |> ^ LINK %o^ cc %f -o %o |> hello.out diff --git a/test/e2e/fixtures/groups_cross_dir_3tree/config/gcc/Tuprules.tup b/test/e2e/fixtures/groups_cross_dir_3tree/config/gcc/Tuprules.tup new file mode 100644 index 0000000..d843141 --- /dev/null +++ b/test/e2e/fixtures/groups_cross_dir_3tree/config/gcc/Tuprules.tup @@ -0,0 +1,5 @@ +S ?= .. +LIB_DIR ?= . +include_rules + +!cc = | $(S)/$(LIB_DIR)/ |> ^ CC %o^ cc -c %f -o %o |> %B.o diff --git a/test/e2e/fixtures/groups_cross_dir_3tree/source/gcc/hello.c b/test/e2e/fixtures/groups_cross_dir_3tree/source/gcc/hello.c new file mode 100644 index 0000000..3665a6d --- /dev/null +++ b/test/e2e/fixtures/groups_cross_dir_3tree/source/gcc/hello.c @@ -0,0 +1 @@ +int hello(void) { return 42; } diff --git a/test/e2e/fixtures/groups_cross_dir_3tree/source/gcc/main.c b/test/e2e/fixtures/groups_cross_dir_3tree/source/gcc/main.c new file mode 100644 index 0000000..58fe692 --- /dev/null +++ b/test/e2e/fixtures/groups_cross_dir_3tree/source/gcc/main.c @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff --git a/test/e2e/fixtures/groups_in_inputs/modules/Tupfile.fixture b/test/e2e/fixtures/groups_in_inputs/modules/Tupfile.fixture index 9fc651d..297eb84 100644 --- a/test/e2e/fixtures/groups_in_inputs/modules/Tupfile.fixture +++ b/test/e2e/fixtures/groups_in_inputs/modules/Tupfile.fixture @@ -1,4 +1,4 @@ include_rules -# Use source-root-relative path for cross-directory group -: |> echo "mod1" > %o |> mod1.header modules/ -: |> echo "mod2" > %o |> mod2.header modules/ +# Group lives in this directory (modules/) +: |> echo "mod1" > %o |> mod1.header +: |> echo "mod2" > %o |> mod2.header diff --git a/test/e2e/fixtures/groups_in_inputs/output/Tupfile.fixture b/test/e2e/fixtures/groups_in_inputs/output/Tupfile.fixture index 77afafe..11ea378 100644 --- a/test/e2e/fixtures/groups_in_inputs/output/Tupfile.fixture +++ b/test/e2e/fixtures/groups_in_inputs/output/Tupfile.fixture @@ -1,4 +1,4 @@ include_rules # Group reference in REGULAR inputs (before |), not order-only section # This tests that path/ syntax works in inputs and % expands in command -: modules/ |> cat % > %o |> headers.txt +: ../modules/ |> cat % > %o |> headers.txt diff --git a/test/unit/test_e2e.cpp b/test/unit/test_e2e.cpp index b5bf814..6438d4d 100644 --- a/test/unit/test_e2e.cpp +++ b/test/unit/test_e2e.cpp @@ -510,6 +510,26 @@ SCENARIO("Build fails when command fails", "[e2e][build]") } } +SCENARIO("Dollar-dollar escapes to literal dollar in shell commands", "[e2e][build]") +{ + GIVEN("a project with $$ in a command") + { + auto f = E2EFixture { "dollar_escape" }; + REQUIRE(f.init().success()); + + WHEN("the project is built") + { + auto result = f.build(); + + THEN("build succeeds and $$ becomes $ for the shell") + { + REQUIRE(result.success()); + REQUIRE(f.read_file("output.txt") == "hello\n"); + } + } + } +} + // ============================================================================= // Incremental Build Tests // ============================================================================= @@ -4180,6 +4200,71 @@ SCENARIO("Out-of-tree configuration with separate source/config/build trees", "[ } } +SCENARIO("Cross-directory groups in 3-tree builds", "[e2e][out-of-tree-config][groups]") +{ + GIVEN("a 3-tree project with cross-directory group references via variables") + { + // Mirrors the GCC example pattern: + // root Tuprules.tup: S = $(TUP_CWD); LIB_DIR = gcc + // gcc/Tuprules.tup: S ?= ...; LIB_DIR ?= .; macros use $(S)/$(LIB_DIR)/ + // gcc/Tupfile: produces , consumes via macros + auto f = E2EFixture { "groups_cross_dir_3tree" }; + auto source_dir = f.workdir() / "source"; + auto config_dir = f.workdir() / "config"; + auto build_dir = f.workdir() / "build"; + + f.mkdir("build"); + f.write_file("build/tup.config", ""); + + WHEN("parsing with -S, -C, and -B options") + { + auto result = f.pup({ + "parse", + "-S", source_dir.string(), + "-C", config_dir.string(), + "-B", build_dir.string(), + "-v" + }); + + THEN("parse succeeds without group warnings") + { + INFO("stdout:\n" << result.stdout_output); + INFO("stderr:\n" << result.stderr_output); + REQUIRE(result.success()); + REQUIRE(result.stdout_output.find("has no members") == std::string::npos); + } + } + + WHEN("building with -S, -C, and -B options") + { + auto result = f.pup({ + "-S", source_dir.string(), + "-C", config_dir.string(), + "-B", build_dir.string(), + "-j1" + }); + + THEN("build succeeds without group warnings") + { + INFO("stdout:\n" << result.stdout_output); + INFO("stderr:\n" << result.stderr_output); + REQUIRE(result.success()); + REQUIRE(result.stdout_output.find("has no members") == std::string::npos); + } + + THEN("generated header exists in build directory") + { + REQUIRE(f.exists("build/gcc/config.h")); + } + + THEN("output files are created from source globs") + { + REQUIRE(f.exists("build/gcc/hello.out")); + } + } + } +} + SCENARIO("Out-of-tree configuration with TUP_SRCDIR and TUP_OUTDIR variables", "[e2e][out-of-tree-config]") { GIVEN("a project using TUP_SRCDIR and TUP_OUTDIR in Tupfiles")