Enable Bootsnap by default

- do some optimisation of `require`s before Bootsnap
- remove `HOMEBREW_BOOTSTRAP` environment variable as it's set by
  default
- add fast require in `bootsnap.rb` using logic from `ruby.sh`
- cleanup `bootsnap.rb` a bit
- remove setting `HOMEBREW_BOOTSNAP` in GitHub Actions
This commit is contained in:
Mike McQuaid 2025-03-31 17:15:31 +01:00
parent faddb73204
commit 9560c01453
No known key found for this signature in database
12 changed files with 39 additions and 28 deletions

View File

@ -12,7 +12,6 @@ env:
HOMEBREW_DEVELOPER: 1 HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_ENV_HINTS: 1 HOMEBREW_NO_ENV_HINTS: 1
HOMEBREW_BOOTSNAP: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1
defaults: defaults:

View File

@ -13,7 +13,6 @@ env:
HOMEBREW_DEVELOPER: 1 HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_ENV_HINTS: 1 HOMEBREW_NO_ENV_HINTS: 1
HOMEBREW_BOOTSNAP: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1
defaults: defaults:

View File

@ -14,7 +14,6 @@ env:
HOMEBREW_DEVELOPER: 1 HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_ENV_HINTS: 1 HOMEBREW_NO_ENV_HINTS: 1
HOMEBREW_BOOTSNAP: 1
HOMEBREW_NO_INSTALL_CLEANUP: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1
HOMEBREW_VERIFY_ATTESTATIONS: 1 HOMEBREW_VERIFY_ATTESTATIONS: 1

View File

