build_config: give the clang-asan config a name of its own - #7197
Conversation
build_config/clang-asan.rb opened an anonymous `MRuby::Build`, and an
unnamed build is called 'host' (lib/mruby/build.rb:94). The build tree
is keyed by that name (:107), so MRUBY_CONFIG=clang-asan wrote its
`-fsanitize=address,undefined` objects straight into build/host, on top
of whatever a default build had left there. No build/clang-asan was
ever created.
Starting from a good default build, and exiting 0 while doing it:
$ ls build/
host
$ md5sum build/host/bin/mruby build/host/lib/libmruby.a
9881d200e90c5a7df4a29a36b193fbab build/host/bin/mruby
8dbb8c26becf449f5871f9e090c8a4ff build/host/lib/libmruby.a
$ ar t build/host/lib/libmruby.a | sort -u | wc -l
99
$ MRUBY_CONFIG=clang-asan rake -j8 # exit 0
...
Config Name: host
Output Directory: build/host
$ ls build/
host
$ md5sum build/host/bin/mruby build/host/lib/libmruby.a
07a8c1484756e079a731e8af15944606 build/host/bin/mruby
5160fcdf4b7e757f4ac6f547fa7100c2 build/host/lib/libmruby.a
$ nm -D build/host/bin/mruby | grep -c asan
174
What is left in build/host is a sanitizer build at `-O0`, and the repo
bin/ symlinks point into it, because `host?` builds install them (:452).
The damage outlives the run, and here it does not stop at a tree that
measures the wrong thing. libmruby.a is archived with `ar rs`
(lib/mruby/build/command.rb:258); r replaces by member name, and an
archive records only the base name, so it cannot hold two objects called
gem_init.o apart. A default build's archive holds 155 members under 99
distinct names, 43 of them gem_init.o. After the clang-asan run it
holds 173 under 107, 51 of them gem_init.o, since full-core.gembox
carries gems that default.gembox does not. The next default build hands
`ar rs` its own 43, which cannot name the 8 that came from those gems,
and they stay compiled with `-fsanitize`.
full-core.gembox skips mruby-bin-debugger while default.gembox carries
it, so the default build's mrdb link is the one that reaches those
members, with plain gcc and no sanitizer runtime. It aborts, and goes
on aborting on every later run:
$ rake -j8
...
ld: build/host/lib/libmruby.a(gem_init.o): in function
`asan.module_ctor':
gem_init.c:(.text.asan.module_ctor[asan.module_ctor]+0x5):
undefined reference to `__asan_init'
collect2: error: ld returned 1 exit status
rake aborted!
Tasks: TOP => build => bin/mrdb => build/host/bin/mrdb
Recovery is rm -rf build/host plus a full rebuild.
Name the build after its config, which is what build_config/asan.rb
already does, and its own comment says why. full-core.gembox supplies
mruby-bin-mrbc through its glob, so the rename is all this config needs.
It now builds into a directory of its own and leaves an existing host
build byte-identical:
$ MRUBY_CONFIG=clang-asan rake -j8 # exit 0
...
Config Name: clang-asan
Output Directory: build/clang-asan
$ ls build/
clang-asan host
$ md5sum build/host/bin/mruby build/host/lib/libmruby.a
9881d200e90c5a7df4a29a36b193fbab build/host/bin/mruby
8dbb8c26becf449f5871f9e090c8a4ff build/host/lib/libmruby.a
$ ar t build/host/lib/libmruby.a | sort -u | wc -l
99
$ nm -D build/clang-asan/bin/mruby | grep -c asan
174
$ rake -j8 # exit 0
The build it produces is the one it was producing before, and it is
green:
$ MRUBY_CONFIG=clang-asan rake -m test # exit 0
bintest - Command Binary Test
Total: 79 OK: 79 KO: 0 Crash: 0 Skip: 0
mrbtest - Embeddable Ruby Test
Total: 2312 OK: 2309 KO: 0 Crash: 0 Skip: 3
One symlink does not follow the rename. mruby-bin-config installs its
product through `define_installer` rather than
`define_installer_if_needed` (mrbgems/mruby-bin-config/mrbgem.rake:31),
so bin/mruby-config follows whichever non-cross build ran last, named or
not. That is what master already does for every named build carrying
that gem, and it is unchanged here:
$ MRUBY_CONFIG=bench rake -j8
$ ls -l bin/mruby-config
bin/mruby-config -> ../build/bench/bin/mruby-config
|
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 (1)
Included review availability: Your plan includes up to 8 reviews per rolling hour; 4 remain after this review. 📝 WalkthroughWalkthroughThe Clang ASan configuration now uses a dedicated ChangesClang ASan build
Estimated code review effort: 1 (Trivial) | ~2 minutes Merge Risk: ⚪ Minimal · up to The change gives the sanitizer build its own output directory, preventing it from overwriting or contaminating the default build; the supplied rebuild and test results are successful, so no actionable merge-blocking risk remains beyond normal checks. Possibly related PRs
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_config/ci/msvc.rb opened an anonymous `MRuby::Build`, and an unnamed build is called 'host' (lib/mruby/build.rb:114). The build tree is keyed by that name (:127), so MRUBY_CONFIG=ci/msvc aimed a full-core build with `MRB_GC_FIXED_ARENA` at build/host, the directory a default build on the same machine uses. The Windows-VC job never sees that, since it builds a fresh checkout, but a developer who points MRUBY_CONFIG at this config on a tree the default config has built shares one directory between two gem sets, which is the shape mruby#7195, mruby#7197, mruby#7199 and mruby#7200 took out of the other configs that had it. 14d6e42 named the bintest build in ci/gcc-clang and left this one alone, on the ground that a single build has no sibling for a name to tell it apart from. That was a reason about telling builds apart; the build directory is decided by the name whether or not there is a sibling, and that is the reason here. Name it after its config, as build_config/mrbc.rb, clang-asan.rb and gctest.rb are. Nothing in the file needs the build to be called 'host'. It is an `MRuby::Build`, and it pulls `mruby-bin-mrbc` in through full-core, so it lends no mrbc to any cross target and creates its own internal one either way (:174). The name reaches three other places: `install_prefix` (:625), the `bin/*.bat` wrappers that `define_installer_if_needed` writes only when `host?` answers true (:461 and :482), and the mrbtest that `rake clean` removes from MRUBY_ROOT/bin (tasks/test.rake:82). The job runs `rake -m test:run:serial` (.github/workflows/build.yml:89), which installs nothing and cleans nothing, so none of the three fires. `enable_bintest` has not required the name 'host' since fd113da, and test/bintest.rb resolves every binary it runs from BUILD_DIR rather than from bin/; the `bintest` build in ci/gcc-clang is this same shape under a name, in the same workflow. There is no MSVC here to run the job with. What can be checked on Linux is that the config still loads and that the tree it names is its own; the job on this change is the run: $ MRUBY_CONFIG=ci/msvc rake -T | grep amalgam rake amalgam # Generate amalgamated mruby.h and mruby.c in .../build/msvc/amalgam
build_config/clang-asan.rbopens an anonymousMRuby::Build, and an unnamed build is calledhost(lib/mruby/build.rb:94). The build tree is keyed by that name (:107), soMRUBY_CONFIG=clang-asanaims its-fsanitize=address,undefinedobjects atbuild/host, on top of whatever a default build has left there, and never creates a directory of its own. This is the same shape as #7195, on a config that PR does not touch.All of the transcripts below are from today's master, starting from one clean default build.
The clobber
It exits 0 while doing it:
What is left in
build/hostis a sanitizer build at-O0, and the repobin/symlinks point into it, becausehost?builds install them (:452).It does not stop at a tree that measures the wrong thing
libmruby.ais archived withar rs(lib/mruby/build/command.rb:258);rreplaces by member name, and an archive records only the base name, so it cannot hold two objects calledgem_init.oapart. A default build's archive holds 155 members under 99 distinct names, 43 of themgem_init.o. After theclang-asanrun it holds 173 under 107, 51 of themgem_init.o, sincefull-core.gemboxcarries gems thatdefault.gemboxdoes not. The next default build handsar rsits own 43, which cannot name the 8 that came from those gems, and they stay compiled with-fsanitize.full-core.gemboxskipsmruby-bin-debuggerwhiledefault.gemboxcarries it, so the default build'smrdblink is the one that reaches those members, with plain gcc and no sanitizer runtime. It aborts, and goes on aborting on every later run:Recovery is
rm -rf build/hostplus a full rebuild.Naming it
The build is named after its config, which is what
build_config/asan.rbandbuild_config/gctest.rbalready do, and what 8b44a52 did forhost-cxx.full-core.gemboxsuppliesmruby-bin-mrbcthrough its glob, so the rename is all this config needs, and nothing outside the config refers to the directory it produces.Verified
One clean default build, then the sanitizer build, then the default config again,
rake -j8throughout:The build it produces is the one it was producing before, and it is green:
One symlink does not follow the rename
mruby-bin-configinstalls its product throughdefine_installerrather thandefine_installer_if_needed(mrbgems/mruby-bin-config/mrbgem.rake:31), sobin/mruby-configfollows whichever non-cross build ran last, named or not. That is what master already does for every named build carrying that gem, and it is unchanged here:A note on
build_config/asan.rbOnce this config has a name, it and
build_config/asan.rbare the same build under two names: bothconf.toolchain :clang, bothconf.gembox 'full-core', bothconf.enable_sanitizer "address,undefined",enable_debug,enable_bintestandenable_test, with nothing else in either file. Whether one of them should go, and which name should survive, is yours to say.clang-asanis the onedoc/mruby3.0.md:14names andtest/t/hash.rb:1005points at;asan.rbis the one whose commit message says it backs a local pre-push hook. This PR changes neither of those things and leaves both files in place.Environment
Details
clang-asanThe line each build gives
src/string.c, read offrake --verbosewith-MMD -c, the-Ilist and-odropped.clang-asancallsenable_debug, which appends-g3 -O0after the clang toolchain's own-g -O3:Summary by CodeRabbit
clang-asansanitizer build configuration.