Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bundler/lib/bundler/man/bundle-config.1
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,15 @@ The path to the lockfile that bundler should use\. By default, Bundler adds \fB\
\fBlockfile_checksums\fR (\fBBUNDLE_LOCKFILE_CHECKSUMS\fR)
Whether Bundler should include a checksums section in new lockfiles, to protect from compromised gem sources\. Defaults to true\.
.TP
\fBno_build_extension\fR (\fBBUNDLE_NO_BUILD_EXTENSION\fR)
Whether Bundler should skip building native extensions during installation\. When set, gems are installed without compiling their C extensions\. To build extensions later, unset this setting and run \fBbundle pristine <gem>\fR\.
.TP
\fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR)
Whether \fBbundle package\fR should skip installing gems\.
.TP
\fBno_install_plugin\fR (\fBBUNDLE_NO_INSTALL_PLUGIN\fR)
Whether Bundler should skip installing RubyGems plugins during installation\. When set, plugin files are not written to the plugins directory\. To install plugins later, unset this setting and run \fBbundle pristine <gem>\fR\.
.TP
\fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR)
Whether Bundler should leave outdated gems unpruned when caching\.
.TP
Expand Down
8 changes: 8 additions & 0 deletions bundler/lib/bundler/man/bundle-config.1.ronn
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,16 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
Gemfile to disable lockfile creation entirely (see gemfile(5)).
* `lockfile_checksums` (`BUNDLE_LOCKFILE_CHECKSUMS`):
Whether Bundler should include a checksums section in new lockfiles, to protect from compromised gem sources. Defaults to true.
* `no_build_extension` (`BUNDLE_NO_BUILD_EXTENSION`):
Whether Bundler should skip building native extensions during installation.
When set, gems are installed without compiling their C extensions.
To build extensions later, unset this setting and run `bundle pristine <gem>`.
* `no_install` (`BUNDLE_NO_INSTALL`):
Whether `bundle package` should skip installing gems.
* `no_install_plugin` (`BUNDLE_NO_INSTALL_PLUGIN`):
Whether Bundler should skip installing RubyGems plugins during installation.
When set, plugin files are not written to the plugins directory.
To install plugins later, unset this setting and run `bundle pristine <gem>`.
* `no_prune` (`BUNDLE_NO_PRUNE`):
Whether Bundler should leave outdated gems unpruned when caching.
* `only` (`BUNDLE_ONLY`):
Expand Down
27 changes: 25 additions & 2 deletions bundler/lib/bundler/rubygems_gem_installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,24 @@ def install
extract_files
end

build_extensions if spec.extensions.any?
if options[:build_extension] == false
warn_skipped_extensions
elsif spec.extensions.any?
build_extensions
end
write_build_info_file
run_post_build_hooks

SharedHelpers.filesystem_access(bin_dir, :write) do
generate_bin
end

generate_plugins
if options[:install_plugin] == false
remove_stale_plugins
warn_skipped_plugins
else
generate_plugins
end
Comment on lines +42 to +47

write_spec

Expand Down Expand Up @@ -80,6 +89,20 @@ def generate_plugins
end
end

def warn_skipped_extensions
return if spec.extensions.empty?

Bundler.ui.warn "#{spec.full_name} contains native extensions that were not built.\n" \
"To build extensions, unset no_build_extension and run `bundle pristine #{spec.name}`."
end

def warn_skipped_plugins
return if spec.plugins.empty?

Bundler.ui.warn "#{spec.full_name} contains plugins that were not installed.\n" \
"To install plugins, unset no_install_plugin and run `bundle pristine #{spec.name}`."
end

if Bundler.rubygems.provides?("< 3.5.19")
def generate_bin_script(filename, bindir)
bin_script_path = File.join bindir, formatted_program_filename(filename)
Expand Down
2 changes: 2 additions & 0 deletions bundler/lib/bundler/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ class Settings
init_gems_rb
inline
lockfile_checksums
no_build_extension
no_install
no_install_plugin
no_prune
path.system
plugins
Expand Down
2 changes: 1 addition & 1 deletion bundler/lib/bundler/source/path/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def initialize(spec, options = {})
def post_install
run_hooks(:pre_install)