@ -72,11 +72,6 @@ module Homebrew
description: "Use this as the `bat` theme for syntax highlighting.", description: "Use this as the `bat` theme for syntax highlighting.",
default_text: "`$BAT_THEME`.", default_text: "`$BAT_THEME`.",
}, },
HOMEBREW_BOOTSNAP: {
description: "If set, use Bootsnap to speed up repeated `brew` calls. " \
"A no-op on Linux when not using Homebrew's vendored, relocatable Ruby.",
boolean: true,
},
HOMEBREW_BOTTLE_DOMAIN: { HOMEBREW_BOTTLE_DOMAIN: {
description: "Use this URL as the download mirror for bottles. " \ description: "Use this URL as the download mirror for bottles. " \
"If bottles at that URL are temporarily unavailable, " \ "If bottles at that URL are temporarily unavailable, " \

View File

@ -43,9 +43,6 @@ module Homebrew::EnvConfig
sig { returns(T.nilable(::String)) } sig { returns(T.nilable(::String)) }
def bat_theme; end def bat_theme; end
sig { returns(T::Boolean) }
def bootsnap?; end
sig { returns(String) } sig { returns(String) }
def bottle_domain; end def bottle_domain; end

View File

@ -1,7 +1,10 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
# This file is included before any other files. It intentionally has typing disabled and has minimal use of `require`. # This file is included before any other files.
# It intentionally has typing disabled and uses `Homebrew::FastBootRequire`
# or `require_relative` to load all files
# (except "rbconfig" which is needed by `Homebrew::FastBootRequire`)
required_ruby_major, required_ruby_minor, = ENV.fetch("HOMEBREW_REQUIRED_RUBY_VERSION", "").split(".").map(&:to_i) required_ruby_major, required_ruby_minor, = ENV.fetch("HOMEBREW_REQUIRED_RUBY_VERSION", "").split(".").map(&:to_i)
gems_vendored = if required_ruby_minor.nil? gems_vendored = if required_ruby_minor.nil?
@ -21,12 +24,30 @@ else
vendored_versions.include?("#{ruby_major}.#{ruby_minor}") vendored_versions.include?("#{ruby_major}.#{ruby_minor}")
end.freeze end.freeze
# Setup Homebrew::FastBootRequire for faster boot requires.
# Inspired by https://github.com/Shopify/bootsnap/wiki/Bootlib::Require
require "rbconfig"
module Homebrew
module FastBootRequire
ARCHDIR = RbConfig::CONFIG["archdir"].freeze
RUBYLIBDIR = RbConfig::CONFIG["rubylibdir"].freeze
def self.from_archdir(feature)
require(File.join(ARCHDIR, feature.to_s))
end
def self.from_rubylibdir(feature)
require(File.join(RUBYLIBDIR, "#{feature}.rb"))
end
end
end
# We trust base Ruby to provide what we need. # We trust base Ruby to provide what we need.
# Don't look into the user-installed sitedir, which may contain older versions of RubyGems. # Don't look into the user-installed sitedir, which may contain older versions of RubyGems.
require "rbconfig"
$LOAD_PATH.reject! { |path| path.start_with?(RbConfig::CONFIG["sitedir"]) } $LOAD_PATH.reject! { |path| path.start_with?(RbConfig::CONFIG["sitedir"]) }
require "pathname" Homebrew::FastBootRequire.from_rubylibdir("pathname")
dir = __dir__ || raise("__dir__ is not defined") dir = __dir__ || raise("__dir__ is not defined")
HOMEBREW_LIBRARY_PATH = Pathname(dir).parent.realpath.freeze HOMEBREW_LIBRARY_PATH = Pathname(dir).parent.realpath.freeze
HOMEBREW_USING_PORTABLE_RUBY = RbConfig.ruby.include?("/vendor/portable-ruby/").freeze HOMEBREW_USING_PORTABLE_RUBY = RbConfig.ruby.include?("/vendor/portable-ruby/").freeze
@ -48,7 +69,7 @@ unless $LOAD_PATH.include?(HOMEBREW_LIBRARY_PATH.to_s)
$LOAD_PATH.insert(last_homebrew_path_idx + 1, HOMEBREW_LIBRARY_PATH.to_s) $LOAD_PATH.insert(last_homebrew_path_idx + 1, HOMEBREW_LIBRARY_PATH.to_s)
end end
require_relative "../vendor/bundle/bundler/setup" require_relative "../vendor/bundle/bundler/setup"
require "portable_ruby_gems" if HOMEBREW_USING_PORTABLE_RUBY Homebrew::FastBootRequire.from_archdir("portable_ruby_gems") if HOMEBREW_USING_PORTABLE_RUBY
$LOAD_PATH.unshift "#{HOMEBREW_LIBRARY_PATH}/vendor/bundle/#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/" \ $LOAD_PATH.unshift "#{HOMEBREW_LIBRARY_PATH}/vendor/bundle/#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/" \
"bundler-#{Homebrew::HOMEBREW_BUNDLER_VERSION}/lib" "bundler-#{Homebrew::HOMEBREW_BUNDLER_VERSION}/lib"
$LOAD_PATH.uniq! $LOAD_PATH.uniq!

View File

@ -2,9 +2,10 @@
# frozen_string_literal: true # frozen_string_literal: true
# This file should be the first `require` in all entrypoints of `brew`. # This file should be the first `require` in all entrypoints of `brew`.
# Bootsnap should be loaded as early as possible.
require_relative "standalone/init" require_relative "standalone/init"
require_relative "startup/bootsnap"
require_relative "startup/ruby_path" require_relative "startup/ruby_path"
require "startup/config" require "startup/config"
require_relative "startup/bootsnap"
require_relative "standalone/sorbet" require_relative "standalone/sorbet"

View File

@ -34,17 +34,21 @@ module Homebrew
end end
private_class_method def self.enabled? private_class_method def self.enabled?
HOMEBREW_USING_PORTABLE_RUBY && ENV["HOMEBREW_NO_BOOTSNAP"].nil? && !ENV["HOMEBREW_BOOTSNAP"].nil? !ENV["HOMEBREW_BOOTSNAP_GEM_PATH"].to_s.empty? && ENV["HOMEBREW_NO_BOOTSNAP"].nil?
end end
def self.load!(compile_cache: true) def self.load!(compile_cache: true)
return unless enabled? return unless enabled?
require "bootsnap" require ENV.fetch("HOMEBREW_BOOTSNAP_GEM_PATH")
::Bootsnap.setup( ::Bootsnap.setup(
cache_dir:, cache_dir:,
ignore_directories:, ignore_directories:,
# In development environments the bootsnap compilation cache is
# generated on the fly when source files are loaded.
# https://github.com/Shopify/bootsnap?tab=readme-ov-file#precompilation
development_mode: true,
load_path_cache: true, load_path_cache: true,
compile_cache_iseq: compile_cache, compile_cache_iseq: compile_cache,
compile_cache_yaml: compile_cache, compile_cache_yaml: compile_cache,

View File

@ -5,7 +5,7 @@
# work as the first item in `brew.rb` so we can load gems with Bundler when # work as the first item in `brew.rb` so we can load gems with Bundler when
# needed before anything else is loaded (e.g. `json`). # needed before anything else is loaded (e.g. `json`).
require "English" Homebrew::FastBootRequire.from_rubylibdir("English")
module Homebrew module Homebrew
# Keep in sync with the `Gemfile.lock`'s BUNDLED WITH. # Keep in sync with the `Gemfile.lock`'s BUNDLED WITH.

View File

@ -127,6 +127,10 @@ If there's no Homebrew Portable Ruby available for your processor:
if [[ -x "${vendor_ruby_path}" ]] if [[ -x "${vendor_ruby_path}" ]]
then then
HOMEBREW_RUBY_PATH="${vendor_ruby_path}" HOMEBREW_RUBY_PATH="${vendor_ruby_path}"
HOMEBREW_BOOTSNAP_GEM_PATH="$(
shopt -s nullglob
echo "${vendor_ruby_root}"/lib/ruby/gems/*/gems/bootsnap-*/lib/bootsnap 2>/dev/null
)"
TERMINFO_DIRS="${vendor_ruby_terminfo}" TERMINFO_DIRS="${vendor_ruby_terminfo}"
if [[ "${vendor_ruby_current_version}" != "${HOMEBREW_PORTABLE_RUBY_VERSION}" ]] if [[ "${vendor_ruby_current_version}" != "${HOMEBREW_PORTABLE_RUBY_VERSION}" ]]
then then
@ -146,7 +150,7 @@ If there's no Homebrew Portable Ruby available for your processor:
fi fi
fi fi
export HOMEBREW_RUBY_PATH export HOMEBREW_RUBY_PATH HOMEBREW_BOOTSNAP_GEM_PATH
[[ -n "${HOMEBREW_LINUX}" && -n "${TERMINFO_DIRS}" ]] && export TERMINFO_DIRS [[ -n "${HOMEBREW_LINUX}" && -n "${TERMINFO_DIRS}" ]] && export TERMINFO_DIRS
} }

View File

@ -3843,11 +3843,6 @@ command execution e.g. `$(cat file)`.
*Default:* `$BAT_THEME`. *Default:* `$BAT_THEME`.
`HOMEBREW_BOOTSNAP`
: If set, use Bootsnap to speed up repeated `brew` calls. A no-op on Linux when
not using Homebrew's vendored, relocatable Ruby.
`HOMEBREW_BOTTLE_DOMAIN` `HOMEBREW_BOTTLE_DOMAIN`
: Use this URL as the download mirror for bottles. If bottles at that URL are : Use this URL as the download mirror for bottles. If bottles at that URL are

View File

@ -2473,9 +2473,6 @@ Use this as the \fBbat\fP theme for syntax highlighting\.
\fIDefault:\fP \fB$BAT_THEME\fP\&\. \fIDefault:\fP \fB$BAT_THEME\fP\&\.
.RE .RE
.TP .TP
\fBHOMEBREW_BOOTSNAP\fP
If set, use Bootsnap to speed up repeated \fBbrew\fP calls\. A no\-op on Linux when not using Homebrew\[u2019]s vendored, relocatable Ruby\.
.TP
\fBHOMEBREW_BOTTLE_DOMAIN\fP \fBHOMEBREW_BOTTLE_DOMAIN\fP
Use this URL as the download mirror for bottles\. If bottles at that URL are temporarily unavailable, the default bottle domain will be used as a fallback mirror\. For example, \fBexport HOMEBREW_BOTTLE_DOMAIN=http://localhost:8080\fP will cause all bottles to download from the prefix \fBhttp://localhost:8080/\fP\&\. If bottles are not available at \fB$HOMEBREW_BOTTLE_DOMAIN\fP they will be downloaded from the default bottle domain\. Use this URL as the download mirror for bottles\. If bottles at that URL are temporarily unavailable, the default bottle domain will be used as a fallback mirror\. For example, \fBexport HOMEBREW_BOTTLE_DOMAIN=http://localhost:8080\fP will cause all bottles to download from the prefix \fBhttp://localhost:8080/\fP\&\. If bottles are not available at \fB$HOMEBREW_BOTTLE_DOMAIN\fP they will be downloaded from the default bottle domain\.
.RS .RS