Skip to content

Avoid PATH-resolved echo in generated Makefiles - #748

Closed
kanutocd wants to merge 1 commit into
oxidize-rb:mainfrom
kanutocd:fix/makefile-echo-path-collision
Closed

Avoid PATH-resolved echo in generated Makefiles#748
kanutocd wants to merge 1 commit into
oxidize-rb:mainfrom
kanutocd:fix/makefile-echo-path-collision

Conversation

@kanutocd

@kanutocd kanutocd commented Jul 19, 2026

Copy link
Copy Markdown

Summary

Ruby's mkmf generates an ECHO command that invokes echo through PATH:

ECHO = $(ECHO1:0=@ echo)

Under some Bundler environments, a RubyGems executable named echo may appear earlier in PATH than the operating system's echo, causing native extension builds to invoke the wrong executable.

This change replaces the PATH-resolved command in rb-sys-generated POSIX Makefiles with an absolute path:

ECHO = $(ECHO1:0=@ /bin/echo)

The replacement is applied only for POSIX Makefiles (unless $nmake), so native Windows builds are unaffected.

Background

I originally encountered this while building the kino gem, where the generated Makefile invoked the RubyGems echo executable instead of the operating system's echo, resulting in incorrect build output.

The issue was originally addressed downstream in kino:

yaroslav/kino#4

Since rb-sys is responsible for generating the Makefile, it seemed more appropriate to apply the workaround here so downstream gems do not each need to patch their generated Makefiles independently.

Tests

  • Added a regression test verifying that generated POSIX Makefiles contain:

    ECHO = $(ECHO1:0=@ /bin/echo)
  • The regression test is skipped on Windows.

  • Verified with:

    • bundle exec rake test
    • bundle exec rubocop gem/lib/rb_sys/mkmf.rb gem/test/test_mkmf_echo.rb

Notes

This addresses the issue within rb-sys-generated Makefiles. The underlying ECHO definition originates from Ruby's mkmf and is now being addressed upstream in ruby/ruby#17975

If the upstream fix is merged and becomes part of the minimum Ruby version supported by rb-sys, this workaround may eventually become unnecessary.

- Ruby's mkmf generates an ECHO command that invokes `echo` through PATH.
When rb-sys is run under Bundler, a RubyGems executable with that name
may precede the system command and hijack native-extension build output.

- Replace the PATH-resolved command in rb-sys-generated POSIX Makefiles
with /bin/echo and add a regression test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant