rubygems-update 3.3.10 → 3.3.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/Manifest.txt +14 -0
  4. data/bundler/CHANGELOG.md +11 -0
  5. data/bundler/exe/bundler +1 -1
  6. data/bundler/lib/bundler/build_metadata.rb +3 -3
  7. data/bundler/lib/bundler/cli/info.rb +1 -1
  8. data/bundler/lib/bundler/cli/init.rb +1 -1
  9. data/bundler/lib/bundler/cli/show.rb +1 -1
  10. data/bundler/lib/bundler/cli.rb +1 -1
  11. data/bundler/lib/bundler/installer.rb +2 -2
  12. data/bundler/lib/bundler/man/bundle-config.1 +3 -3
  13. data/bundler/lib/bundler/man/bundle-config.1.ronn +8 -6
  14. data/bundler/lib/bundler/shared_helpers.rb +4 -4
  15. data/bundler/lib/bundler/source/metadata.rb +1 -1
  16. data/bundler/lib/bundler/templates/Executable +2 -4
  17. data/bundler/lib/bundler/templates/Executable.bundler +1 -1
  18. data/bundler/lib/bundler/templates/Executable.standalone +2 -4
  19. data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +1 -1
  20. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
  21. data/bundler/lib/bundler/version.rb +1 -1
  22. data/bundler/lib/bundler.rb +1 -1
  23. data/lib/rubygems/commands/setup_command.rb +1 -1
  24. data/lib/rubygems/ext/builder.rb +3 -0
  25. data/lib/rubygems/ext/cargo_builder.rb +305 -0
  26. data/lib/rubygems/ext/ext_conf_builder.rb +1 -1
  27. data/lib/rubygems/ext.rb +1 -0
  28. data/lib/rubygems/gemcutter_utilities.rb +34 -5
  29. data/lib/rubygems/request.rb +1 -1
  30. data/lib/rubygems/source/git.rb +1 -0
  31. data/lib/rubygems.rb +2 -2
  32. data/rubygems-update.gemspec +1 -1
  33. data/setup.rb +1 -1
  34. data/test/rubygems/helper.rb +5 -5
  35. data/test/rubygems/test_gem.rb +1 -1
  36. data/test/rubygems/test_gem_command_manager.rb +1 -1
  37. data/test/rubygems/test_gem_commands_help_command.rb +1 -1
  38. data/test/rubygems/test_gem_commands_push_command.rb +5 -0
  39. data/test/rubygems/test_gem_commands_setup_command.rb +1 -1
  40. data/test/rubygems/test_gem_commands_signin_command.rb +100 -11
  41. data/test/rubygems/test_gem_dependency_installer.rb +2 -2
  42. data/test/rubygems/test_gem_ext_builder.rb +1 -1
  43. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore +1 -0
  44. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock +374 -0
  45. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml +10 -0
  46. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb +21 -0
  47. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec +10 -0
  48. data/test/rubygems/test_gem_ext_cargo_builder/custom_name/src/lib.rs +30 -0
  49. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore +1 -0
  50. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +374 -0
  51. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +10 -0
  52. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb +21 -0
  53. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec +8 -0
  54. data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs +42 -0
  55. data/test/rubygems/test_gem_ext_cargo_builder.rb +148 -0
  56. data/test/rubygems/test_gem_ext_cmake_builder.rb +2 -0
  57. data/test/rubygems/test_gem_gemcutter_utilities.rb +4 -2
  58. data/test/rubygems/test_gem_source_git.rb +1 -0
  59. data/test/rubygems/test_gem_specification.rb +1 -1
  60. data/test/rubygems/test_project_sanity.rb +1 -1
  61. data/test/rubygems/test_require.rb +1 -1
  62. data/test/test_changelog_generator.rb +1 -0
  63. metadata +17 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88b51a16140837e81c1775155ede2bfd054f6ac05e34072ebfa871814decd8e6
