rb_sys 0.9.59 → 0.9.61

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d0c1e0630a88954cda754dbb7db45842203cacd6fd265ea75a0424989d66e34
4
- data.tar.gz: 94d12fe7fe913ffb00ac9343a3ab594e3701d82f99fda2ab99a79e654bd4259e
3
+ metadata.gz: 123a974ae1143185fe76488a7869cb2c388046c72c07ea774b9d6ef04d76ac3d
4
+ data.tar.gz: fbb7fe655195f3afac258f93df6a43ecb414faa1697140500afc09153872654d
5
5
  SHA512:
6
- metadata.gz: 618d433d7992df2fab66bdeb03204d0e699a4594881bc48bd61a4c5359b94eb25f26fd0eb9f2cd57038d4130c125383069267e125edc92d5761ef920ae3a6d87
7
- data.tar.gz: 1d6aa9c2039dffc0093bed770be24703f88ec95164ad87d24913e1889e9697206a1ef461e405f57ef1b56e02f505b7dc86e36839d8df7a1f972aa8973b94b186
6
+ metadata.gz: 114714eacc8d7bd88e7fe2169d5b4356d39add07f44148650805af0e6212de154fddc5464ec7c23847b5632c1474513e83b4dfd30d15eb28ff1218c222c122aa
7
+ data.tar.gz: 0d6933769276e790671ab4717a756a874045c7a037eaac4220fb5a89c56798006461b3fd5d5cc99096eed05e56bfda9f553ca4fbfb71c946f986d20a13018b28
checksums.yaml.gz.sig CHANGED
@@ -1 +1,3 @@
1
- 8�y/���$�\���͟��G�ߎdQ* ۈ����:6!G��Z#�&wl��G��6_��� ��������GwcIP:J��׿���Ӯ�2#��ڇ9!)/}F(Zupj�i�?gO�������\d'q���w[��آ 8�B�8�t��c�`Y�<+��YK~��e�I֗2����u���Q��b��R]|m�@\���� R�p���Vᄃ��ͅ��HZG[����ߍa��n�M1� S������
1
+ z9RbR4]f=!�Yκ�Cm_ZO,��ͣ�FD���ޘm��u��$3����[�!L3.1��7"Q�4��y�$f̓
2
+ �T�UF�!Ȓ�yF�S)��x�����.��{���O2���
3
+ t5�g��=K��Ïvķz vD#�J_e��N�q�4�ǻsC1=�;�J�T�Z�W����E?Ӎ%�����컜4<Х.�)քڀK߀��㭭�l2ݪ�b�+1�Q1d��n�_����Խo�~]D3Dx��.�BM�z�
data/exe/rb-sys-dock CHANGED
@@ -4,6 +4,7 @@ require "optparse"
4
4
  require "rb_sys/version"
5
5
  require "rb_sys/toolchain_info"
6
6
  require "fileutils"
7
+ require "tmpdir"
7
8
 
8
9
  options = {
9
10
  version: RbSys::VERSION
@@ -101,6 +102,7 @@ OptionParser.new do |opts|
101
102
  opts.on("--latest", "Use the latest version of the Docker image") do
102
103
  log(:notice, "Using latest version of the Docker image", emoji: "🆕")
103
104
  options[:version] = "latest"
105
+ options[:no_cache] = true
104
106
  end
105
107
 
106
108
  opts.on("--list-platforms", "--list", "List all supported platforms") do
@@ -113,6 +115,18 @@ OptionParser.new do |opts|
113
115
  exit(0)
114
116
  end
115
117
 
118
+ opts.on("--ruby-versions LIST", "List all supported Ruby versions") do |arg|
119
+ log(:notice, "Requested Ruby versions: #{arg}")
120
+
121
+ vers = arg.split(/[^0-9.]/).map do |v|
122
+ parts = v.split(".")
123
+ parts[2] = "0" if parts[2].nil?
124
+ parts.join(".")
125
+ end
126
+
127
+ ENV["RUBY_CC_VERSION"] = vers.join(":")
128
+ end
129
+
116
130
  opts.on("-h", "--help", "Prints this help") do
117
131
  puts opts
118
132
  exit
@@ -123,6 +137,10 @@ OptionParser.new do |opts|
123
137
  ENV["VERBOSE"] = "1"
124
138
  options[:verbose] = true
125
139
  end
140
+
141
+ opts.on("--build", "Build the Docker image") do
142
+ options[:build] = true
143
+ end
126
144
  end.parse!
127
145
 
128
146
  def determine_cache_dir
@@ -160,48 +178,91 @@ def mount_cargo_registry
160
178
  "--mount type=bind,source=#{File.join(local_registry_dir, dir)},target=#{File.join("/usr/local/cargo", dir)},readonly=false"
161
179
  end
162
180
 
163
- def mount_bundle_cache(options, extra_env)
164
- dir = File.join(cache_dir, options.fetch(:platform), "bundle")
181
+ def volume(src, dest, mode: "rw")
182
+ "--volume #{src}:#{dest}:rw"
183
+ end
184
+
185
+ def mount_bundle_cache(options)
186
+ dir = File.join(cache_dir, options.fetch(:toolchain_info).platform, "bundle")
187
+ bundle_path = File.join(docker_tmp, "bundle")
165
188
  FileUtils.mkdir_p(dir)
166
189
  log(:trace, "Mounting bundle cache: #{dir}")
167
- "-v #{dir}:#{File.join(docker_tmp, "bundle")}"
190
+
191
+ "#{volume(dir, bundle_path)} -e BUNDLE_PATH=#{bundle_path.inspect}"
168
192
  end
169
193
 
170
- def mount_target_dir(options, _extra_env)
171
- tmp_target_dir = File.join(Dir.pwd, "tmp", "rb-sys-dock", options[:platform], "target")
172
- FileUtils.mkdir_p(tmp_target_dir)
173
- "-v #{tmp_target_dir}:#{File.join(Dir.pwd, "target")}"
194
+ def tmp_target_dir(options)
195
+ return @tmp_target_dir if defined?(@tmp_target_dir)
196
+
197
+ dir = File.join(Dir.pwd, "tmp", "rb-sys-dock", options.fetch(:toolchain_info).platform, "target")
198
+ FileUtils.mkdir_p(dir)
199
+ @tmp_target_dir = dir
200
+ end
201
+
202
+ def mount_target_dir(options)
203
+ "-v #{tmp_target_dir(options)}:#{File.join(Dir.pwd, "target")}"
174
204
  end
175
205
 
176
206
  def mount_command_history(options)
177
207
  return unless $stdin.tty?
178
208
 
179
209
  history_dir = File.join(cache_dir, options.fetch(:platform), "commandhistory")
210
+ FileUtils.mkdir_p(history_dir)
180
211
  "-v #{history_dir}:#{File.join(docker_tmp, "commandhistory")}"
181
212
  end
182
213
 
214
+ def default_command_to_run(input_args, options)
215
+ input_cmd = input_args.empty? ? "true" : input_args.join(" ")
216
+
217
+ if options[:build]
218
+ with_bundle = +"test -f Gemfile && bundle install && #{input_cmd} && bundle exec rake native:$RUBY_TARGET gem"
219
+ without_bundle = "#{input_cmd} && rake native:$RUBY_TARGET gem"
220
+ log(:notice, "Running default build command:")
221
+ log(:notice, " $ rake native:#{options[:toolchain_info].platform} gem")
222
+ "bash -c '(#{with_bundle}) || (#{without_bundle})'"
223
+ else
224
+ input_args.empty? ? "bash" : "bash -c '#{input_args.join(" ")}'"
225
+ end
226
+ end
227
+
228
+ def uid_gid
229
+ if /darwin/.match?(RbConfig::CONFIG["host_os"])
230
+ ["1000", "1000"]
231
+ else
232
+ [Process.uid, Process.gid]
233
+ end
234
+ end
235
+
236
+ def user_mapping
237
+ uid, gid = uid_gid
238
+ "-e UID=#{uid} -e GID=#{gid} -e GROUP=_staff -e USER=rb-sys-dock"
239
+ end
240
+
241
+ def interactive?(input_args)
242
+ $stdin.tty?
243
+ end
244
+
245
+ def mount_tmp_dir(options)
246
+ "--mount type=bind,source=#{Dir.mktmpdir},destination=#{Dir.pwd}/tmp/#{options.fetch(:toolchain_info).platform},readonly=false"
247
+ end
248
+
183
249
  def rcd(input_args, options)
184
250
  wrapper_command = []
185
- wrapper_command << "sigfw" unless $stdin.tty?
251
+ wrapper_command << "sigfw" unless interactive?(input_args)
186
252
  wrapper_command << "runas"
187
253
 
188
- extra_env = []
189
-
190
254
  docker_options = []
191
- docker_options << "--tty" if $stdin.tty?
192
- cmd = input_args.empty? ? "bash" : "bash -c '#{input_args.join(" ")}'"
255
+ docker_options << "--tty" if interactive?(input_args)
193
256
 
194
257
  cmd = <<~SH
195
258
  #{default_docker_command} run \
196
259
  -v #{Dir.pwd}:#{Dir.pwd} \
197
- #{mount_target_dir(options, extra_env)} \
260
+ #{mount_tmp_dir(options)} \
261
+ #{mount_target_dir(options)} \
198
262
  #{mount_cargo_registry} \
199
- #{mount_bundle_cache(options, extra_env)} \
263
+ #{mount_bundle_cache(options)} \
200
264
  #{mount_command_history(options)} \
201
- -e UID=#{ENV.fetch("RB_SYS_DOCK_UID", "1000")} \
202
- -e GID=#{ENV.fetch("RB_SYS_DOCK_GID", "1000")} \
203
- -e USER=rb-sys-dock \
204
- -e GROUP=_staff \
265
+ #{user_mapping} \
205
266
  -e GEM_PRIVATE_KEY_PASSPHRASE \
206
267
  -e ftp_proxy \
207
268
  -e http_proxy \
@@ -209,14 +270,19 @@ def rcd(input_args, options)
209
270
  -e RCD_HOST_RUBY_PLATFORM=#{RbConfig::CONFIG["arch"]} \
210
271
  -e RCD_HOST_RUBY_VERSION=#{RUBY_VERSION} \
211
272
  -e RCD_IMAGE \
273
+ -e RB_SYS_DOCK_TMPDIR="/tmp/rb-sys-dock" \
274
+ -e RB_SYS_CARGO_TARGET_DIR=#{tmp_target_dir(options).inspect} \
275
+ #{ENV["RUBY_CC_VERSION"] ? "-e RUBY_CC_VERSION=#{ENV["RUBY_CC_VERSION"]}" : ""} \
276
+ -e RAKEOPT \
212
277
  -e TERM \
278
+ -e LC_ALL=#{ENV.fetch("LC_ALL", "en_US.UTF-8")} \
213
279
  -w #{Dir.pwd} \
214
280
  --rm \
215
281
  --interactive \
216
282
  #{docker_options.join(" ")} \
217
283
  #{ENV.fetch("RCD_IMAGE")} \
218
284
  #{wrapper_command.join(" ")} \
219
- #{cmd}
285
+ #{default_command_to_run(input_args, options)}
220
286
  SH
221
287
 
222
288
  log(:trace, "Running command: $ #{cmd}")
@@ -224,10 +290,10 @@ def rcd(input_args, options)
224
290
  exec(cmd)
225
291
  end
226
292
 
227
- def download_image(_options)
293
+ def download_image(options)
228
294
  image = ENV.fetch("RCD_IMAGE")
229
295
 
230
- if docker("images -q #{image}").strip.empty?
296
+ if docker("images -q #{image}").strip.empty? || options[:no_cache]
231
297
  # Nicely formatted message that we are downloading the image which might take awhile
232
298
  log(:notice, "Downloading container #{image.inspect}, this might take awhile...")
233
299
  docker("pull #{image} --quiet > /dev/null")
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+ require "psych"
5
+
6
+ module RbSys
7
+ module Cargo
8
+ # Extracts metadata from a Cargo project using `cargo metadata`.
9
+ class Metadata
10
+ attr_reader :name
11
+
12
+ def initialize(name)
13
+ raise ArgumentError, "name must be a String" unless name.is_a?(String)
14
+
15
+ @name = name
16
+ end
17
+
18
+ # @api private
19
+ def self.delegates_to_cargo_metadata(*methods)
20
+ methods.each do |method|
21
+ define_method(method) { cargo_metadata.fetch(method.to_s) }
22
+ end
23
+ end
24
+
25
+ # @api private
26
+ def self.delegates_to_package_metadata(*methods)
27
+ methods.each do |method|
28
+ define_method(method) { package_metadata.fetch(method.to_s) }
29
+ end
30
+ end
31
+
32
+ delegates_to_cargo_metadata :target_directory, :workspace_root, :packages
33
+
34
+ delegates_to_package_metadata :manifest_path, :version, :id, :edition, :targets, :features, :metadata
35
+
36
+ # Returns the path where the Cargo project's Cargo.toml is located.
37
+ #
38
+ # @return [String]
39
+ def manifest_directory
40
+ @manifest_directory ||= File.dirname(manifest_path)
41
+ end
42
+
43
+ private
44
+
45
+ def package_metadata
46
+ return @package_metadata if @package_metadata
47
+
48
+ found = cargo_metadata.fetch("packages").find { |p| p.fetch("name") == name }
49
+ raise PackageNotFoundError, @name unless found
50
+ @package_metadata = found
51
+ end
52
+
53
+ def cargo_metadata
54
+ return @cargo_metadata if @cargo_metadata
55
+
56
+ ::Gem.load_yaml
57
+ cargo = ENV["CARGO"] || "cargo"
58
+ args = ["metadata", "--no-deps", "--format-version", "1"]
59
+ out, stderr, _status = Open3.capture3(cargo, *args)
60
+ @cargo_metadata = Gem::SafeYAML.safe_load(out)
61
+ rescue => err
62
+ raise CargoMetadataError.new(err, stderr, manifest_path)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RbSys
4
+ # Helpers for Cargo
5
+ module Cargo
6
+ end
7
+ end
8
+
9
+ require_relative "cargo/metadata"
@@ -5,6 +5,7 @@ require "shellwords"
5
5
  module RbSys
6
6
  class CargoBuilder < Gem::Ext::Builder
7
7
  # Converts Ruby link flags into something cargo understands
8
+ # @api private
8
9
  class LinkFlagConverter
9
10
  FILTERED_PATTERNS = [
10
11
  /compress-debug-sections/, # Not supported by all linkers, and not required for Rust
@@ -4,6 +4,7 @@ require_relative "cargo_builder/link_flag_converter"
4
4
 
5
5
  module RbSys
6
6
  # A class to build a Ruby gem Cargo. Extracted from `rubygems` gem, with some modifications.
7
+ # @api private
7
8
  class CargoBuilder < Gem::Ext::Builder
8
9
  attr_accessor :spec, :runner, :env, :features, :target, :extra_rustc_args, :dry_run, :ext_dir, :extra_rustflags,
9
10
  :extra_cargo_args
@@ -22,7 +23,7 @@ module RbSys
22
23
  @extra_rustc_args = []
23
24
  @extra_cargo_args = []
24
25
  @dry_run = true
25
- @ext_dir = nil
26
+ @ext_dir = ""
26
27
  @extra_rustflags = []
27
28
  end
28
29
 
@@ -57,16 +58,16 @@ module RbSys
57
58
  build_env.merge(env)
58
59
  end
59
60
 
60
- def cargo_command(dest_path, args = [])
61
- manifest = File.join(ext_dir, "Cargo.toml")
62
- cargo = ENV.fetch("CARGO", "cargo")
61
+ def manifest_dir
62
+ ext_dir
63
+ end
63
64
 
65
+ def cargo_command(dest_path, args = [])
64
66
  cmd = []
65
- cmd += [cargo, "rustc"]
67
+ cmd += ["cargo", "rustc"]
66
68
  cmd += ["--target", target] if target
67
69
  cmd += ["--target-dir", dest_path]
68
70
  cmd += ["--features", features.join(",")] unless features.empty?
69
- cmd += ["--manifest-path", manifest]
70
71
  cmd += ["--lib"]
71
72
  cmd += ["--profile", profile.to_s]
72
73
  cmd += Gem::Command.build_args
@@ -235,7 +236,7 @@ module RbSys
235
236
  !!Gem::WIN_PATTERNS.find { |r| target_platform =~ r }
236
237
  end
237
238
 
238
- # Interpolate substition vars in the arg (i.e. $(DEFFILE))
239
+ # Interpolate substition vars in the arg
239
240
  def maybe_resolve_ldflag_variable(input_arg, dest_dir)
240
241
  var_matches = input_arg.match(/\$\((\w+)\)/)
241
242
 
@@ -246,31 +247,13 @@ module RbSys
246
247
  return input_arg if var_name.nil? || var_name.chomp.empty?
247
248
 
248
249
  case var_name
249
- # On windows, it is assumed that mkmf has setup an exports file for the
250
- # extension, so we have to to create one ourselves.
251
250
  when "DEFFILE"
252
- write_deffile(dest_dir)
251
+ # DEFFILE already generated by cargo
253
252
  else
254
253
  RbConfig::CONFIG[var_name]
255
254
  end
256
255
  end
257
256
 
258
- def write_deffile(dest_path)
259
- deffile_path = File.join(dest_path, "#{spec.name}-#{RbConfig::CONFIG["arch"]}.def")
260
-
261
- unless dry_run
262
- FileUtils.mkdir_p(dest_dir)
263
- export_prefix = makefile_config("EXPORT_PREFIX") || ""
264
-
265
- File.open(deffile_path, "w") do |f|
266
- f.puts "EXPORTS"
267
- f.puts "#{export_prefix.strip}Init_#{spec.name}"
268
- end
269
- end
270
-
271
- deffile_path
272
- end
273
-
274
257
  # Corresponds to $(LIBPATH) in mkmf
275
258
  def mkmf_libpath
276
259
  ["-L", "native=#{makefile_config("libdir")}"]
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RbSys
4
+ # Error is the base class for all errors raised by rb_sys.
5
+ class Error < StandardError; end
6
+
7
+ # Raised when a package is not found from the Cargo metadata.
8
+ class PackageNotFoundError < Error
9
+ def initialize(name)
10
+ msg = <<~MSG.chomp.tr("\n", " ")
11
+ Could not find Cargo package metadata for #{@name.inspect}. Please
12
+ check that #{@name.inspect} matches the crate name in your
13
+ Cargo.toml."
14
+ MSG
15
+
16
+ super(msg)
17
+ end
18
+ end
19
+
20
+ # Raised when Cargo metadata cannot be parsed.
21
+ class CargoMetadataError < Error
22
+ def initialize(err, stderr, manifest_path)
23
+ msg = <<~MSG.chomp.tr("\n", " ")
24
+ Could not parse Cargo metadata. Please check that your Cargo.toml
25
+ is valid. The error was: #{err}
26
+
27
+ Looking for this Cargo.toml: #{manifest_path.inspect}
28
+
29
+ Stderr
30
+ ------
31
+ #{stderr}
32
+ MSG
33
+
34
+ super(msg)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,122 @@
1
+ require_relative "cargo/metadata"
2
+ require_relative "error"
3
+
4
+ begin
5
+ require "rake/extensiontask"
6
+ rescue LoadError
7
+ abort "Please install rake-compiler to use this gem"
8
+ end
9
+
10
+ module RbSys
11
+ # ExtensionTask is a Rake::ExtensionTask subclass that is used to tailored for
12
+ # Rust extensions. It has the same options a `Rake::ExtensionTask`.
13
+ #
14
+ # @see https://www.rubydoc.info/gems/rake-compiler/Rake/ExtensionTask
15
+ #
16
+ # @example
17
+ # RbSys::ExtensionTask.new("my-crate", my_gemspec) do |ext|
18
+ # ext.lib_dir = "lib/my-crate"
19
+ # end
20
+ #
21
+ # @param name [String] the crate name to build
22
+ # @param gem_spec [Gem::Specification] the gem specification to build (needed for cross-compiling)
23
+ # @return [Rake::ExtensionTask]
24
+ class ExtensionTask < Rake::ExtensionTask
25
+ def init(name = nil, gem_spec = nil)
26
+ super
27
+ @orginal_ext_dir = @ext_dir
28
+ @ext_dir = cargo_metadata.manifest_directory
29
+ @source_pattern = nil
30
+ @compiled_pattern = "*.{obj,so,bundle,dSYM}"
31
+ @cross_compile = ENV.key?("RUBY_TARGET")
32
+ @cross_platform = [ENV["RUBY_TARGET"]].compact
33
+ @cross_compiling_blocks = []
34
+ @cross_compiling_blocks << proc do |gemspec|
35
+ warn "Removing unneeded dependencies from native gemspec"
36
+ gemspec.dependencies.reject! { |d| d.name == "rb_sys" }
37
+ end
38
+ @cross_compiling_blocks << proc do |gemspec|
39
+ warn "Removing source files from native gemspec"
40
+ gemspec.files.reject! { |f| f.end_with?(".rs") }
41
+ gemspec.files.reject! { |f| f.match?(/Cargo.(toml|lock)$/) }
42
+ gemspec.files.reject! { |f| extconf.end_with?(f) }
43
+ end
44
+ end
45
+
46
+ def define
47
+ super
48
+ define_env_tasks
49
+ end
50
+
51
+ def cargo_metadata
52
+ @cargo_metadata ||= Cargo::Metadata.new(@name)
53
+ end
54
+
55
+ def extconf
56
+ File.join(cargo_metadata.manifest_directory, "extconf.rb")
57
+ end
58
+
59
+ def binary(_platf)
60
+ super.tr("-", "_")
61
+ end
62
+
63
+ # I'm not sure why this is necessary, can it be removed?
64
+ def source_files
65
+ list = FileList[
66
+ "#{ext_dir}/**/*.{rs,rb,c,h,toml}",
67
+ "**/Cargo.{toml,lock}",
68
+ "**/.cargo/**/*",
69
+ "#{ext_dir}/lib/**/*"
70
+ ]
71
+ list.include("#{ext_dir}/#{@source_pattern}") if @source_pattern
72
+ list.exclude(File.join(target_directory, "**/*"))
73
+ list
74
+ end
75
+
76
+ def cross_compiling(&block)
77
+ @cross_compiling_blocks << block if block
78
+ end
79
+
80
+ def target_directory
81
+ cargo_metadata.target_directory
82
+ end
83
+
84
+ def define_native_tasks(for_platform = nil, ruby_ver = RUBY_VERSION, callback = nil)
85
+ cb = proc do |gemspec|
86
+ callback&.call(gemspec)
87
+
88
+ @cross_compiling_blocks.each do |block|
89
+ block.call(gemspec)
90
+ end
91
+ end
92
+
93
+ super(for_platform, ruby_ver, cb)
94
+ end
95
+
96
+ def define_env_tasks
97
+ task "rb_sys:env:default" do
98
+ ENV["RB_SYS_CARGO_TARGET_DIR"] ||= target_directory
99
+ ENV["RB_SYS_CARGO_MANIFEST_DIR"] ||= cargo_metadata.manifest_directory
100
+ ENV["RB_SYS_CARGO_PROFILE"] ||= "release"
101
+ end
102
+
103
+ desc "Use the debug profile for building native Rust extensions"
104
+ task "rb_sys:env:dev" do
105
+ ENV["RB_SYS_CARGO_PROFILE"] = "dev"
106
+ end
107
+
108
+ desc "Use the release profile for building native Rust extensions"
109
+ task "rb_sys:env:release" do
110
+ ENV["RB_SYS_CARGO_PROFILE"] = "release"
111
+ end
112
+
113
+ file extconf => "rb_sys:env:default"
114
+
115
+ desc 'Compile the native Rust extension with the "dev" profile'
116
+ task "compile:dev" => ["rb_sys:env:dev", "compile"]
117
+
118
+ desc 'Compile the native Rust extension with the "release" profile'
119
+ task "compile:release" => ["rb_sys:env:release", "compile"]
120
+ end
121
+ end
122
+ end
@@ -4,7 +4,20 @@ module RbSys
4
4
  module Mkmf
5
5
  # Config that delegates to CargoBuilder if needded
6
6
  class Config
7
- attr_accessor :force_install_rust_toolchain, :clean_after_install, :target_dir, :auto_install_rust_toolchain, :rubygems_clean_dirs
7
+ # Force the installation of the Rust toolchain when building
8
+ attr_accessor :force_install_rust_toolchain
9
+
10
+ # Clean artifacts after install (default: true if invoked by Rubygems)
11
+ attr_accessor :clean_after_install
12
+
13
+ # Target directory for cargo artifacts
14
+ attr_accessor :target_dir
15
+
16
+ # Automatically install the Rust toolchain when building (default: true)
17
+ attr_accessor :auto_install_rust_toolchain
18
+
19
+ # Directories to clean after installing with Rubygems
20
+ attr_accessor :rubygems_clean_dirs
8
21
 
9
22
  def initialize(builder)
10
23
  @builder = builder
@@ -14,14 +27,17 @@ module RbSys
14
27
  @rubygems_clean_dirs = ["./cargo-vendor"]
15
28
  end
16
29
 
30
+ # @api private
17
31
  def cross_compiling?
18
32
  RbConfig::CONFIG["CROSS_COMPILING"] == "yes"
19
33
  end
20
34
 
35
+ # @api private
21
36
  def method_missing(name, *args, &blk)
22
37
  @builder.send(name, *args, &blk)
23
38
  end
24
39
 
40
+ # @api private
25
41
  def respond_to_missing?(name, include_private = false)
26
42
  @builder.respond_to?(name) || super
27
43
  end
@@ -29,6 +45,7 @@ module RbSys
29
45
  # Seems to be the only way to reliably know if we were invoked by Rubygems.
30
46
  # We want to know this so we can cleanup the target directory after an
31
47
  # install, to remove bloat.
48
+ # @api private
32
49
  def rubygems_invoked?
33
50
  ENV.key?("SOURCE_DATE_EPOCH")
34
51
  end
data/lib/rb_sys/mkmf.rb CHANGED
@@ -10,6 +10,7 @@ require_relative "mkmf/config"
10
10
  module RbSys
11
11
  # Helper class for creating Rust Makefiles
12
12
  module Mkmf
13
+ # @api private
13
14
  GLOBAL_RUSTFLAGS = ["--cfg=rb_sys_gem"]
14
15
 
15
16
  # Helper for building Rust extensions by creating a Ruby compatible makefile
@@ -48,7 +49,7 @@ module RbSys
48
49
 
49
50
  yield builder if blk
50
51
 
51
- srcprefix = "$(srcdir)/#{builder.ext_dir}".chomp("/")
52
+ srcprefix = File.join("$(srcdir)", builder.ext_dir.gsub(/\A\.\/?/, "")).chomp("/")
52
53
  RbConfig.expand(srcdir = srcprefix.dup)
53
54
 
54
55
  full_cargo_command = cargo_command(srcdir, builder)
@@ -69,6 +70,7 @@ module RbSys
69
70
  #{conditional_assign("RB_SYS_GLOBAL_RUSTFLAGS", GLOBAL_RUSTFLAGS.join(" "))}
70
71
  #{conditional_assign("RB_SYS_EXTRA_RUSTFLAGS", builder.extra_rustflags.join(" "))}
71
72
  #{conditional_assign("RB_SYS_EXTRA_CARGO_ARGS", builder.extra_cargo_args.join(" "))}
73
+ #{conditional_assign("RB_SYS_CARGO_MANIFEST_DIR", builder.manifest_dir)}
72
74
 
73
75
  # Set dirname for the profile, since the profiles do not directly map to target dir (i.e. dev -> debug)
74
76
  #{if_eq_stmt("$(RB_SYS_CARGO_PROFILE)", "dev")}
@@ -100,10 +102,10 @@ module RbSys
100
102
  DLLIB = $(TARGET).#{RbConfig::CONFIG["DLEXT"]}
101
103
  RUSTLIBDIR = $(RB_SYS_FULL_TARGET_DIR)/$(RB_SYS_CARGO_PROFILE_DIR)
102
104
  RUSTLIB = $(RUSTLIBDIR)/$(SOEXT_PREFIX)$(TARGET_NAME).$(SOEXT)
105
+ TIMESTAMP_DIR = .
103
106
 
104
107
  CLEANOBJS = $(RUSTLIBDIR) $(RB_SYS_BUILD_DIR)
105
- DEFFILE = $(RB_SYS_CARGO_TARGET_DIR)/$(TARGET)-$(arch).def
106
- CLEANLIBS = $(DLLIB) $(RUSTLIB) $(DEFFILE)
108
+ CLEANLIBS = $(DLLIB) $(RUSTLIB)
107
109
  RUBYGEMS_CLEAN_DIRS = $(CLEANOBJS) $(CLEANFILES) #{builder.rubygems_clean_dirs.join(" ")}
108
110
 
109
111
  #{base_makefile(srcdir)}
@@ -119,18 +121,20 @@ module RbSys
119
121
 
120
122
  FORCE: ;
121
123
 
122
- #{deffile_definition}
123
-
124
124
  #{optional_rust_toolchain(builder)}
125
125
 
126
- $(RUSTLIB): #{deffile_definition ? "$(DEFFILE) " : nil}FORCE
126
+ #{timestamp_file("sitearchdir")}:
127
+ \t$(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR)
128
+ \t$(Q) $(TOUCH) $@
129
+
130
+ $(RUSTLIB): FORCE
127
131
  \t$(ECHO) generating $(@) \\("$(RB_SYS_CARGO_PROFILE)"\\)
128
132
  \t#{full_cargo_command}
129
133
 
130
134
  $(DLLIB): $(RUSTLIB)
131
135
  \t$(Q) $(COPY) "$(RUSTLIB)" $@
132
136
 
133
- install-so: $(DLLIB)
137
+ install-so: $(DLLIB) #{timestamp_file("sitearchdir")}
134
138
  \t$(ECHO) installing $(DLLIB) to $(RUBYARCHDIR)
135
139
  \t$(Q) $(MAKEDIRS) $(RUBYARCHDIR)
136
140
  \t$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
@@ -166,7 +170,7 @@ module RbSys
166
170
  cargo_cmd = builder.cargo_command(dest_path, args)
167
171
  cmd = Shellwords.join(cargo_cmd)
168
172
  cmd.gsub!("\\=", "=")
169
- cmd.gsub!(/\Acargo rustc/, "$(CARGO) rustc $(RB_SYS_EXTRA_CARGO_ARGS)")
173
+ cmd.gsub!(/\Acargo rustc/, "$(CARGO) rustc $(RB_SYS_EXTRA_CARGO_ARGS) --manifest-path $(RB_SYS_CARGO_MANIFEST_DIR)/Cargo.toml")
170
174
  cmd.gsub!(/-v=\d/, "")
171
175
  cmd
172
176
  end
@@ -200,21 +204,6 @@ module RbSys
200
204
  cargo_command
201
205
  end
202
206
 
203
- def deffile_definition
204
- warn("EXPORT_PREFIX is not defined, please require \"mkmf\" before requiring \"rb_sys/mkmf\"") unless defined?(EXPORT_PREFIX)
205
-
206
- return unless defined?(EXPORT_PREFIX) && EXPORT_PREFIX
207
-
208
- @deffile_definition ||= <<~MAKE
209
- $(DEFFILE):
210
- \t$(ECHO) creating target directory \\($(RUSTLIBDIR)\\)
211
- \t$(Q) $(MAKEDIRS) $(RUSTLIBDIR)
212
- \t$(ECHO) generating $(@)
213
- \t$(ECHO) EXPORTS > $@
214
- \t$(ECHO) $(TARGET_ENTRY) >> $@
215
- MAKE
216
- end
217
-
218
207
  def rust_toolchain_env(builder)
219
208
  <<~MAKE
220
209
  #{conditional_assign("RB_SYS_RUSTUP_PROFILE", "minimal")}
@@ -4,6 +4,7 @@
4
4
 
5
5
  module RbSys
6
6
  class ToolchainInfo
7
+ # @private
7
8
  DATA = {"arm-linux" => {"rust-target" => "arm-unknown-linux-gnueabihf", "rake-compiler-dock" => {"cc" => "arm-linux-gnueabihf-gcc"}, "docker-platform" => "linux/arm/v7", "supported" => true}, "aarch64-linux" => {"rust-target" => "aarch64-unknown-linux-gnu", "rake-compiler-dock" => {"cc" => "aarch64-linux-gnu-gcc"}, "docker-platform" => "linux/arm64/v8", "supported" => true}, "arm64-darwin" => {"rust-target" => "aarch64-apple-darwin", "rake-compiler-dock" => {"cc" => "aarch64-apple-darwin-clang"}, "docker-platform" => "linux/arm64/v8", "supported" => true}, "x64-mingw-ucrt" => {"rust-target" => "x86_64-pc-windows-gnu", "rake-compiler-dock" => {"cc" => "x86_64-windows-gnu-gcc"}, "docker-platform" => "linux/amd64", "supported" => true}, "x64-mingw32" => {"rust-target" => "x86_64-pc-windows-gnu", "rake-compiler-dock" => {"cc" => "x86_64-windows-gnu-gcc"}, "docker-platform" => "linux/amd64", "supported" => true}, "x86-linux" => {"rust-target" => "i686-unknown-linux-gnu", "rake-compiler-dock" => {"cc" => "i686-redhat-linux-gcc"}, "docker-platform" => "linux/i386", "supported" => false}, "x86-mingw32" => {"rust-target" => "i686-pc-windows-gnu", "rake-compiler-dock" => {"cc" => "i686-w64-mingw32-gcc"}, "docker-platform" => "linux/i386", "supported" => false}, "x86_64-darwin" => {"rust-target" => "x86_64-apple-darwin", "rake-compiler-dock" => {"cc" => "x86_64-apple-darwin-clang"}, "docker-platform" => "linux/amd64", "supported" => true}, "x86_64-linux" => {"rust-target" => "x86_64-unknown-linux-gnu", "rake-compiler-dock" => {"cc" => "x86_64-redhat-linux-gcc"}, "docker-platform" => "linux/amd64", "supported" => true}, "x86_64-linux-musl" => {"rust-target" => "x86_64-unknown-linux-musl", "rake-compiler-dock" => {"cc" => "x86_64-unknown-linux-musl-gcc"}, "docker-platform" => "linux/amd64", "supported" => true}}
8
9
  end
9
10
  end
@@ -14,19 +14,31 @@ module RbSys
14
14
  attr_reader :platform, :gem_platform, :rust_target, :rake_compiler_dock_cc, :supported, :rake_compiler_dock_image, :docker_platform
15
15
 
16
16
  class << self
17
+ # Get all known toolchains.
18
+ #
19
+ # @return [Array<RbSys::ToolchainInfo>]
17
20
  def all
18
21
  @all ||= DATA.keys.map { |k| new(k) }
19
22
  end
20
23
 
24
+ # Get all supported toolchains.
25
+ #
26
+ # @return [Array<RbSys::ToolchainInfo>]
21
27
  def supported
22
28
  @supported ||= all.select(&:supported?)
23
29
  end
24
30
 
31
+ # Get the toolchain for the current platform.
32
+ #
33
+ # @return [RbSys::ToolchainInfo]
25
34
  def local
26
35
  @current ||= new(RbConfig::CONFIG["arch"])
27
36
  end
28
37
  end
29
38
 
39
+ # Create a new toolchain info object.
40
+ #
41
+ # @param platform [String] The platform to get information about.
30
42
  def initialize(platform)
31
43
  @platform = platform
32
44
  @gem_platform = Gem::Platform.new(platform)
@@ -38,14 +50,24 @@ module RbSys
38
50
  @docker_platform = data["docker-platform"]
39
51
  end
40
52
 
53
+ # Whether this toolchain is supported.
54
+ #
55
+ # @return [Boolean]
41
56
  def supported?
42
57
  @supported
43
58
  end
44
59
 
60
+ # String representation of the toolchain.
61
+ #
62
+ # @return [String]
45
63
  def to_s
46
64
  "#{gem_platform.cpu}-#{gem_platform.os}"
47
65
  end
48
66
 
67
+ # Compare two toolchains.
68
+ #
69
+ # @param other [RbSys::ToolchainInfo]
70
+ # @return [Boolean]
49
71
  def ==(other)
50
72
  @gem_platform == other.gem_platform
51
73
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RbSys
4
- VERSION = "0.9.59"
4
+ VERSION = "0.9.61"
5
5
  end
data/lib/rb_sys.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "rb_sys/version"
4
+ require_relative "rb_sys/error"
4
5
  require_relative "rb_sys/toolchain_info"
5
6
 
6
7
  module RbSys
7
- class Error < StandardError; end
8
- # Your code goes here...
9
8
  end
data.tar.gz.sig CHANGED
@@ -1,2 +1 @@
1
- �f1`�QQ׿2 �B���c�x(�����ZH��U�-|p+$ P|�}d4~�y(i?y1R]�
2
- Jm�Rt���r
1
+ �¸cdm����S)����Z��6O��b�����j��R41,Lڃ��}\AzJ��S�c�|�as����*u-��=S|�5�r�5~�З�BQpiH{��Z:�M4���B?@��#�q���@X���v���Ѯ�����K�hq���]p��=���yU��ӛ���ΟB[��x�>2zh��7��Qw��SC1�-wY��\H
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rb_sys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.59
4
+ version: 0.9.61
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Ker-Seymer
@@ -30,7 +30,7 @@ cert_chain:
30
30
  Rl+ASkq2/1i07TkBpCf+2hq66+h/hx+/Y/KrUzXfe0jtvil0WESkJT2kqRqHWNhD
31
31
  9GKBxaQlXokNDtWCm1/gl6cD8WRZ0N5S4ZGJT1FLLsA=
32
32
  -----END CERTIFICATE-----
33
- date: 2023-02-01 00:00:00.000000000 Z
33
+ date: 2023-02-06 00:00:00.000000000 Z
34
34
  dependencies: []
35
35
  description:
36
36
  email:
@@ -45,8 +45,12 @@ files:
45
45
  - certs/ianks.pem
46
46
  - exe/rb-sys-dock
47
47
  - lib/rb_sys.rb
48
+ - lib/rb_sys/cargo.rb
49
+ - lib/rb_sys/cargo/metadata.rb
48
50
  - lib/rb_sys/cargo_builder.rb
49
51
  - lib/rb_sys/cargo_builder/link_flag_converter.rb
52
+ - lib/rb_sys/error.rb
53
+ - lib/rb_sys/extensiontask.rb
50
54
  - lib/rb_sys/mkmf.rb
51
55
  - lib/rb_sys/mkmf/config.rb
52
56
  - lib/rb_sys/toolchain_info.rb
@@ -74,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
78
  - !ruby/object:Gem::Version
75
79
  version: '0'
76
80
  requirements: []
77
- rubygems_version: 3.4.2
81
+ rubygems_version: 3.4.6
78
82
  signing_key:
79
83
  specification_version: 4
80
84
  summary: Helpers for compiling Rust extensions for ruby
metadata.gz.sig CHANGED
Binary file