build: build the gem loader object through the rules - #7250
Conversation
`build/<name>/mrbgems/gem_init.o` was the one object declared by hand: an action-less `file` task whose prerequisites were the generated `gem_init.c` and `LEGAL`. rake does find the rule for it, but only when the task runs, after `needed?` was answered from those two files alone. The `.d` the compile writes and the flags record are read by the prerequisite procs of the rule, and for this object they never ran. A header it includes changing, or a define that reaches the build without touching `MRUBY_CONFIG`, left the old object in the archive. Adding a field to `struct mrb_state` and running `rake` shows it: every other object is compiled again, `gem_init.o` is not, and `bin/mruby` reads `mrb->c` at the old offset and crashes at start. A second `rake` changes nothing. Drop the hand-written task so the object is built the way `mrblib.o` is: by the rule that pairs it with `gem_init.c` and reads its `.d`. `LEGAL` hung on that task only so that a build wrote it. It now hangs on the products, beside the `libmruby.a` whose contents it describes, and stays out of the archive as before. A build without a gem writes it too now, with the mruby license alone.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
💤 Files with no reviewable changes (1)
Included review availability: Your plan includes up to 8 reviews per rolling hour; 1 remains after this review. 📝 WalkthroughWalkthroughThe build now registers the generated ChangesMRuby build artifacts
Estimated code review effort: 1 (Trivial) | ~5 minutes Merge Risk: ⚪ Minimal · up to This change makes the generated gem loader rebuild when its headers or recorded compiler flags change and moves LEGAL generation to the library build; no actionable merge-blocking risk remains after normal checks. Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
build/<name>/mrbgems/gem_init.o, the object that boots every gem of abuild, is the one object
tasks/mrbgems.rakedeclares by hand: afiletask without an action, with the generated
gem_init.candLEGALas itsprerequisites. Rake finds the rule for it, but only when the task runs,
after it has already answered
needed?from those two files alone. The.dits compile writes and the flags record beside it are read by theprerequisite procs of the rule, and for this object those never ran. A
header it includes changing, or a define reaching the build by a way that
leaves
MRUBY_CONFIGuntouched, left the old object inlibmruby.a.The header case is visible from the outside.
gem_init.creadsmrb->cand
mrb->exc; add a field at the top ofstruct mrb_stateand runrake:Every other object of the build is compiled again;
gem_init.okeeps theold offset of
mrb->c, andmrb_init_mrbgemsdies atmrb->c->cibaseunder
mrb_open.Why
file objfile(gem_init) => [gem_init.c, LEGAL](2013, 15871eb) exists tohave a build write
LEGALwithout archiving it:LEGALused to sit inthe object list of
libmruby.aand was moved to a prerequisite of thisobject. Rake's
Task#executerunsenhance_with_matching_rulefor a taskwithout an action, so the rule's action does compile the object, and its
prerequisite procs do run then; but that is after
invokedecided fromthe written prerequisites whether to execute at all.
mrblib.o, the othergenerated object of core, declares no task and is built by the rule from
Compiler#define_rulesalone, which reads the.dand discards an outputwhose recorded flags differ (#7236).
What this does
tasks/mrbgems.rakeno longer declares the object. The rule pairsmrbgems/gem_init.owithmrbgems/gem_init.cin the build directory asit does for
mrblib.o, and its.dand flags record take effect.LEGALbecomes a product of the build intasks/libmruby.rake, besidethe
libmruby.awhose contents it describes. It stays out of thearchive as before, and it is still written by a plain
rake. A buildwithout a gem writes it too now, with the mruby license alone; the
mrbcbuild (disable_libmruby) still does not.Verified
rake -m -j16,CCACHE_DISABLE=1, gcc;defaultgembox withenable_bintestandenable_test; the build directory built once onmaster(0122b45) before each row, and the run after each row doesnothing in both columns.
struct mrb_stateininclude/mruby.hCC,gem_init.onot among them;bin/mruby -e 'p 1'segfaults, and still does after anotherrakeCC,gem_init.oamong them;bin/mruby -e 'p 1'prints 1touch include/mruby.hCC,gem_init.onot among themCCconf.cc.defines << "PROBE_FLAG=1"from an environment variable the config reads (MRUBY_CONFIGuntouched)CC,gem_init.onot among them, its flags record has noPROBE_FLAGCC,gem_init.oamong them, its flags record has-DPROBE_FLAG=1; the variable removed: 166CCagainrake -m -j16 testfrom an empty build directoryrake -m -j16 test MRUBY_CONFIG=ci/gcc-clangfrom an empty build directoryLEGALin every target's build directoryLEGALafter a clean buildbuild/host/LEGAL, none inbuild/host/mrbc/,ar t libmruby.ahas noLEGALLEGALbuild/host/LEGALwith the mruby license aloneThe 165 in the master column is 208 objects less the 42 Prism objects
(#7248) and this one.
Environment
Details
The compile line of
gem_init.oin the default build, unchanged by thisPR (the record beside the object;
%{flags}is theflags:line):gcc -MMD -c -std=gnu99 -g -O3 -Wall -Wundef -Werror-implicit-function-declaration -Wwrite-strings -DHAVE_MRUBY_REGEXP_GEM -DMRB_USE_SET -DHAVE_MRUBY_IO_GEM -DMRB_USE_RATIONAL -DMRB_USE_COMPLEX -DMRB_USE_BIGINT -DMRB_USE_DEBUG_HOOK -I"include" -I"build/host/include" -o "build/host/mrbgems/gem_init.o" "build/host/mrbgems/gem_init.c"No C source changes and the compile line is the same, so
.textisunaffected in every build.
Summary by CodeRabbit