4
- data.tar.gz: 12de868024f63a63873184ddf8cf856f14808484fb41dd091c862390870cbd4f
3
+ metadata.gz: 3f9f133a10adb0dca16feb1c6dd3d12c2da126c621dcf6ac086a5434f62cdecb
4
+ data.tar.gz: 0b48275de222559f54a44e6cdf9c1105e40ff156d57d26d2a5a246d1fcc50521
5
5
  SHA512:
6
- metadata.gz: 0aab9e5b5388126454361b8a1b591cb376da5edc5449246690cf0c666cfed5714ad95dfa6844739362cbae488fd1fb868eccaa5a990bb5e3a50eaef9a7df28ca
7
- data.tar.gz: e438ac4bf829acc1244d51dd00f098c1073d904391b8c5feee24fad1949b870b23cd60d180ac458db707bbcdae2c13bc6ede5a6491e6c0ee9afa23884f7305b6
6
+ metadata.gz: ab1dc93b4c3748bc3580c8d4047ec956a52271b389fcb1c306ebecbf665670231648126aed8b84c711d7444025323a27cf665fefe801180bfeb3cc5d5a26ad25
7
+ data.tar.gz: 24d7c27ed7fdfff099d291b7524c377296ea4f3622c9c1880c3f2bd55b9fafcca79ee138df9d00138cc22dd5be5d5db376d6b145ec96566ccbc63dd7fd4cd507
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # 3.3.11 / 2022-04-07
2
+
3
+ ## Enhancements:
4
+
5
+ * Enable mfa on specific keys during gem signin. Pull request #5305 by
6
+ aellispierce
7
+ * Prefer `__dir__` to `__FILE__`. Pull request #5444 by deivid-rodriguez
8
+ * Add cargo builder for rust extensions. Pull request #5175 by ianks
9
+ * Installs bundler 2.3.11 as a default gem.
10
+
11
+ ## Documentation:
12
+
13
+ * Improve RDoc setup. Pull request #5398 by deivid-rodriguez
14
+
1
15
  # 3.3.10 / 2022-03-23
2
16
 
3
17
  ## Enhancements:
data/Manifest.txt CHANGED
@@ -382,6 +382,7 @@ lib/rubygems/exceptions.rb
382
382
  lib/rubygems/ext.rb
383
383
  lib/rubygems/ext/build_error.rb
384
384
  lib/rubygems/ext/builder.rb
385
+ lib/rubygems/ext/cargo_builder.rb
385
386
  lib/rubygems/ext/cmake_builder.rb
386
387
  lib/rubygems/ext/configure_builder.rb
387
388
  lib/rubygems/ext/ext_conf_builder.rb
@@ -635,6 +636,19 @@ test/rubygems/test_gem_dependency_list.rb
635
636
  test/rubygems/test_gem_dependency_resolution_error.rb
636
637
  test/rubygems/test_gem_doctor.rb
637
638
  test/rubygems/test_gem_ext_builder.rb
639
+ test/rubygems/test_gem_ext_cargo_builder.rb
640
+ test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore
641
+ test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.lock
642
+ test/rubygems/test_gem_ext_cargo_builder/custom_name/Cargo.toml
643
+ test/rubygems/test_gem_ext_cargo_builder/custom_name/build.rb
644
+ test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec
645
+ test/rubygems/test_gem_ext_cargo_builder/custom_name/src/lib.rs
646
+ test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore
647
+ test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock
648
+ test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml
649
+ test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/build.rb
650
+ test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec
651
+ test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs
638
652
  test/rubygems/test_gem_ext_cmake_builder.rb
639
653
  test/rubygems/test_gem_ext_configure_builder.rb
640
654
  test/rubygems/test_gem_ext_ext_conf_builder.rb
