Project

General

Profile

Bug #22490 ยป cruby-make-n-build-ext-runsheet.sh

hopefully you'll only need to set your WORK dir - graial (al gray), 11/02/2026 01:03 AM

 
#!/usr/bin/env bash
# Run-sheet: does `make -n build-ext` delete ext/extinit.{c,o}?
# Native build of the Ruby 4.0.9 release tarball, with --with-static-linked-ext.
# No rbenv, no install, nothing outside $WORK is touched.
#
# Usage: bash cruby-make-n-build-ext-runsheet.sh [WORK_DIR]
# Needs: curl, a C compiler, GNU make, sha256sum, stat (GNU coreutils).
# Time: about 2 minutes of build on 2 cores.
#
# Every result the report needs is written to $WORK/out/.

set -euo pipefail

WORK=<please-set-your-folder>
VER=4.0.9
TARBALL=ruby-$VER.tar.gz
# Official digest, from ruby-lang.org's _data/releases.yml
SHA=c35350682ff050b79702d57ade4516e7336063f510155d19fb2fb5b3f3909511
EXTS=etc,stringio

mkdir -p "$WORK/out"
cd "$WORK"
OUT=$WORK/out

step() { printf '\n=== %s\n' "$*"; }

# --------------------------------------------------------------------------
step "0. Environment (for the report's Environment section)"
{
uname -srm
make --version | head -1
cc --version | head -1
} | tee "$OUT/environment.txt"

# --------------------------------------------------------------------------
step "1. Download and verify the $VER tarball"
[ -f "$TARBALL" ] || curl -sSfLO "https://cache.ruby-lang.org/pub/ruby/${VER%.*}/$TARBALL"
echo "$SHA $TARBALL" | sha256sum -c -
rm -rf "ruby-$VER" && tar xzf "$TARBALL"

# --------------------------------------------------------------------------
step "2. Configure and build natively with --with-static-linked-ext --with-ext=$EXTS"
cd "ruby-$VER"
./configure --disable-install-doc --with-static-linked-ext --with-ext="$EXTS" \
> "$OUT/configure.log" 2>&1
make -j"$(nproc)" > "$OUT/make.log" 2>&1
./ruby -v | tee "$OUT/ruby-v.txt"
echo "init( lines in ext/extinit.c: $(grep -c 'init(Init_' ext/extinit.c)" # expect 2
./ruby --disable-gems -e 'require "etc"; require "stringio"; puts "extensions load: ok"'
cd ..

# Keep the built tree pristine; each experiment gets its own copy.
rm -rf tree-A tree-B
cp -a "ruby-$VER" tree-A
cp -a "ruby-$VER" tree-B

# --------------------------------------------------------------------------
step "3. Experiment A: the dry run (the bug)"
cd tree-A
sha256sum ruby ext/extinit.o ext/extinit.c | tee "$OUT/A-before.sha256"
make -n build-ext > "$OUT/A-make-n-build-ext.log" 2>&1
echo "make -n build-ext exit status: $?"
sha256sum ruby ext/extinit.o ext/extinit.c > "$OUT/A-after.sha256" 2>&1 || true
cat "$OUT/A-after.sha256"
# expect: ruby unchanged; extinit.o and extinit.c "No such file or directory"
echo "--- the recursive-make lines make ran despite -n:"
grep -n -m1 "make -f ext/configure-ext.mk -n" "$OUT/A-make-n-build-ext.log"
echo "extmk.rb invocations printed: $(grep -c 'extmk.rb --make=' "$OUT/A-make-n-build-ext.log")"

# --------------------------------------------------------------------------
step "4. Experiment A, continued: what a follow-up 'make ruby' produces"
make ruby > "$OUT/A-make-ruby.log" 2>&1
echo "make ruby exit status: $?" # expect 0
echo "init( lines in ext/extinit.c: $(grep -c 'init(Init_' ext/extinit.c || true)" # expect 0
set +e
./ruby --disable-gems -e 'require "etc"' > "$OUT/A-require-etc.txt" 2>&1
echo "require \"etc\" exit status: $?" # expect 1
set -e
head -1 "$OUT/A-require-etc.txt" # expect LoadError
cd ..

# --------------------------------------------------------------------------
step "5. Experiment B: does a real 'make build-ext' also delete them?"
cd tree-B
stat -c '%n inode=%i' ext/extinit.c ext/extinit.o ruby | tee "$OUT/B-before.stat"
sha256sum ext/extinit.c ruby > "$OUT/B-before.sha256"
make build-ext > "$OUT/B-make-build-ext.log" 2>&1
echo "make build-ext exit status: $?"
stat -c '%n inode=%i' ext/extinit.c ext/extinit.o ruby | tee "$OUT/B-after.stat"
sha256sum ext/extinit.c ruby > "$OUT/B-after.sha256"
echo "--- extinit.c content (expect: identical):"
diff <(head -1 "$OUT/B-before.sha256") <(head -1 "$OUT/B-after.sha256") && echo identical
echo "--- ruby binary (changed if it was relinked):"
diff <(tail -1 "$OUT/B-before.sha256") <(tail -1 "$OUT/B-after.sha256") && echo identical || true
# expect: new inodes for extinit.c and extinit.o (deleted and rewritten),
# same extinit.c content.
cd ..

step "Done. Results are in $OUT"
ls "$OUT"
    (1-1/1)