unless @disable_extensions
unless @disable_extensions || Bundler.settings[:no_build_extension]
build_extensions
run_hooks(:post_build)
end
Expand Down
4 changes: 3 additions & 1 deletion bundler/lib/bundler/source/rubygems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,9 @@ def rubygems_gem_installer(spec, options)
wrappers: true,
env_shebang: true,
build_args: options[:build_args],
bundler_extension_cache_path: extension_cache_path(spec)
bundler_extension_cache_path: extension_cache_path(spec),
build_extension: Bundler.settings[:no_build_extension] ? false : nil,
install_plugin: Bundler.settings[:no_install_plugin] ? false : nil
Comment on lines 533 to +538
)
@gem_installers_mutex.synchronize { @gem_installers[spec.name] ||= installer }
end
Expand Down
4 changes: 4 additions & 0 deletions lib/rubygems/dependency_installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ def initialize(options = {})
@dir_mode = options[:dir_mode]
@data_mode = options[:data_mode]
@prog_mode = options[:prog_mode]
@build_extension = options[:build_extension]
@install_plugin = options[:install_plugin]

# Indicates that we should not try to update any deps unless
# we absolutely must.
Expand Down Expand Up @@ -169,6 +171,8 @@ def install(dep_or_name, version = Gem::Requirement.default)
dir_mode: @dir_mode,
data_mode: @data_mode,
prog_mode: @prog_mode,
build_extension: @build_extension,
install_plugin: @install_plugin,
}
options[:install_dir] = @install_dir if @only_install_dir

Expand Down
12 changes: 12 additions & 0 deletions lib/rubygems/install_update_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,18 @@ def add_install_update_options
"rbconfig.rb for the deployment target platform") do |v, _o|
Gem.set_target_rbconfig(v)
end

add_option(:"Install/Update", "--[no-]build-extension",
"Build native extensions during installation.",
"Defaults to true") do |v, _o|
options[:build_extension] = v
end

add_option(:"Install/Update", "--[no-]install-plugin",
"Install plugins during installation.",
"Defaults to true") do |v, _o|
options[:install_plugin] = v
end
end

##
Expand Down
42 changes: 37 additions & 5 deletions lib/rubygems/installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,12 @@ def install
run_post_build_hooks

generate_bin
generate_plugins
if options[:install_plugin] == false
remove_stale_plugins
warn_skipped_plugins
else
generate_plugins
end
Comment on lines 289 to +295

write_spec
write_cache_file
Expand All @@ -298,7 +303,7 @@ def install

Gem::Specification.add_spec(spec) unless @install_dir

load_plugin
load_plugin unless options[:install_plugin] == false

run_post_install_hooks

Expand Down Expand Up @@ -804,11 +809,37 @@ def windows_stub_script(bindir, bin_file_name)
# configure scripts and rakefiles or mkrf_conf files.

def build_extensions
if options[:build_extension] == false
warn_skipped_extensions
return
end

builder = Gem::Ext::Builder.new spec, build_args, Gem.target_rbconfig, build_jobs

builder.build_extensions
end

def warn_skipped_extensions # :nodoc:
return if spec.extensions.empty?

alert_warning "#{spec.full_name} contains native extensions that were not built.\n" \
"To build extensions, run: gem pristine #{spec.name} --extensions"
end

def warn_skipped_plugins # :nodoc:
return if spec.plugins.empty?

alert_warning "#{spec.full_name} contains plugins that were not installed.\n" \
"To install plugins, run: gem pristine #{spec.name} --only-plugins"
end

def remove_stale_plugins # :nodoc:
return unless spec.plugins.empty?

ensure_writable_dir @plugins_dir
remove_plugins_for(spec, @plugins_dir)
end

##
# Reads the file index and extracts each file into the gem directory.
#
Expand Down Expand Up @@ -990,9 +1021,10 @@ def load_plugin
# are loaded at the same time.
return unless specs.size == 1

