How does RbConfig::CONFIG['ruby_version'] get set?

Viewed 530

I noticed that although my Gemfile specifies Ruby 2.6.3 and ruby -v returns 2.6.3, I have a directory inside vendor/bundle/ruby called 2.6.0 and not one called 2.6.3.

I also noticed that if I run RbConfig::CONFIG['ruby_version'] inside an IRB console, I get "2.6.0", not 2.6.3.

Why is RbConfig::CONFIG['ruby_version'] set to 2.6.0 instead of 2.6.3? What controls it?

1 Answers

If you're on Mac, you can find rbconfig file in /Users/<username>/.rubies/ruby-2.6.5/lib/ruby/2.6.0/x86_64-darwin18 or somewhere alike.

Inside it, the comment says:

# The module storing Ruby interpreter configurations on building.
#
# This file was created by mkconfig.rb when ruby was built.  It contains
# build information for ruby which is used e.g. by mkmf to build
# compatible native extensions.  Any changes made to this file will be
# lost the next time ruby is built.

It turned out this file is generated by tool/mkconfig.rb script during the build process. Let's check it out.

versions = {}
IO.foreach(File.join(srcdir, "version.h")) do |l|
  m = /^\s*#\s*define\s+RUBY_(PATCHLEVEL)\s+(-?\d+)/.match(l)
  if m
    versions[m[1]] = m[2]
    break if versions.size == 4
    next
  end
  m = /^\s*#\s*define\s+RUBY_VERSION_(\w+)\s+(-?\d+)/.match(l)
  if m
    versions[m[1]] = m[2]
    break if versions.size == 4
    next
  end
  m = /^\s*#\s*define\s+RUBY_VERSION\s+\W?([.\d]+)/.match(l)
  if m
    versions['MAJOR'], versions['MINOR'], versions['TEENY'] = m[1].split('.')
    break if versions.size == 4
    next
  end
end
if versions.size != 4
  IO.foreach(File.join(srcdir, "include/ruby/version.h")) do |l|
    m = /^\s*#\s*define\s+RUBY_API_VERSION_(\w+)\s+(-?\d+)/.match(l)
    if m
      versions[m[1]] ||= m[2]
      break if versions.size == 4
      next
    end
  end
end
%w[MAJOR MINOR TEENY PATCHLEVEL].each do |v|
  print "  CONFIG[#{v.dump}] = #{(versions[v]||vars[v]).dump}\n"
end

And this is the logic to generate RbConfig::CONFIG['ruby_version'].

Two files referenced in the file are version.h and include/ruby/version.h, which you might find interesting.

Related