rb_sys 0.9.63 → 0.9.64
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.yardopts +3 -0
- data/README.md +98 -0
- data/lib/rb_sys/cargo/metadata.rb +69 -18
- data/lib/rb_sys/error.rb +13 -7
- data/lib/rb_sys/mkmf.rb +21 -0
- data/lib/rb_sys/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +5 -4
- metadata.gz.sig +0 -0
- data/sig/rb_sys.rbs +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da8a462e7210f1746cca7dd9935d243b179176318aa766474fc33dd2de71227c
|
4
|
+
data.tar.gz: 7cd4a0126f7240b2b58ee3338dceec912d1cd9de211adc55a6f4da320fa982cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be81aba075a717c61a156cfcfafba1b9e7b36a33a045a2f04372b1c8244dd4280c0ebcc113fdc5c468bf72e49b6aaa8eff8d20784706ac779bab80e64d09ae04
|
7
|
+
data.tar.gz: 3fa8cb0393b6cbbd53cba685b8616e5b747556ea583b8e943ec54b93a938b6b0f6610768c545e28076eb9806afb92108e1bdf6e0e2f9d78b6cdaf05666fa6bd9
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/.yardopts
ADDED
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# The `rb_sys` gem
|
2
|
+
|
3
|
+
![Gem](https://img.shields.io/gem/v/rb_sys)
|
4
|
+
[![Documentation](https://img.shields.io/badge/docs-rdoc.info-blue.svg)](https://www.rubydoc.info/gems/rb_sys/frames)
|
5
|
+
[![Join the discussion](https://img.shields.io/badge/slack-chat-blue.svg)](https://join.slack.com/t/oxidize-rb/shared_invite/zt-16zv5tqte-Vi7WfzxCesdo2TqF_RYBCw)
|
6
|
+
|
7
|
+
The `rb_sys` gem is a Ruby gem makes it easy to build native Ruby extensions in Rust. It interops with the existing Ruby
|
8
|
+
native extension toolchains (i.e. `rake-compiler`) to make testing, building, and cross compilation of gems easy.
|
9
|
+
|
10
|
+
## `RbSys::ExtensionTask`
|
11
|
+
|
12
|
+
This gem provides a `RbSys::ExtensionTask` class that can be used to build a Ruby extension in Rust. It's a thin wrapper
|
13
|
+
around `Rake::ExtensionTask` that provides sane defaults for building Rust extensions.
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
# Rakefile
|
17
|
+
|
18
|
+
require "rb_sys/extensiontask"
|
19
|
+
|
20
|
+
GEMSPEC = Gem::Specification.load("my_gem.gemspec")
|
21
|
+
|
22
|
+
RbSys::ExtensionTask.new("my-crate-name", GEMSPEC) do |ext|
|
23
|
+
ext.lib_dir = "lib/my_gem"
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
## `create_rust_makefile`
|
28
|
+
|
29
|
+
This gem provides a simple helper to build a Ruby compatible Makefile for you Rust extension. For a full example, see
|
30
|
+
the [examples](./../examples) directory.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
# ext/rust_reverse/extconf.rb
|
34
|
+
|
35
|
+
# We need to require mkmf *first* this since `rake-compiler` injects code here for cross compilation
|
36
|
+
require "mkmf"
|
37
|
+
require "rb_sys/mkmf"
|
38
|
+
|
39
|
+
create_rust_makefile("rust_reverse") do |r|
|
40
|
+
# Create debug builds in dev. Make sure that release gems are compiled with
|
41
|
+
# `RB_SYS_CARGO_PROFILE=release` (optional)
|
42
|
+
r.profile = ENV.fetch("RB_SYS_CARGO_PROFILE", :dev).to_sym
|
43
|
+
|
44
|
+
# Can be overridden with `RB_SYS_CARGO_FEATURES` env var (optional)
|
45
|
+
r.features = ["test-feature"]
|
46
|
+
|
47
|
+
# You can add whatever env vars you want to the env hash (optional)
|
48
|
+
r.env = {"FOO" => "BAR"}
|
49
|
+
|
50
|
+
# If your Cargo.toml is in a different directory, you can specify it here (optional)
|
51
|
+
r.ext_dir = "."
|
52
|
+
|
53
|
+
# Extra flags to pass to the $RUSTFLAGS environment variable (optional)
|
54
|
+
r.extra_rustflags = ["--cfg=some_nested_config_var_for_crate"]
|
55
|
+
|
56
|
+
# Force a rust toolchain to be installed via rustup (optional)
|
57
|
+
# You can also set the env var `RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN=true`
|
58
|
+
r.force_install_rust_toolchain = "stable"
|
59
|
+
|
60
|
+
# Clean up the target/ dir after `gem install` to reduce bloat (optional)
|
61
|
+
r.clean_after_install = false # default: true if invoked by rubygems
|
62
|
+
|
63
|
+
# Auto-install Rust toolchain if not present on "gem install" (optional)
|
64
|
+
r.auto_install_rust_toolchain = false # default: true if invoked by rubygems
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
## Tips and Tricks
|
69
|
+
|
70
|
+
- When using `rake-compiler` to build your gem, you can use the `RB_SYS_CARGO_PROFILE` environment variable to set the
|
71
|
+
Cargo profile (i.e. `release` or `dev`).
|
72
|
+
|
73
|
+
- You can pass Cargo arguments to `rake-compiler` like so: `rake compile -- --verbose`
|
74
|
+
|
75
|
+
- It's possible to force an installation of a Rust toolchain by setting the `RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN`
|
76
|
+
environment variable. This will install [rustup](https://rustup.rs/) and [cargo](https://crates.io/) in the build
|
77
|
+
directory, so the end user does not have to have Rust pre-installed. Ideally, this should be a last resort, as it's
|
78
|
+
better to already have the toolchain installed on your system.
|
79
|
+
|
80
|
+
## Troubleshooting
|
81
|
+
|
82
|
+
### Libclang issues
|
83
|
+
|
84
|
+
If you see an error like this:
|
85
|
+
|
86
|
+
```
|
87
|
+
thread 'main' panicked at 'Unable to find libclang: "couldn't find any valid shared libraries matching: \['libclang.so', 'libclang-*.so', 'libclang.so.*', 'libclang-*.so.*'\], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: \[\])"'
|
88
|
+
```
|
89
|
+
|
90
|
+
This means that bindgen is having issues finding a usable version of libclang. An easy way to fix this is to install the
|
91
|
+
[`libclang` gem](https://github.com/oxidize-rb/libclang-rb), which will install a pre-built version of libclang for you.
|
92
|
+
`rb_sys` will automatically detect this gem and use it.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# Gemfile
|
96
|
+
|
97
|
+
gem "libclang", "~> 14.0.6"
|
98
|
+
```
|
@@ -9,35 +9,83 @@ module RbSys
|
|
9
9
|
class Metadata
|
10
10
|
attr_reader :name
|
11
11
|
|
12
|
+
# Initializes a new Cargo::Metadata instance.
|
13
|
+
#
|
14
|
+
# @param name [String] the name of the Cargo project
|
12
15
|
def initialize(name)
|
13
16
|
raise ArgumentError, "name must be a String" unless name.is_a?(String)
|
14
17
|
|
15
18
|
@name = name
|
16
19
|
end
|
17
20
|
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
# Returns the path where the Cargo project's Cargo.toml is located.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
def manifest_directory
|
25
|
+
@manifest_directory ||= File.dirname(manifest_path)
|
23
26
|
end
|
24
27
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
# Returns the target directory for the Cargo project.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
def target_directory
|
32
|
+
cargo_metadata.fetch("target_directory")
|
30
33
|
end
|
31
34
|
|
32
|
-
|
35
|
+
# Returns the workspace root for the Cargo project.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
def workspace_root
|
39
|
+
cargo_metadata.fetch("workspace_root")
|
40
|
+
end
|
33
41
|
|
34
|
-
|
42
|
+
# Returns the workspace members for the Cargo project.
|
43
|
+
#
|
44
|
+
# @return [Array<Hash>]
|
45
|
+
def packages
|
46
|
+
cargo_metadata.fetch("packages")
|
47
|
+
end
|
35
48
|
|
36
|
-
# Returns the path
|
49
|
+
# Returns the path to the package's Cargo.toml.
|
37
50
|
#
|
38
51
|
# @return [String]
|
39
|
-
def
|
40
|
-
|
52
|
+
def manifest_path
|
53
|
+
package_metadata.fetch("manifest_path")
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns the package's version.
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
def version
|
60
|
+
package_metadata.fetch("version")
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the package's id.
|
64
|
+
#
|
65
|
+
# @return [String]
|
66
|
+
def id
|
67
|
+
package_metadata.fetch("id")
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the package's Rust edition.
|
71
|
+
#
|
72
|
+
# @return [String]
|
73
|
+
def edition
|
74
|
+
package_metadata.fetch("edition")
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns the package's features.
|
78
|
+
#
|
79
|
+
# @return [Array<String>]
|
80
|
+
def features
|
81
|
+
package_metadata.fetch("features")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the package's custom metadata.
|
85
|
+
#
|
86
|
+
# @return [Hash]
|
87
|
+
def metadata
|
88
|
+
package_metadata.fetch("metadata")
|
41
89
|
end
|
42
90
|
|
43
91
|
private
|
@@ -56,10 +104,13 @@ module RbSys
|
|
56
104
|
::Gem.load_yaml
|
57
105
|
cargo = ENV["CARGO"] || "cargo"
|
58
106
|
args = ["metadata", "--no-deps", "--format-version", "1"]
|
59
|
-
out, stderr,
|
60
|
-
|
107
|
+
out, stderr, status = Open3.capture3(cargo, *args)
|
108
|
+
raise "exited with non-zero status (#{status})" unless status.success?
|
109
|
+
data = Gem::SafeYAML.safe_load(out)
|
110
|
+
raise "metadata must be a Hash" unless data.is_a?(Hash)
|
111
|
+
@cargo_metadata = data
|
61
112
|
rescue => err
|
62
|
-
raise CargoMetadataError.new(err, stderr
|
113
|
+
raise CargoMetadataError.new(err, stderr)
|
63
114
|
end
|
64
115
|
end
|
65
116
|
end
|
data/lib/rb_sys/error.rb
CHANGED
@@ -19,18 +19,24 @@ module RbSys
|
|
19
19
|
|
20
20
|
# Raised when Cargo metadata cannot be parsed.
|
21
21
|
class CargoMetadataError < Error
|
22
|
-
def initialize(err, stderr
|
22
|
+
def initialize(err, stderr)
|
23
23
|
msg = <<~MSG.chomp.tr("\n", " ")
|
24
|
-
Could not
|
25
|
-
is valid. The error was: #{err}
|
24
|
+
Could not infer Rust crate information using `cargo metadata`.
|
26
25
|
|
27
|
-
|
26
|
+
Original error was:
|
27
|
+
#{err.class}: #{err.message}
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
Things to check:
|
30
|
+
- Check that your ext/*/Cargo.toml at is valid
|
31
|
+
- If you are using a workspace, make sure you are the root Cargo.toml exists
|
32
|
+
- Make sure `cargo` is installed and in your PATH
|
32
33
|
MSG
|
33
34
|
|
35
|
+
if !stderr.empty?
|
36
|
+
indented_stderr = stderr.lines.map { |line| " #{line}" }.join
|
37
|
+
msg << "Stderr from `cargo metadata` was:\n#{indented_stderr}"
|
38
|
+
end
|
39
|
+
|
34
40
|
super(msg)
|
35
41
|
end
|
36
42
|
end
|
data/lib/rb_sys/mkmf.rb
CHANGED
@@ -59,6 +59,7 @@ module RbSys
|
|
59
59
|
#{conditional_assign("CARGO", "cargo")}
|
60
60
|
#{conditional_assign("CARGO_BUILD_TARGET", builder.target)}
|
61
61
|
#{conditional_assign("SOEXT", builder.so_ext)}
|
62
|
+
#{try_load_bundled_libclang(builder)}
|
62
63
|
|
63
64
|
# Determine the prefix Cargo uses for the lib.
|
64
65
|
#{if_neq_stmt("$(SOEXT)", "dll")}
|
@@ -317,6 +318,26 @@ module RbSys
|
|
317
318
|
end
|
318
319
|
end
|
319
320
|
|
321
|
+
def try_load_bundled_libclang(_builder)
|
322
|
+
require "libclang"
|
323
|
+
assert_libclang_version_valid!
|
324
|
+
export_env("LIBCLANG_PATH", Libclang.libdir)
|
325
|
+
rescue LoadError
|
326
|
+
# If we can't load the bundled libclang, just continue
|
327
|
+
end
|
328
|
+
|
329
|
+
def assert_libclang_version_valid!
|
330
|
+
libclang_version = Libclang.version
|
331
|
+
|
332
|
+
if libclang_version < Gem::Version.new("5.0.0")
|
333
|
+
raise "libclang version 5.0.0 or greater is required (current #{libclang_version})"
|
334
|
+
end
|
335
|
+
|
336
|
+
if libclang_version >= Gem::Version.new("15.0.0")
|
337
|
+
raise "libclang version > 14.0.0 or greater is required (current #{libclang_version})"
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
320
341
|
def set_cargo_profile(builder)
|
321
342
|
return assign_stmt("RB_SYS_CARGO_PROFILE", "release") if builder.rubygems_invoked?
|
322
343
|
|
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.64
|
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-07 00:00:00.000000000 Z
|
34
34
|
dependencies: []
|
35
35
|
description:
|
36
36
|
email:
|
@@ -40,8 +40,10 @@ executables:
|
|
40
40
|
extensions: []
|
41
41
|
extra_rdoc_files: []
|
42
42
|
files:
|
43
|
+
- ".yardopts"
|
43
44
|
- LICENSE-APACHE
|
44
45
|
- LICENSE-MIT
|
46
|
+
- README.md
|
45
47
|
- certs/ianks.pem
|
46
48
|
- exe/rb-sys-dock
|
47
49
|
- lib/rb_sys.rb
|
@@ -56,8 +58,7 @@ files:
|
|
56
58
|
- lib/rb_sys/toolchain_info.rb
|
57
59
|
- lib/rb_sys/toolchain_info/data.rb
|
58
60
|
- lib/rb_sys/version.rb
|
59
|
-
-
|
60
|
-
homepage: https://github.com/oxidize-rb/rb-sys
|
61
|
+
homepage: https://oxidize-rb.github.io/rb-sys/
|
61
62
|
licenses:
|
62
63
|
- MIT
|
63
64
|
- Apache-2.0
|
metadata.gz.sig
CHANGED
Binary file
|
data/sig/rb_sys.rbs
DELETED