plugin_files = spec.plugins.map do |plugin|
File.join(@plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}")
plugin_files = spec.plugins.filter_map do |plugin|
path = File.join(@plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}")
path if File.exist?(path)
end
Gem.load_plugin_files(plugin_files)
Gem.load_plugin_files(plugin_files) unless plugin_files.empty?
end
end
2 changes: 1 addition & 1 deletion lib/rubygems/request_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def install(options, &block) # :yields: request, installer
# Install requested gems after they have been downloaded
sorted_requests.each do |req|
if req.installed? && @always_install.none? {|spec| spec == req.spec.spec }
req.spec.spec.build_extensions
req.spec.spec.build_extensions unless options[:build_extension] == false
yield req, nil if block_given?
Comment on lines 183 to 186
next
end
Expand Down
54 changes: 54 additions & 0 deletions spec/install/gems/no_build_extension_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

RSpec.describe "bundle install with --no-build-extension" do
before do
build_repo2 do
build_gem "with_extension" do |s|
s.extensions << "Rakefile"
s.write "Rakefile", <<-RUBY
task :default do
path = File.expand_path("lib", __dir__)
FileUtils.mkdir_p(path)
File.open("\#{path}/with_extension.rb", "w") do |f|
f.puts "WITH_EXTENSION = 'YES'"
end
end
RUBY
end
end
end

it "skips building native extensions and warns when no_build_extension is set" do
bundle_config "no_build_extension true"

gemfile <<-G
source "https://gem.repo2"
gem "with_extension"
gem "rake"
G

bundle :install

build_complete = default_bundle_path("extensions").join(
Gem::Platform.local.to_s,
Gem.extension_api_version.to_s,
"with_extension-1.0",
"gem.build_complete"
)
expect(build_complete).not_to exist
expect(err).to include("with_extension-1.0 contains native extensions that were not built")
expect(err).to include("unset no_build_extension and run `bundle pristine with_extension`")
end

it "builds native extensions by default" do
gemfile <<-G
source "https://gem.repo2"
gem "with_extension"
gem "rake"
G

bundle :install

expect(out).to include("Installing with_extension 1.0 with native extensions")
end
end
53 changes: 53 additions & 0 deletions spec/install/gems/no_install_plugin_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

RSpec.describe "bundle install with --no-install-plugin" do
before do
build_repo2 do
build_gem "with_plugin", "1.0" do |s|
s.write "lib/rubygems_plugin.rb", "# plugin code"
end

build_gem "with_plugin", "2.0"
end
end

let(:plugin_path) { default_bundle_path("plugins", "with_plugin_plugin.rb") }

it "does not generate the plugin wrapper and warns when no_install_plugin is set" do
bundle_config "no_install_plugin true"

install_gemfile <<-G
source "https://gem.repo2"
gem "with_plugin", "1.0"
G

expect(plugin_path).not_to exist
expect(err).to include("with_plugin-1.0 contains plugins that were not installed")
expect(err).to include("unset no_install_plugin and run `bundle pristine with_plugin`")
end

it "removes a stale plugin wrapper from a prior version when no_install_plugin is set" do
install_gemfile <<-G
source "https://gem.repo2"
gem "with_plugin", "1.0"
G
expect(plugin_path).to exist

bundle_config "no_install_plugin true"
install_gemfile <<-G
source "https://gem.repo2"
gem "with_plugin", "2.0"
G

expect(plugin_path).not_to exist
end

it "generates the plugin wrapper by default" do
install_gemfile <<-G
source "https://gem.repo2"
gem "with_plugin", "1.0"
G

expect(plugin_path).to exist
end
end
2 changes: 2 additions & 0 deletions spec/support/windows_tag_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ module WindowsTagGroup
"spec/bundler/digest_spec.rb",
"spec/bundler/fetcher/gem_remote_fetcher_spec.rb",
"spec/bundler/uri_normalizer_spec.rb",
"spec/install/gems/no_build_extension_spec.rb",
"spec/install/gems/no_install_plugin_spec.rb",
],
}.freeze
end
Expand Down
Loading
Loading