rb_sys 0.9.64 → 0.9.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/exe/rb-sys-dock +222 -125
- data/lib/rb_sys/cargo/metadata.rb +13 -2
- data/lib/rb_sys/extensiontask.rb +35 -3
- data/lib/rb_sys/mkmf.rb +0 -1
- data/lib/rb_sys/util/logger.rb +73 -0
- data/lib/rb_sys/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5dc9ecb59d4b2cc130afff772c740063ee2bdbf5bdf15fb866aa6dcbb501d396
|
|
4
|
+
data.tar.gz: b9c2c65ef48e0c5400ea857bb75ad9ec85ffac300a4290bc6f20ef00ca5e8163
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c4acd2a28480da0b8adb18a48a806354afae12d963b9394f6ce9bd41f89c703a27dbe9a6bc52136f897ad7e64ccba70c9bbfd4231a9b209964d130dc703d8ad
|
|
7
|
+
data.tar.gz: 849c5b3fd8209dfe41b6a5efc0dbd06d6760e849b32cd0182915f9e1d5e011885ba64d56ef7c8f8ed286094ba4efaaec2ad5ffa1134690579223ae826e81ba54
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/exe/rb-sys-dock
CHANGED
|
@@ -1,82 +1,61 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
4
|
+
|
|
3
5
|
require "optparse"
|
|
6
|
+
require "open3"
|
|
4
7
|
require "rb_sys/version"
|
|
5
8
|
require "rb_sys/toolchain_info"
|
|
9
|
+
require "rb_sys/cargo/metadata"
|
|
10
|
+
require "rb_sys/util/logger"
|
|
6
11
|
require "fileutils"
|
|
7
12
|
require "tmpdir"
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
OPTIONS = {
|
|
15
|
+
docker_platform: "linux/amd64",
|
|
16
|
+
version: RbSys::VERSION,
|
|
17
|
+
directory: Dir.pwd
|
|
11
18
|
}
|
|
12
19
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
["❌", "\e[1;31m"]
|
|
17
|
-
when :warn
|
|
18
|
-
["⚠️", "\e[1;33m"]
|
|
19
|
-
when :info
|
|
20
|
-
["ℹ️", "\e[1;37m"]
|
|
21
|
-
when :notice
|
|
22
|
-
["🐳", "\e[1;34m"]
|
|
23
|
-
when :trace
|
|
24
|
-
return unless ENV["LOG_LEVEL"] == "trace"
|
|
25
|
-
|
|
26
|
-
["🔍", "\e[1;2m"]
|
|
27
|
-
else raise "Unknown log level: #{level.inspect}"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
emoji_opt = if emoji.is_a?(String)
|
|
31
|
-
emoji + " "
|
|
32
|
-
elsif emoji
|
|
33
|
-
emoji_opt + " "
|
|
34
|
-
end
|
|
20
|
+
def cargo_metadata
|
|
21
|
+
@cargo_metadata ||= RbSys::Cargo::Metadata.new("rb-sys-dock", deps: true)
|
|
22
|
+
end
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
def logger
|
|
25
|
+
return @logger if @logger
|
|
38
26
|
|
|
39
|
-
io.
|
|
27
|
+
io = ARGV.include?("--quiet") ? File.open(File::NULL, "w") : $stderr
|
|
28
|
+
@logger ||= RbSys::Util::Logger.new(io: io)
|
|
40
29
|
end
|
|
41
30
|
|
|
42
|
-
|
|
43
|
-
|
|
31
|
+
OptionParser.new do |opts|
|
|
32
|
+
opts.banner = <<~MSG
|
|
33
|
+
Usage: rb-sys-dock [OPTIONS] [COMMAND]
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
end
|
|
35
|
+
A CLI to facillitate building Ruby on Rust extensions using Docker.
|
|
47
36
|
|
|
48
|
-
|
|
49
|
-
log(:trace, "Running command: $ #{cmd}")
|
|
50
|
-
stdout, stderr, status = Open3.capture3(cmd)
|
|
37
|
+
Examples:
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
else
|
|
55
|
-
log(:error, "Error running command: $ #{cmd}")
|
|
56
|
-
warn(stderr)
|
|
57
|
-
exit(status.exitstatus)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
39
|
+
Build for Linux (x86_64)
|
|
40
|
+
$ rb-sys-dock --platform x86_64-linux --build
|
|
60
41
|
|
|
61
|
-
|
|
62
|
-
|
|
42
|
+
Build for macOS (Ruby 3.1 and 3.2)
|
|
43
|
+
$ rb-sys-dock -p arm64-darwin --ruby-versions 3.1,3.2 --build
|
|
63
44
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
log(:trace, "Could not find docker command, trying podman")
|
|
45
|
+
Enter a shell
|
|
46
|
+
$ rb-sys-dock --list-platforms
|
|
67
47
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@default_docker_command = "podman"
|
|
71
|
-
stdout
|
|
72
|
-
rescue Errno::ENOENT
|
|
73
|
-
log(:error, "Could not find docker or podman command, please install one of them")
|
|
74
|
-
exit(1)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
48
|
+
Run a command in the container with a specific directory mounted
|
|
49
|
+
$ rb-sys-dock -p x64-mingw-ucrt -d /tmp/mygem -- "env | grep RUBY"
|
|
77
50
|
|
|
78
|
-
|
|
79
|
-
|
|
51
|
+
List all supported platforms
|
|
52
|
+
$ rb-sys-dock --list-platforms
|
|
53
|
+
|
|
54
|
+
Options:
|
|
55
|
+
MSG
|
|
56
|
+
|
|
57
|
+
opts.on("--quiet", "Prints no logging output") do
|
|
58
|
+
end
|
|
80
59
|
|
|
81
60
|
opts.on("-v", "--version", "Prints version") do
|
|
82
61
|
require "rb_sys/version"
|
|
@@ -84,6 +63,10 @@ OptionParser.new do |opts|
|
|
|
84
63
|
exit
|
|
85
64
|
end
|
|
86
65
|
|
|
66
|
+
opts.on("--build", "Run the default command to cross-compile a gem") do
|
|
67
|
+
OPTIONS[:build] = true
|
|
68
|
+
end
|
|
69
|
+
|
|
87
70
|
opts.on("-p", "--platform PLATFORM", "Platform to build for (i.e. x86_64-linux)") do |p|
|
|
88
71
|
toolchain_info = begin
|
|
89
72
|
RbSys::ToolchainInfo.new(p)
|
|
@@ -91,42 +74,40 @@ OptionParser.new do |opts|
|
|
|
91
74
|
supported_list = RbSys::ToolchainInfo.all
|
|
92
75
|
supported_list.select!(&:supported?)
|
|
93
76
|
list = supported_list.map { |p| "- #{p} (#{p.rust_target})" }.join("\n")
|
|
94
|
-
|
|
77
|
+
logger.error("Platform #{p} is not supported, please use one of:\n\n#{list}")
|
|
95
78
|
exit(1)
|
|
96
79
|
end
|
|
97
80
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
opts.on("--latest", "Use the latest version of the Docker image") do
|
|
103
|
-
log(:notice, "Using latest version of the Docker image", emoji: "🆕")
|
|
104
|
-
options[:version] = "latest"
|
|
105
|
-
options[:no_cache] = true
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
opts.on("--list-platforms", "--list", "List all supported platforms") do
|
|
109
|
-
log(:notice, "Supported platforms listed below:")
|
|
110
|
-
|
|
111
|
-
RbSys::ToolchainInfo.supported.each do |p|
|
|
112
|
-
log(:info, "- #{p} (#{p.rust_target})", emoji: false, io: $stdout)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
exit(0)
|
|
81
|
+
OPTIONS[:platform] = p
|
|
82
|
+
OPTIONS[:toolchain_info] = toolchain_info
|
|
116
83
|
end
|
|
117
84
|
|
|
118
|
-
opts.on("--ruby-versions LIST", "List all supported Ruby versions") do |arg|
|
|
119
|
-
log(:notice, "Requested Ruby versions: #{arg}")
|
|
120
|
-
|
|
85
|
+
opts.on("-r", "--ruby-versions LIST", "List all supported Ruby versions") do |arg|
|
|
121
86
|
vers = arg.split(/[^0-9.]/).map do |v|
|
|
122
87
|
parts = v.split(".")
|
|
123
88
|
parts[2] = "0" if parts[2].nil?
|
|
124
89
|
parts.join(".")
|
|
125
90
|
end
|
|
126
91
|
|
|
92
|
+
OPTIONS[:ruby_versions] = vers
|
|
93
|
+
|
|
94
|
+
logger.info("Building for Ruby requested versions: #{vers}")
|
|
95
|
+
|
|
127
96
|
ENV["RUBY_CC_VERSION"] = vers.join(":")
|
|
128
97
|
end
|
|
129
98
|
|
|
99
|
+
opts.on("--tag TAG", "Use a specific version of the Docker image") do |tag|
|
|
100
|
+
logger.info("Using version #{tag} of the Docker image")
|
|
101
|
+
OPTIONS[:version] = tag
|
|
102
|
+
OPTIONS[:no_cache] = tag == "latest"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
opts.on("--list-platforms", "--list", "List all supported platforms") do
|
|
106
|
+
logger.info("Supported platforms listed below:")
|
|
107
|
+
list_platforms
|
|
108
|
+
exit(0)
|
|
109
|
+
end
|
|
110
|
+
|
|
130
111
|
opts.on("-h", "--help", "Prints this help") do
|
|
131
112
|
puts opts
|
|
132
113
|
exit
|
|
@@ -135,14 +116,60 @@ OptionParser.new do |opts|
|
|
|
135
116
|
opts.on("-V", "--verbose", "Prints verbose output") do
|
|
136
117
|
ENV["LOG_LEVEL"] = "trace"
|
|
137
118
|
ENV["VERBOSE"] = "1"
|
|
138
|
-
|
|
119
|
+
logger.level = :trace
|
|
120
|
+
OPTIONS[:verbose] = true
|
|
139
121
|
end
|
|
140
122
|
|
|
141
|
-
opts.on("--
|
|
142
|
-
|
|
123
|
+
opts.on("--mount-toolchains", "Mount local Rustup toolchain (instead of pre-installed from Docker container)") do
|
|
124
|
+
OPTIONS[:mount_rustup_toolchains] = true
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
opts.on("-d", "--directory DIR", "Directory to run the command in") do |val|
|
|
128
|
+
OPTIONS[:directory] = File.expand_path(val)
|
|
143
129
|
end
|
|
144
130
|
end.parse!
|
|
145
131
|
|
|
132
|
+
def list_platforms
|
|
133
|
+
RbSys::ToolchainInfo.supported.each do |p|
|
|
134
|
+
old = logger.io
|
|
135
|
+
logger.io = $stdout
|
|
136
|
+
puts "- #{p.platform}"
|
|
137
|
+
ensure
|
|
138
|
+
logger.io = old
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def default_docker_command
|
|
143
|
+
return @default_docker_command if defined?(@default_docker_command)
|
|
144
|
+
|
|
145
|
+
@default_docker_command = ENV.fetch("DOCKER") do
|
|
146
|
+
if !(docker = `which docker`).empty?
|
|
147
|
+
docker.strip
|
|
148
|
+
elsif !(podman = `which podman`).empty?
|
|
149
|
+
podman.strip
|
|
150
|
+
else
|
|
151
|
+
logger.fatal("Could not find docker or podman command, please install one of them")
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def run_command!(*cmd)
|
|
157
|
+
logger.trace("Running command:\n\t$ #{cmd.join(" ")}")
|
|
158
|
+
stdout, stderr, status = Open3.capture3(*cmd)
|
|
159
|
+
|
|
160
|
+
if status.success?
|
|
161
|
+
stdout
|
|
162
|
+
else
|
|
163
|
+
logger.error("Error running command: $ #{cmd}")
|
|
164
|
+
warn(stderr)
|
|
165
|
+
exit(status.exitstatus)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def docker(cmd)
|
|
170
|
+
run_command!("#{default_docker_command} #{cmd}")
|
|
171
|
+
end
|
|
172
|
+
|
|
146
173
|
def determine_cache_dir
|
|
147
174
|
return ENV["RB_SYS_DOCK_CACHE_DIR"] if ENV["RB_SYS_DOCK_CACHE_DIR"]
|
|
148
175
|
return File.join(ENV["XDG_CACHE_HOME"], "rb-sys-dock") if ENV["XDG_CACHE_HOME"]
|
|
@@ -172,53 +199,93 @@ def mount_cargo_registry
|
|
|
172
199
|
end
|
|
173
200
|
|
|
174
201
|
dir = File.join("registry")
|
|
175
|
-
|
|
202
|
+
logger.trace("Mounting cargo registry dir: #{dir}")
|
|
176
203
|
FileUtils.mkdir_p(dir)
|
|
177
204
|
|
|
178
|
-
|
|
205
|
+
mount_shared_bind_dir(File.join(local_registry_dir, dir), File.join("/usr/local/cargo", dir))
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def mount_rustup_toolchains
|
|
209
|
+
return unless OPTIONS[:mount_rustup_toolchains]
|
|
210
|
+
|
|
211
|
+
local_rustup_dir = if OPTIONS[:mount_rustup_toolchains].is_a?(String)
|
|
212
|
+
OPTIONS[:mount_rustup_toolchains]
|
|
213
|
+
elsif ENV["RUSTUP_HOME"]
|
|
214
|
+
ENV["RUSTUP_HOME"]
|
|
215
|
+
elsif File.exist?(rustup_home = File.join(ENV["HOME"], ".rustup"))
|
|
216
|
+
rustup_home
|
|
217
|
+
else
|
|
218
|
+
logger.fatal("Could not find Rustup home directory, please set RUSTUP_HOME")
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
logger.info("Mounting rustup toolchains from #{local_rustup_dir}")
|
|
222
|
+
|
|
223
|
+
target_triple = OPTIONS[:toolchain_info].rust_target
|
|
224
|
+
dkr_triple = "x86_64-unknown-linux-gnu"
|
|
225
|
+
dkr_toolchain = "stable-#{dkr_triple}"
|
|
226
|
+
dkr_toolchain_dir = "/usr/local/rustup/toolchains/#{dkr_toolchain}"
|
|
227
|
+
installed_toolchains = Dir.glob(File.join(local_rustup_dir, "toolchains", "*")).map { |f| File.basename(f) }
|
|
228
|
+
has_host_toolchain = installed_toolchains.any? { |t| t.end_with?(dkr_toolchain) }
|
|
229
|
+
|
|
230
|
+
if !has_host_toolchain
|
|
231
|
+
logger.info("Installing default toolchain for docker image (#{dkr_toolchain})")
|
|
232
|
+
run_command!("rustup", "toolchain", "add", dkr_toolchain, "--force-non-host")
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
has_target = run_command!("rustup target list --installed --toolchain #{dkr_toolchain}").include?(target_triple)
|
|
236
|
+
|
|
237
|
+
if !has_target
|
|
238
|
+
logger.info("Installing target for docker image (#{target_triple})")
|
|
239
|
+
run_command!("rustup", "target", "add", target_triple, "--toolchain", dkr_toolchain)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
volume("#{local_rustup_dir}/toolchains/#{dkr_toolchain}", dkr_toolchain_dir, mode: "z,ro")
|
|
179
243
|
end
|
|
180
244
|
|
|
181
245
|
def volume(src, dest, mode: "rw")
|
|
182
246
|
"--volume #{src}:#{dest}:rw"
|
|
183
247
|
end
|
|
184
248
|
|
|
185
|
-
def mount_bundle_cache
|
|
186
|
-
dir = File.join(cache_dir,
|
|
249
|
+
def mount_bundle_cache
|
|
250
|
+
dir = File.join(cache_dir, ruby_platform, "bundle")
|
|
187
251
|
bundle_path = File.join(docker_tmp, "bundle")
|
|
188
252
|
FileUtils.mkdir_p(dir)
|
|
189
|
-
|
|
253
|
+
logger.trace("Mounting bundle cache: #{dir}")
|
|
190
254
|
|
|
191
255
|
"#{volume(dir, bundle_path)} -e BUNDLE_PATH=#{bundle_path.inspect}"
|
|
192
256
|
end
|
|
193
257
|
|
|
194
|
-
def tmp_target_dir
|
|
258
|
+
def tmp_target_dir
|
|
195
259
|
return @tmp_target_dir if defined?(@tmp_target_dir)
|
|
196
260
|
|
|
197
|
-
dir = File.join(
|
|
261
|
+
dir = File.join(working_directory, "tmp", "rb-sys-dock", ruby_platform, "target")
|
|
198
262
|
FileUtils.mkdir_p(dir)
|
|
199
263
|
@tmp_target_dir = dir
|
|
200
264
|
end
|
|
201
265
|
|
|
202
|
-
def
|
|
203
|
-
|
|
266
|
+
def working_directory
|
|
267
|
+
OPTIONS.fetch(:directory)
|
|
204
268
|
end
|
|
205
269
|
|
|
206
|
-
def
|
|
270
|
+
def mount_target_dir
|
|
271
|
+
"-v #{tmp_target_dir}:#{File.join(working_directory, "target")}"
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def mount_command_history
|
|
207
275
|
return unless $stdin.tty?
|
|
208
276
|
|
|
209
|
-
history_dir = File.join(cache_dir,
|
|
277
|
+
history_dir = File.join(cache_dir, OPTIONS.fetch(:platform), "commandhistory")
|
|
210
278
|
FileUtils.mkdir_p(history_dir)
|
|
211
279
|
"-v #{history_dir}:#{File.join(docker_tmp, "commandhistory")}"
|
|
212
280
|
end
|
|
213
281
|
|
|
214
|
-
def default_command_to_run(input_args
|
|
282
|
+
def default_command_to_run(input_args)
|
|
215
283
|
input_cmd = input_args.empty? ? "true" : input_args.join(" ")
|
|
216
284
|
|
|
217
|
-
if
|
|
285
|
+
if OPTIONS[:build]
|
|
218
286
|
with_bundle = +"test -f Gemfile && bundle install && #{input_cmd} && bundle exec rake native:$RUBY_TARGET gem"
|
|
219
287
|
without_bundle = "#{input_cmd} && rake native:$RUBY_TARGET gem"
|
|
220
|
-
|
|
221
|
-
log(:notice, " $ rake native:#{options[:toolchain_info].platform} gem")
|
|
288
|
+
logger.info("Running default build command (rake native:#{ruby_platform} gem)")
|
|
222
289
|
"bash -c '(#{with_bundle}) || (#{without_bundle})'"
|
|
223
290
|
else
|
|
224
291
|
input_args.empty? ? "bash" : "bash -c '#{input_args.join(" ")}'"
|
|
@@ -242,11 +309,27 @@ def interactive?(input_args)
|
|
|
242
309
|
$stdin.tty?
|
|
243
310
|
end
|
|
244
311
|
|
|
245
|
-
def
|
|
246
|
-
"--mount type=bind,source=#{
|
|
312
|
+
def mount_shared_bind_dir(src, dest)
|
|
313
|
+
"--mount type=bind,source=#{src},destination=#{dest},readonly=false"
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def mount_tmp_dir
|
|
317
|
+
"--mount type=bind,source=#{Dir.mktmpdir},destination=#{working_directory}/tmp/#{ruby_platform},readonly=false"
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def toolchain_info
|
|
321
|
+
@toolchain_info ||= OPTIONS.fetch(:toolchain_info) do
|
|
322
|
+
logger.error("Could not determine ruby platform, please set ruby platform with --platform to one of:")
|
|
323
|
+
list_platforms
|
|
324
|
+
logger.fatal("Exiting...")
|
|
325
|
+
end
|
|
247
326
|
end
|
|
248
327
|
|
|
249
|
-
def
|
|
328
|
+
def ruby_platform
|
|
329
|
+
@ruby_platform ||= toolchain_info.platform
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def rcd(input_args)
|
|
250
333
|
wrapper_command = []
|
|
251
334
|
wrapper_command << "sigfw" unless interactive?(input_args)
|
|
252
335
|
wrapper_command << "runas"
|
|
@@ -256,12 +339,14 @@ def rcd(input_args, options)
|
|
|
256
339
|
|
|
257
340
|
cmd = <<~SH
|
|
258
341
|
#{default_docker_command} run \
|
|
259
|
-
|
|
260
|
-
#{
|
|
261
|
-
#{
|
|
342
|
+
--platform #{OPTIONS.fetch(:docker_platform)} \
|
|
343
|
+
-v #{working_directory}:#{working_directory} \
|
|
344
|
+
#{mount_tmp_dir} \
|
|
345
|
+
#{mount_target_dir} \
|
|
262
346
|
#{mount_cargo_registry} \
|
|
263
|
-
#{
|
|
264
|
-
#{
|
|
347
|
+
#{mount_rustup_toolchains} \
|
|
348
|
+
#{mount_bundle_cache} \
|
|
349
|
+
#{mount_command_history} \
|
|
265
350
|
#{user_mapping} \
|
|
266
351
|
-e GEM_PRIVATE_KEY_PASSPHRASE \
|
|
267
352
|
-e ftp_proxy \
|
|
@@ -269,52 +354,64 @@ def rcd(input_args, options)
|
|
|
269
354
|
-e https_proxy \
|
|
270
355
|
-e RCD_HOST_RUBY_PLATFORM=#{RbConfig::CONFIG["arch"]} \
|
|
271
356
|
-e RCD_HOST_RUBY_VERSION=#{RUBY_VERSION} \
|
|
357
|
+
-e RUSTUP_PERMIT_COPY_RENAME=true \
|
|
272
358
|
-e RCD_IMAGE \
|
|
273
359
|
-e RB_SYS_DOCK_TMPDIR="/tmp/rb-sys-dock" \
|
|
274
|
-
-e RB_SYS_CARGO_TARGET_DIR=#{tmp_target_dir
|
|
360
|
+
-e RB_SYS_CARGO_TARGET_DIR=#{tmp_target_dir.inspect} \
|
|
275
361
|
#{ENV["RUBY_CC_VERSION"] ? "-e RUBY_CC_VERSION=#{ENV["RUBY_CC_VERSION"]}" : ""} \
|
|
276
362
|
-e RAKEOPT \
|
|
277
363
|
-e TERM \
|
|
278
|
-
-
|
|
279
|
-
-w #{Dir.pwd} \
|
|
364
|
+
-w #{working_directory} \
|
|
280
365
|
--rm \
|
|
281
366
|
--interactive \
|
|
282
367
|
#{docker_options.join(" ")} \
|
|
283
368
|
#{ENV.fetch("RCD_IMAGE")} \
|
|
284
369
|
#{wrapper_command.join(" ")} \
|
|
285
|
-
#{default_command_to_run(input_args
|
|
370
|
+
#{default_command_to_run(input_args)}
|
|
286
371
|
SH
|
|
287
372
|
|
|
288
|
-
|
|
373
|
+
cmd.gsub!(/\s+/, " ")
|
|
374
|
+
|
|
375
|
+
logger.trace("Running command:\n\t$ #{cmd}")
|
|
289
376
|
|
|
290
377
|
exec(cmd)
|
|
291
378
|
end
|
|
292
379
|
|
|
293
|
-
def download_image
|
|
380
|
+
def download_image
|
|
294
381
|
image = ENV.fetch("RCD_IMAGE")
|
|
295
382
|
|
|
296
|
-
if docker("images -q #{image}").strip.empty? ||
|
|
383
|
+
if docker("images -q #{image}").strip.empty? || OPTIONS[:no_cache]
|
|
297
384
|
# Nicely formatted message that we are downloading the image which might take awhile
|
|
298
|
-
|
|
299
|
-
docker("pull #{image} --quiet > /dev/null")
|
|
385
|
+
logger.info("Downloading container #{image.inspect}, this might take awhile...")
|
|
386
|
+
docker("pull #{image} --platform #{OPTIONS[:docker_platform]} --quiet > /dev/null")
|
|
300
387
|
end
|
|
301
388
|
end
|
|
302
389
|
|
|
303
|
-
def log_some_useful_info
|
|
304
|
-
return if
|
|
390
|
+
def log_some_useful_info
|
|
391
|
+
return if OPTIONS[:build]
|
|
305
392
|
|
|
306
393
|
if ARGV.empty?
|
|
307
|
-
|
|
394
|
+
logger.info("Entering shell in Docker container #{ENV["RCD_IMAGE"].inspect}")
|
|
308
395
|
else
|
|
309
|
-
|
|
396
|
+
logger.info("Running command #{ARGV.inspect} in Docker container #{ENV["RCD_IMAGE"].inspect}")
|
|
310
397
|
end
|
|
311
398
|
end
|
|
312
399
|
|
|
313
|
-
def set_env
|
|
314
|
-
ENV["RCD_IMAGE"] ||= "rbsys/#{
|
|
400
|
+
def set_env
|
|
401
|
+
ENV["RCD_IMAGE"] ||= "rbsys/#{ruby_platform}:#{OPTIONS[:version]}"
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def lint_rb_sys
|
|
405
|
+
cargo_version = cargo_metadata.rb_sys_version
|
|
406
|
+
return if cargo_version == RbSys::VERSION
|
|
407
|
+
logger.warn("Cargo rb-sys version (#{cargo_version}) does not match Ruby gem version (#{RbSys::VERSION})")
|
|
408
|
+
rescue => e
|
|
409
|
+
logger.warn("Could not determine Cargo rb-sys version")
|
|
410
|
+
logger.trace("Error was: #{e.inspect}")
|
|
315
411
|
end
|
|
316
412
|
|
|
317
|
-
set_env
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
413
|
+
set_env
|
|
414
|
+
lint_rb_sys
|
|
415
|
+
download_image
|
|
416
|
+
log_some_useful_info
|
|
417
|
+
rcd(ARGV)
|
|
@@ -12,10 +12,13 @@ module RbSys
|
|
|
12
12
|
# Initializes a new Cargo::Metadata instance.
|
|
13
13
|
#
|
|
14
14
|
# @param name [String] the name of the Cargo project
|
|
15
|
-
def initialize(name)
|
|
15
|
+
def initialize(name, deps: false)
|
|
16
16
|
raise ArgumentError, "name must be a String" unless name.is_a?(String)
|
|
17
17
|
|
|
18
18
|
@name = name
|
|
19
|
+
@cargo_metadata = nil
|
|
20
|
+
@package_metadata = nil
|
|
21
|
+
@deps = deps
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
# Returns the path where the Cargo project's Cargo.toml is located.
|
|
@@ -88,6 +91,13 @@ module RbSys
|
|
|
88
91
|
package_metadata.fetch("metadata")
|
|
89
92
|
end
|
|
90
93
|
|
|
94
|
+
# Returns the rb-sys version, if any.
|
|
95
|
+
def rb_sys_version
|
|
96
|
+
pkg = packages.find { |p| p.fetch("name") == "rb-sys" }
|
|
97
|
+
return unless pkg
|
|
98
|
+
pkg["version"]
|
|
99
|
+
end
|
|
100
|
+
|
|
91
101
|
private
|
|
92
102
|
|
|
93
103
|
def package_metadata
|
|
@@ -103,7 +113,8 @@ module RbSys
|
|
|
103
113
|
|
|
104
114
|
::Gem.load_yaml
|
|
105
115
|
cargo = ENV["CARGO"] || "cargo"
|
|
106
|
-
args = ["metadata", "--
|
|
116
|
+
args = ["metadata", "--format-version", "1"]
|
|
117
|
+
args << "--no-deps" unless @deps
|
|
107
118
|
out, stderr, status = Open3.capture3(cargo, *args)
|
|
108
119
|
raise "exited with non-zero status (#{status})" unless status.success?
|
|
109
120
|
data = Gem::SafeYAML.safe_load(out)
|
data/lib/rb_sys/extensiontask.rb
CHANGED
|
@@ -4,7 +4,7 @@ require_relative "error"
|
|
|
4
4
|
begin
|
|
5
5
|
require "rake/extensiontask"
|
|
6
6
|
rescue LoadError
|
|
7
|
-
abort "Please install rake-compiler to use this
|
|
7
|
+
abort "Please install rake-compiler to use this feature"
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
module RbSys
|
|
@@ -22,8 +22,9 @@ module RbSys
|
|
|
22
22
|
# @param gem_spec [Gem::Specification] the gem specification to build (needed for cross-compiling)
|
|
23
23
|
# @return [Rake::ExtensionTask]
|
|
24
24
|
class ExtensionTask < Rake::ExtensionTask
|
|
25
|
-
def init(name = nil, gem_spec =
|
|
26
|
-
super
|
|
25
|
+
def init(name = nil, gem_spec = :undefined)
|
|
26
|
+
super(name, lint_gem_spec(name, gem_spec))
|
|
27
|
+
|
|
27
28
|
@orginal_ext_dir = @ext_dir
|
|
28
29
|
@ext_dir = cargo_metadata.manifest_directory
|
|
29
30
|
@source_pattern = nil
|
|
@@ -46,6 +47,8 @@ module RbSys
|
|
|
46
47
|
def define
|
|
47
48
|
super
|
|
48
49
|
define_env_tasks
|
|
50
|
+
|
|
51
|
+
CLEAN.include(target_directory) if defined?(CLEAN)
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
def cargo_metadata
|
|
@@ -118,5 +121,34 @@ module RbSys
|
|
|
118
121
|
desc 'Compile the native Rust extension with the "release" profile'
|
|
119
122
|
task "compile:release" => ["rb_sys:env:release", "compile"]
|
|
120
123
|
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
def lint_gem_spec(name, gs)
|
|
128
|
+
gem_spec = case gs
|
|
129
|
+
when :undefined
|
|
130
|
+
return
|
|
131
|
+
when Gem::Specification
|
|
132
|
+
gs
|
|
133
|
+
when String
|
|
134
|
+
Gem::Specification.load(gem_spec) || raise(ArgumentError, "Unable to load gemspec from file #{gs.inspect}")
|
|
135
|
+
else
|
|
136
|
+
raise ArgumentError, "gem_spec must be a Gem::Specification, got #{gs.class}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
gem_spec.files.each do |f|
|
|
140
|
+
if /\.(dll|so|dylib|lib|bundle)$/.match?(f)
|
|
141
|
+
warn "⚠️ gemspec includes native artifact (#{f}), please remove it."
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
if (gem_crate_name = gem_spec.metadata["cargo_crate_name"])
|
|
146
|
+
if name != gem_crate_name
|
|
147
|
+
warn "⚠️ cargo_crate_name (#{gem_crate_name}) does not match extension task crate name (#{name})"
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
gem_spec
|
|
152
|
+
end
|
|
121
153
|
end
|
|
122
154
|
end
|
data/lib/rb_sys/mkmf.rb
CHANGED
|
@@ -246,7 +246,6 @@ module RbSys
|
|
|
246
246
|
\t$(Q) curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL "https://sh.rustup.rs" | sh -s -- --no-modify-path --profile $(RB_SYS_RUSTUP_PROFILE) --default-toolchain none -y
|
|
247
247
|
\t$(Q) rustup toolchain install $(RB_SYS_DEFAULT_TOOLCHAIN) --profile $(RB_SYS_RUSTUP_PROFILE)
|
|
248
248
|
\t$(Q) rustup default $(RB_SYS_DEFAULT_TOOLCHAIN)
|
|
249
|
-
\t$(Q) rustup component add rustfmt
|
|
250
249
|
|
|
251
250
|
$(RUSTLIB): $(CARGO)
|
|
252
251
|
#{endif_stmt}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RbSys
|
|
4
|
+
module Util
|
|
5
|
+
class Logger
|
|
6
|
+
attr_accessor :io, :level
|
|
7
|
+
|
|
8
|
+
def initialize(io: $stderr, level: :info)
|
|
9
|
+
@io = ENV["GITHUB_ACTIONS"] ? $stdout : io
|
|
10
|
+
@level = level
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def error(message, **opts)
|
|
14
|
+
add(:error, message, **opts)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def warn(message, **opts)
|
|
18
|
+
add(:warn, message, **opts)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def info(message, **opts)
|
|
22
|
+
add(:info, message, **opts)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def notice(message, **opts)
|
|
26
|
+
add(:notice, message, **opts)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def trace(message, **opts)
|
|
30
|
+
return unless level == :trace
|
|
31
|
+
|
|
32
|
+
add(:trace, message, **opts)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def fatal(message, **opts)
|
|
36
|
+
error(message, **opts)
|
|
37
|
+
abort
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
LEVEL_STYLES = {
|
|
43
|
+
warn: ["⚠️", "\e[1;33m"],
|
|
44
|
+
error: ["❌", "\e[1;31m"],
|
|
45
|
+
notice: ["👋", "\e[1;37m"],
|
|
46
|
+
info: ["🐳", "\e[1;34m"],
|
|
47
|
+
trace: ["🔍", "\e[1;2m"]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if ENV["GITHUB_ACTIONS"]
|
|
51
|
+
def add(level, message, emoji: true)
|
|
52
|
+
emote, _ = LEVEL_STYLES.fetch(level.to_sym)
|
|
53
|
+
io.puts "::#{level}::#{emote} #{message}"
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
def add(level, message, emoji: true)
|
|
57
|
+
emoji_opt, shellcode = LEVEL_STYLES.fetch(level.to_sym)
|
|
58
|
+
|
|
59
|
+
emoji_opt = if emoji.is_a?(String)
|
|
60
|
+
emoji + " "
|
|
61
|
+
elsif emoji
|
|
62
|
+
emoji_opt + " "
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Escape the message for bash shell codes (e.g. \033[1;31m)
|
|
66
|
+
escaped = message.gsub("\\", "\\\\\\").gsub("\033", "\\033")
|
|
67
|
+
|
|
68
|
+
io.puts "#{shellcode}#{emoji_opt}#{escaped}\033[0m"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/rb_sys/version.rb
CHANGED
data.tar.gz.sig
CHANGED
|
Binary file
|
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.
|
|
4
|
+
version: 0.9.65
|
|
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-
|
|
33
|
+
date: 2023-02-13 00:00:00.000000000 Z
|
|
34
34
|
dependencies: []
|
|
35
35
|
description:
|
|
36
36
|
email:
|
|
@@ -57,6 +57,7 @@ files:
|
|
|
57
57
|
- lib/rb_sys/mkmf/config.rb
|
|
58
58
|
- lib/rb_sys/toolchain_info.rb
|
|
59
59
|
- lib/rb_sys/toolchain_info/data.rb
|
|
60
|
+
- lib/rb_sys/util/logger.rb
|
|
60
61
|
- lib/rb_sys/version.rb
|
|
61
62
|
homepage: https://oxidize-rb.github.io/rb-sys/
|
|
62
63
|
licenses:
|
|
@@ -79,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
79
80
|
- !ruby/object:Gem::Version
|
|
80
81
|
version: '0'
|
|
81
82
|
requirements: []
|
|
82
|
-
rubygems_version: 3.4.
|
|
83
|
+
rubygems_version: 3.4.6
|
|
83
84
|
signing_key:
|
|
84
85
|
specification_version: 4
|
|
85
86
|
summary: Helpers for compiling Rust extensions for ruby
|
metadata.gz.sig
CHANGED
|
Binary file
|