data/bundler/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # 2.3.11 (April 7, 2022)
2
+
3
+ ## Enhancements:
4
+
5
+ - Bump actions/checkout to 3 in bundler gem template [#5445](https://github.com/rubygems/rubygems/pull/5445)
6
+ - Prefer `__dir__` to `__FILE__` [#5444](https://github.com/rubygems/rubygems/pull/5444)
7
+
8
+ ## Documentation:
9
+
10
+ - Update bundler documentation to reflect bundle config scope changes [#5441](https://github.com/rubygems/rubygems/pull/5441)
11
+
1
12
  # 2.3.10 (March 23, 2022)
2
13
 
3
14
  ## Enhancements:
data/bundler/exe/bundler CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- load File.expand_path("../bundle", __FILE__)
4
+ load File.expand_path("bundle", __dir__)
@@ -4,8 +4,8 @@ module Bundler
4
4
  # Represents metadata from when the Bundler gem was built.
5
5
  module BuildMetadata
6
6
  # begin ivars
7
- @built_at = "2022-03-23".freeze
8
- @git_commit_sha = "4bbb70e7de".freeze
7
+ @built_at = "2022-04-07".freeze
8
+ @git_commit_sha = "9b6c5a801a".freeze
9
9
  @release = true
10
10
  # end ivars
11
11
 
@@ -29,7 +29,7 @@ module Bundler
29
29
 
30
30
  # If Bundler has been installed without its .git directory and without a
31
31
  # commit instance variable then we can't determine its commits SHA.
32
- git_dir = File.join(File.expand_path("../../../..", __FILE__), ".git")
32
+ git_dir = File.expand_path("../../../.git", __dir__)
33
33
  if File.directory?(git_dir)
34
34
  return @git_commit_sha = Dir.chdir(git_dir) { `git rev-parse --short HEAD`.strip.freeze }
35
35
  end
@@ -47,7 +47,7 @@ module Bundler
47
47
  def print_gem_path(spec)
48
48
  name = spec.name
49
49
  if name == "bundler"
50
- path = File.expand_path("../../../..", __FILE__)
50
+ path = File.expand_path("../../..", __dir__)
51
51
  else
52
52
  path = spec.full_gem_path
53
53
  if spec.deleted_gem?
@@ -32,7 +32,7 @@ module Bundler
32
32
  file << spec.to_gemfile
33
33
  end
34
34
  else
35
- FileUtils.cp(File.expand_path("../../templates/#{gemfile}", __FILE__), gemfile)
35
+ FileUtils.cp(File.expand_path("../templates/#{gemfile}", __dir__), gemfile)
36
36
  end
37
37
 
38
38
  puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}"
@@ -18,7 +18,7 @@ module Bundler
18
18
 
19
19
  if gem_name
20
20
  if gem_name == "bundler"
21
- path = File.expand_path("../../../..", __FILE__)
21
+ path = File.expand_path("../../..", __dir__)
22
22
  else
23
23
  spec = Bundler::CLI::Common.select_spec(gem_name, :regex_match)
24
24
  return unless spec
@@ -610,7 +610,7 @@ module Bundler
610
610
  private :gem
611
611
 
612
612
  def self.source_root
613
- File.expand_path(File.join(File.dirname(__FILE__), "templates"))
613
+ File.expand_path("templates", __dir__)
614
614
  end
615
615
 
616
616
  desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory", :hide => true
@@ -119,7 +119,7 @@ module Bundler
119
119
  relative_gemfile_path = relative_gemfile_path
120
120
  ruby_command = Thor::Util.ruby_command
121
121
  ruby_command = ruby_command
122
- template_path = File.expand_path("../templates/Executable", __FILE__)
122
+ template_path = File.expand_path("templates/Executable", __dir__)
123
123
  if spec.name == "bundler"
124
124
  template_path += ".bundler"
125
125
  spec.executables = %(bundle)
@@ -172,7 +172,7 @@ module Bundler
172
172
  end
173
173
  standalone_path = Bundler.root.join(path).relative_path_from(bin_path)
174
174
  standalone_path = standalone_path
175
- template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
175
+ template = File.read(File.expand_path("templates/Executable.standalone", __dir__))
176
176
  ruby_command = Thor::Util.ruby_command
177
177
  ruby_command = ruby_command
178
178
 
@@ -36,13 +36,13 @@ Executing \fBbundle config list\fR with will print a list of all bundler configu
36
36
  Executing \fBbundle config get <name>\fR will print the value of that configuration setting, and where it was set\.
37
37
  .
38
38
  .P
39
- Executing \fBbundle config set <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
39
+ Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\.
40
40
  .
41
41
  .P
42
- Executing \fBbundle config set \-\-global <name> <value>\fR works the same as above\.
42
+ Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB<project_root>/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\.
43
43
  .
44
44
  .P
45
- Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB<project_root>/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\.
45
+ Executing \fBbundle config set \-\-global <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
46
46
  .
47
47
  .P
48
48
  Executing \fBbundle config unset <name>\fR will delete the configuration in both local and global sources\.
@@ -23,18 +23,20 @@ was set.
23
23
  Executing `bundle config get <name>` will print the value of that configuration
24
24
  setting, and where it was set.
25
25
 
26
- Executing `bundle config set <name> <value>` will set that configuration to the
27
- value specified for all bundles executed as the current user. The configuration
28
- will be stored in `~/.bundle/config`. If <name> already is set, <name> will be
29
- overridden and user will be warned.
30
-
31
- Executing `bundle config set --global <name> <value>` works the same as above.
26
+ Executing `bundle config set <name> <value>` defaults to setting `local`
27
+ configuration if executing from within a local application, otherwise it will
28
+ set `global` configuration. See `--local` and `--global` options below.
32
29
 
33
30
  Executing `bundle config set --local <name> <value>` will set that configuration
34
31
  in the directory for the local application. The configuration will be stored in
35
32
  `<project_root>/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration
36
33
  will be stored in `$BUNDLE_APP_CONFIG/config`.
37
34
 
35
+ Executing `bundle config set --global <name> <value>` will set that
36
+ configuration to the value specified for all bundles executed as the current
37
+ user. The configuration will be stored in `~/.bundle/config`. If <name> already
38
+ is set, <name> will be overridden and user will be warned.
39
+
38
40
  Executing `bundle config unset <name>` will delete the configuration in both
39
41
  local and global sources.
40
42
 
@@ -274,10 +274,10 @@ module Bundler
274
274
 
275
275
  def set_bundle_variables
276
276
  # bundler exe & lib folders have same root folder, typical gem installation
277
- exe_file = File.expand_path("../../../exe/bundle", __FILE__)
277
+ exe_file = File.expand_path("../../exe/bundle", __dir__)
278
278
 
279
279
  # for Ruby core repository testing
280
- exe_file = File.expand_path("../../../libexec/bundle", __FILE__) unless File.exist?(exe_file)
280
+ exe_file = File.expand_path("../../libexec/bundle", __dir__) unless File.exist?(exe_file)
281
281
 
282
282
  # bundler is a default gem, exe path is separate
283
283
  exe_file = Bundler.rubygems.bin_path("bundler", "bundle", VERSION) unless File.exist?(exe_file)
@@ -309,7 +309,7 @@ module Bundler
309
309
  end
310
310
 
311
311
  def bundler_ruby_lib
312
- resolve_path File.expand_path("../..", __FILE__)
312
+ File.expand_path("..", __dir__)
313
313
  end
314
314
 
315
315
  def clean_load_path
@@ -325,7 +325,7 @@ module Bundler
325
325
 
326
326
  def resolve_path(path)
327
327
  expanded = File.expand_path(path)
328
- return expanded unless File.respond_to?(:realpath) && File.exist?(expanded)
328
+ return expanded unless File.exist?(expanded)
329
329
 
330
330
  File.realpath(expanded)
331
331
  end
@@ -22,7 +22,7 @@ module Bundler
22
22
  s.summary = "The best way to manage your application's dependencies"
23
23
  s.executables = %w[bundle]
24
24
  # can't point to the actual gemspec or else the require paths will be wrong
25
- s.loaded_from = File.expand_path("..", __FILE__)
25
+ s.loaded_from = __dir__
26
26
  end
27
27
 
28
28
  if local_spec = Bundler.rubygems.find_bundler(VERSION)
@@ -8,11 +8,9 @@
8
8
  # this file is here to facilitate running it.
9
9
  #
10
10
 
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
13
- Pathname.new(__FILE__).realpath)
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("<%= relative_gemfile_path %>", __dir__)
14
12
 
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
16
14
 
17
15
  if File.file?(bundle_binstub)
18
16
  if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
@@ -41,7 +41,7 @@ m = Module.new do
41
41
  gemfile = ENV["BUNDLE_GEMFILE"]
42
42
  return gemfile if gemfile && !gemfile.empty?
43
43
 
44
- File.expand_path("../<%= relative_gemfile_path %>", __FILE__)
44
+ File.expand_path("<%= relative_gemfile_path %>", __dir__)
45
45
  end
46
46
 
47
47
  def lockfile
@@ -6,9 +6,7 @@
6
6
  # this file is here to facilitate running it.
7
7
  #
8
8
 
9
- require "pathname"
10
- path = Pathname.new(__FILE__)
11
- $:.unshift File.expand_path "../<%= standalone_path %>", path.realpath
9
+ $:.unshift File.expand_path "<%= standalone_path %>", __dir__
12
10
 
13
11
  require "bundler/setup"
14
- load File.expand_path "../<%= executable_path %>", path.realpath
12
+ load File.expand_path "<%= executable_path %>", __dir__
@@ -17,7 +17,7 @@ jobs:
17
17
  - '<%= RUBY_VERSION %>'
18
18
 
19
19
  steps:
20
- - uses: actions/checkout@v2
20
+ - uses: actions/checkout@v3
21
21
  - name: Set up Ruby
22
22
  uses: ruby/setup-ruby@v1
23
23
  with:
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  # Specify which files should be added to the gem when it is released.
26
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
+ spec.files = Dir.chdir(__dir__) do
28
28
  `git ls-files -z`.split("\x0").reject do |f|
29
29
  (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
30
30
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.3.10".freeze
4
+ VERSION = "2.3.11".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
@@ -370,7 +370,7 @@ EOF
370
370
 
371
371
  if env.key?("RUBYLIB")
372
372
  rubylib = env["RUBYLIB"].split(File::PATH_SEPARATOR)
373
- rubylib.delete(File.expand_path("..", __FILE__))
373
+ rubylib.delete(__dir__)
374
374
  env["RUBYLIB"] = rubylib.join(File::PATH_SEPARATOR)
375
375
  end
376
376
 
@@ -341,7 +341,7 @@ By default, this RubyGems will install gem as:
341
341
 
342
342
  fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION
343
343
  def fake_spec.full_gem_path
344
- File.expand_path '../../../..', __FILE__
344
+ File.expand_path '../../..', __dir__
345
345
  end
346
346
 
347
347
  generate_ri = options[:document].include? 'ri'
@@ -123,6 +123,9 @@ class Gem::Ext::Builder
123
123
  Gem::Ext::RakeBuilder
124
124
  when /CMakeLists.txt/ then
125
125
  Gem::Ext::CmakeBuilder
126
+ when /Cargo.toml/ then
127
+ # We use the spec name here to ensure we invoke the correct init function later
128
+ Gem::Ext::CargoBuilder.new(@spec)
126
129
  else
127
130
  build_error("No builder for extension '#{extension}'")
128
131
  end
@@ -0,0 +1,305 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This class is used by rubygems to build Rust extensions. It is a thin-wrapper
4
+ # over the `cargo rustc` command which takes care of building Rust code in a way
5
+ # that Ruby can use.
6
+ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
7
+ attr_reader :spec
8
+
9
+ def initialize(spec)
10
+ @spec = spec
11
+ end
12
+
13
+ def build(_extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd)
14
+ require "rubygems/command"
15
+ require "fileutils"
16
+ require "shellwords"
17
+
18
+ build_crate(dest_path, results, args, cargo_dir)
19
+ ext_path = rename_cdylib_for_ruby_compatibility(dest_path)
20
+ finalize_directory(ext_path, dest_path, lib_dir, cargo_dir)
21
+ results
22
+ end
23
+
24
+ private
25
+
26
+ def build_crate(dest_path, results, args, cargo_dir)
27
+ manifest = File.join(cargo_dir, "Cargo.toml")
28
+
29
+ given_ruby_static = ENV["RUBY_STATIC"]
30
+
31
+ ENV["RUBY_STATIC"] = "true" if ruby_static? && !given_ruby_static
32
+
33
+ cargo = ENV.fetch("CARGO", "cargo")
34
+
35
+ cmd = []
36
+ cmd += [cargo, "rustc"]
37
+ cmd += ["--target-dir", dest_path]
38
+ cmd += ["--manifest-path", manifest]
39
+ cmd += ["--lib", "--release", "--locked"]
40
+ cmd += ["--"]
41
+ cmd += [*cargo_rustc_args(dest_path)]
42
+ cmd += Gem::Command.build_args
43
+ cmd += args
44
+
45
+ self.class.run cmd, results, self.class.class_name, cargo_dir
46
+ results
47
+ ensure
48
+ ENV["RUBY_STATIC"] = given_ruby_static
49
+ end
50
+
51
+ def cargo_rustc_args(dest_dir)
52
+ [
53
+ *linker_args,
54
+ *mkmf_libpath,
55
+ *rustc_dynamic_linker_flags(dest_dir),
56
+ *rustc_lib_flags(dest_dir),
57
+ *platform_specific_rustc_args(dest_dir),
58
+ *debug_flags,
59
+ ]
60
+ end
61
+
62
+ def platform_specific_rustc_args(dest_dir, flags = [])
63
+ if mingw_target?
64
+ # On mingw platforms, mkmf adds libruby to the linker flags
65
+ flags += libruby_args(dest_dir)
66
+
67
+ # Make sure ALSR is used on mingw
68
+ # see https://github.com/rust-lang/rust/pull/75406/files
69
+ flags += ["-C", "link-arg=-Wl,--dynamicbase"]
70
+ flags += ["-C", "link-arg=-Wl,--disable-auto-image-base"]
71
+
72
+ # If the gem is installed on a host with build tools installed, but is
73
+ # run on one that isn't the missing libraries will cause the extension
74
+ # to fail on start.
75
+ flags += ["-C", "link-arg=-static-libgcc"]
76
+ end
77
+
78
+ flags
79
+ end
80
+
81
+ # We want to use the same linker that Ruby uses, so that the linker flags from
82
+ # mkmf work properly.
83
+ def linker_args
84
+ # Have to handle CC="cl /nologo" on mswin
85
+ cc_flag = Shellwords.split(makefile_config("CC"))
86
+ linker = cc_flag.shift
87
+ link_args = cc_flag.flat_map {|a| ["-C", "link-arg=#{a}"] }
88
+
89
+ ["-C", "linker=#{linker}", *link_args]
90
+ end
91
+
92
+ def libruby_args(dest_dir)
93
+ libs = makefile_config(ruby_static? ? "LIBRUBYARG_STATIC" : "LIBRUBYARG_SHARED")
94
+ raw_libs = Shellwords.split(libs)
95
+ raw_libs.flat_map {|l| ldflag_to_link_modifier(l, dest_dir) }
96
+ end
97
+
98
+ def ruby_static?
99
+ return true if %w[1 true].include?(ENV["RUBY_STATIC"])
100
+
101
+ makefile_config("ENABLE_SHARED") == "no"
102
+ end
103
+
104
+ # Ruby expects the dylib to follow a file name convention for loading
105
+ def rename_cdylib_for_ruby_compatibility(dest_path)
106
+ dylib_path = validate_cargo_build!(dest_path)
107
+ dlext_name = "#{spec.name}.#{makefile_config("DLEXT")}"
108
+ new_name = dylib_path.gsub(File.basename(dylib_path), dlext_name)
109
+ FileUtils.cp(dylib_path, new_name)
110
+ new_name
111
+ end
112
+
113
+ def validate_cargo_build!(dir)
114
+ prefix = so_ext == "dll" ? "" : "lib"
115
+ dylib_path = File.join(dir, "release", "#{prefix}#{cargo_crate_name}.#{so_ext}")
116
+
117
+ raise DylibNotFoundError, dir unless File.exist?(dylib_path)
118
+
119
+ dylib_path
120
+ end
121
+
122
+ def cargo_crate_name
123
+ spec.metadata.fetch('cargo_crate_name', spec.name).tr('-', '_')
124
+ end
125
+
126
+ def rustc_dynamic_linker_flags(dest_dir)
127
+ split_flags("DLDFLAGS")
128
+ .map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir) }
129
+ .compact
130
+ .flat_map {|arg| ldflag_to_link_modifier(arg, dest_dir) }
131
+ end
132
+
133
+ def rustc_lib_flags(dest_dir)
134
+ split_flags("LIBS").flat_map {|arg| ldflag_to_link_modifier(arg, dest_dir) }
135
+ end
136
+
137
+ def split_flags(var)
138
+ Shellwords.split(RbConfig::CONFIG.fetch(var, ""))
139
+ end
140
+
141
+ def ldflag_to_link_modifier(arg, dest_dir)
142
+ flag = arg[0..1]
143
+ val = arg[2..-1]
144
+
145
+ case flag
146
+ when "-L" then ["-L", "native=#{val}"]
147
+ when "-l" then ["-l", val.to_s]
148
+ when "-F" then ["-l", "framework=#{val}"]
149
+ else ["-C", "link_arg=#{arg}"]
150
+ end
151
+ end
152
+
153
+ def link_flag(link_name)
154
+ # These are provided by the CRT with MSVC
155
+ # @see https://github.com/rust-lang/pkg-config-rs/blob/49a4ac189aafa365167c72e8e503565a7c2697c2/src/lib.rs#L622
156
+ return [] if msvc_target? && ["m", "c", "pthread"].include?(link_name)
157
+
158
+ if link_name.include?("ruby")
159
+ # Specify the lib kind and give it the name "ruby" for linking
160
+ kind = ruby_static? ? "static" : "dylib"
161
+
162
+ ["-l", "#{kind}=ruby:#{link_name}"]
163
+ else
164
+ ["-l", link_name]
165
+ end
166
+ end
167
+
168
+ def msvc_target?
169
+ makefile_config("target_os").include?("msvc")
170
+ end
171
+
172
+ def darwin_target?
173
+ makefile_config("target_os").include?("darwin")
174
+ end
175
+
176
+ def mingw_target?
177
+ makefile_config("target_os").include?("mingw")
178
+ end
179
+
180
+ def win_target?
181
+ target_platform = RbConfig::CONFIG["target_os"]
182
+ !!Gem::WIN_PATTERNS.find {|r| target_platform =~ r }
183
+ end
184
+
185
+ # Intepolate substition vars in the arg (i.e. $(DEFFILE))
186
+ def maybe_resolve_ldflag_variable(input_arg, dest_dir)
187
+ str = input_arg.gsub(/\$\((\w+)\)/) do |var_name|
188
+ case var_name
189
+ # On windows, it is assumed that mkmf has setup an exports file for the
190
+ # extension, so we have to to create one ourselves.
191
+ when "DEFFILE"
192
+ write_deffile(dest_dir)
193
+ else
194
+ RbConfig::CONFIG[var_name]
195
+ end
196
+ end.strip
197
+
198
+ str == "" ? nil : str
199
+ end
200
+
201
+ def write_deffile(dest_dir)
202
+ deffile_path = File.join(dest_dir, "#{spec.name}-#{RbConfig::CONFIG["arch"]}.def")
203
+ export_prefix = makefile_config("EXPORT_PREFIX") || ""
204
+
205
+ File.open(deffile_path, "w") do |f|
206
+ f.puts "EXPORTS"
207
+ f.puts "#{export_prefix.strip}Init_#{spec.name}"
208
+ end
209
+
210
+ deffile_path
211
+ end
212
+
213
+ # We have to basically reimplement RbConfig::CONFIG['SOEXT'] here to support
214
+ # Ruby < 2.5
215
+ #
216
+ # @see https://github.com/ruby/ruby/blob/c87c027f18c005460746a74c07cd80ee355b16e4/configure.ac#L3185
217
+ def so_ext
218
+ return RbConfig::CONFIG["SOEXT"] if RbConfig::CONFIG.key?("SOEXT")
219
+
220
+ if win_target?
221
+ "dll"
222
+ elsif darwin_target?
223
+ "dylib"
224
+ else
225
+ "so"
226
+ end
227
+ end
228
+
229
+ # Corresponds to $(LIBPATH) in mkmf
230
+ def mkmf_libpath
231
+ ["-L", "native=#{makefile_config("libdir")}"]
232
+ end
233
+
234
+ def makefile_config(var_name)
235
+ val = RbConfig::MAKEFILE_CONFIG[var_name]
236
+
237
+ return unless val
238
+
239
+ RbConfig.expand(val.dup)
240
+ end
241
+
242
+ # Good balance between binary size and debugability
243
+ def debug_flags
244
+ ["-C", "debuginfo=1"]
245
+ end
246
+
247
+ # Copied from ExtConfBuilder
248
+ def finalize_directory(ext_path, dest_path, lib_dir, extension_dir)
249
+ require "fileutils"
250
+ require "tempfile"
251
+
252
+ begin
253
+ tmp_dest = Dir.mktmpdir(".gem.", extension_dir)
254
+
255
+ # Some versions of `mktmpdir` return absolute paths, which will break make
256
+ # if the paths contain spaces. However, on Ruby 1.9.x on Windows, relative
257
+ # paths cause all C extension builds to fail.
258
+ #
259
+ # As such, we convert to a relative path unless we are using Ruby 1.9.x on
260
+ # Windows. This means that when using Ruby 1.9.x on Windows, paths with
261
+ # spaces do not work.
262
+ #
263
+ # Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940
264
+ tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir)
265
+
266
+ if tmp_dest_relative
267
+ full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
268
+
269
+ # TODO: remove in RubyGems 3
270
+ if Gem.install_extension_in_lib && lib_dir
271
+ FileUtils.mkdir_p lib_dir
272
+ FileUtils.cp_r ext_path, lib_dir, remove_destination: true
273
+ end
274
+
275
+ FileUtils::Entry_.new(full_tmp_dest).traverse do |ent|
276
+ destent = ent.class.new(dest_path, ent.rel)
277
+ destent.exist? || FileUtils.mv(ent.path, destent.path)
278
+ end
279
+ end
280
+ ensure
281
+ FileUtils.rm_rf tmp_dest if tmp_dest
282
+ end
283
+ end
284
+
285
+ def get_relative_path(path, base)
286
+ path[0..base.length - 1] = "." if path.start_with?(base)
287
+ path
288
+ end
289
+
290
+ # Error raised when no cdylib artifact was created
291
+ class DylibNotFoundError < StandardError
292
+ def initialize(dir)
293
+ files = Dir.glob(File.join(dir, "**", "*")).map {|f| "- #{f}" }.join "\n"
294
+
295
+ super <<~MSG
296
+ Dynamic library not found for Rust extension (in #{dir})
297
+
298
+ Make sure you set "crate-type" in Cargo.toml to "cdylib"
299
+
300
+ Found files:
301
+ #{files}
302
+ MSG
303
+ end
304
+ end
305
+ end