Skip to content

Conversation

@tobi
Copy link

@tobi tobi commented Jan 2, 2026

Summary

When brew is not in PATH, use_homebrew_yaml fails silently and Ruby compiles without libyaml/psych support.

This PR adds a fallback that downloads and builds libyaml from source when brew isn't in the path, similar to how OpenSSL is already handled.

Changes

  • Add build_package_yaml to install libyaml to $PREFIX_PATH/libyaml
  • Add fetch_libyaml_latest_version to get latest version from GitHub API (falls back to 0.2.5)
  • Add build_yaml_from_source as fallback in the yaml detection chain
  • Fix use_freebsd_yaml to return failure when not on FreeBSD (was silently succeeding)

After

$ PATH=/usr/bin:/bin ruby-build 3.4.1 /tmp/ruby
ruby-build: building libyaml 0.2.5 from source
==> Downloading yaml-0.2.5.tar.gz...
==> Installing yaml-0.2.5...
# ... continues with Ruby build ...
$ /tmp/ruby/bin/ruby -e "require 'yaml'"
# works!

When brew is not in PATH, use_homebrew_yaml fails silently and Ruby
compiles without libyaml/psych support. This adds a fallback that
downloads and builds libyaml from source, similar to how OpenSSL is
handled.

Changes:
- Add build_package_yaml to install libyaml to PREFIX_PATH/libyaml
- Add fetch_libyaml_latest_version to get latest version from GitHub
  API with fallback to 0.2.5
- Add build_yaml_from_source as fallback in the yaml detection chain
- Fix use_freebsd_yaml to return failure when not on FreeBSD
@eregon
Copy link
Member

eregon commented Jan 2, 2026

This builds libyaml on Linux even if it's already available on the system:

$ ruby-build ruby-4.0.0 ~/.rubies/ruby-4.0.0-libyaml
...
==> Downloading yaml-0.2.5.tar.gz...
...
==> Installing yaml-0.2.5...
-> ./configure "--prefix=$HOME/.rubies/ruby-4.0.0-libyaml/libyaml"
-> make -j 16
-> make install
==> Installed yaml-0.2.5 to /home/eregon/.rubies/ruby-4.0.0-libyaml
-> ./configure "--prefix=$HOME/.rubies/ruby-4.0.0-libyaml" --enable-shared "--with-libyaml-dir=$HOME/.rubies/ruby-4.0.0-libyaml/libyaml" --with-ext=openssl,psych,+

That would be a regression on Linux, e.g. OpenSSL is not built on Linux if already available on the system.

BTW in that scenario psych links to the system libyaml:

$ ldd ~/.rubies/ruby-4.0.0-libyaml/lib/ruby/4.0.0/x86_64-linux/psych.so
	linux-vdso.so.1 (0x00007f8472ac2000)
	libruby.so.4.0 => /home/eregon/.rubies/ruby-4.0.0-libyaml/lib/libruby.so.4.0 (0x00007f8472200000)
	libyaml-0.so.2 => /lib64/libyaml-0.so.2 (0x00007f84721c4000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f84720de000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f8471eeb000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f8471ec7000)
	libcrypt.so.2 => /lib64/libcrypt.so.2 (0x00007f8471e91000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f8471e62000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f8472ac4000)

which e.g. could break if the versions differ.

Probably the simplest & safest for now is to build_yaml_from_source only on macOS.

Copy link
Member

@mislav mislav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thank you for the contribution.

On top of everything @eregon already pointed out, I would also like to note that within the ruby-build project, we prefer that the declaration of dependencies is explicit in the ruby definition itself, for example how we did with libyaml up to Ruby 2.1.0:

install_package "yaml-0.1.6" "http://pyyaml.org/download/libyaml/yaml-0.1.6.tar.gz#7da6971b4bd08a986dd2a61353bc422362bd0edcc67d7ebaac68c95f74182749" --if needs_yaml

Starting from Ruby 2.2, we stopped using the needs_yaml declaration in ruby formulae, although my memory is fuzzy and I'm not sure why. It might have something to do with the psych gem bundling its own libyaml at some point? /cc @hsbt d646595

In any case, if we added the needs_yaml dependency back to Ruby definitions, we would need to make sure that libyaml would not be downloaded and compiled on systems that already have libyaml already present and discoverable in the build path. This last part is tricky since discovering system libraries isn't exactly straightforward. For example, we try to only download and build OpenSSL when it's not present on the system or when the system version is incompatible, but our detection approach for openssl is somewhat complex and cannot be easily extended to libyaml.

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.

3 participants