beni 0.21.0 → 0.22.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b78383ebbf4e02480045b7ae74845cc215964e9118a1b15eb802993f8ed6941
4
- data.tar.gz: daf134ab87ea00080792acc5022d53db9c81e8ef41a52f4928469ae58e59e30d
3
+ metadata.gz: 41959d26671559a3d7e06bc0369e0991aca90e6ee22571b473e97ba96c311075
4
+ data.tar.gz: 506fc11ef6a60d42d86e36ecf33d9974e9d4826279748af8f54a0ad17473b5ea
5
5
  SHA512:
6
- metadata.gz: d7e645406a51b0c8100061eaf40af10cb5c00c797e442b2708f596922448c23a7553e2dfb55f31fab5666d9e83c2435d54d53cd88e72726babbfbc29f33426be
7
- data.tar.gz: d7469f1936310dbe2cf6412f8a31b0f7d68aa91b144ed93dcf4fc042fbf8cb7b889488e7238c4a615b2442af3f3380d52f4508baa4f18c03ca915d64d0d59114
6
+ metadata.gz: 98650dbc14af4e10977fa2d11bc7ef09d468cf977ae8f02b11beaf98bac6b1f46cc1ae900967974ef101e39f1a0cf5235ee4624320bc5c1e697b479eceb5beef
7
+ data.tar.gz: 108e152a7452db8f4f2990a430306d58ae6a70919577fe85f8545df89c7e58c59774d7c860b57a55d7e6757e1eb7bec205c7a4d13bec4a76748d59343d19158d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.22.1](https://github.com/elct9620/beni/compare/v0.22.0...v0.22.1) (2026-10-09)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **beni:** name a mismatched value by mruby's own immediate test ([a86dd77](https://github.com/elct9620/beni/commit/a86dd77ec29fce3b70ff95cab7b32ef7e9dc8a75))
9
+
10
+ ## [0.22.0](https://github.com/elct9620/beni/compare/v0.21.0...v0.22.0) (2026-10-08)
11
+
12
+
13
+ ### ⚠ BREAKING CHANGES
14
+
15
+ * **beni:** `Mrb::class_new` is `Class::new(mrb, superclass)`; `RClass::new_instance`, `RClass::undef_default_alloc_func`, and `ExceptionClass::as_r_class` move onto the `Class` trait, in the prelude; `Module::name` becomes `Class::name`, so a module handle reads its path instead.
16
+
17
+ ### Features
18
+
19
+ * **beni-sys:** publish the mruby release the bindings declare ([66c6abc](https://github.com/elct9620/beni/commit/66c6abc997d6c6770ccb7ab8ce320b2610482332))
20
+ * **beni-sys:** read the keyword flag mruby 4.1 keeps in call info ([1c7244b](https://github.com/elct9620/beni/commit/1c7244b1eb93e69832a7afb673e42db4d670a6ee))
21
+ * **beni-sys:** read whether a class's default allocator is undefined ([420bebe](https://github.com/elct9620/beni/commit/420bebe3893336c120c87c5165a2ba6289e0b7b4))
22
+ * **beni:** allocate a class's instance without running initialize ([8f094bc](https://github.com/elct9620/beni/commit/8f094bc2b549b44c3b240f457d175a828234fd51))
23
+ * **beni:** carry class-only operations on a Class trait ([2a3077e](https://github.com/elct9620/beni/commit/2a3077e15801c75562ebffb8dd4599f49c863e95))
24
+ * **beni:** derive release cfgs from the published mruby release ([0333594](https://github.com/elct9620/beni/commit/033359457c6691f81e05b1c69248ae80896a6676))
25
+ * **beni:** read a class's superclass ([104404d](https://github.com/elct9620/beni/commit/104404df0414496822452f5454b627e022e788f7))
26
+ * **vendor:** stage Prism into the mruby source from a prism definition ([e7ccace](https://github.com/elct9620/beni/commit/e7ccace631a836d40d5a3fa2977d6cb57eb3cb42))
27
+
28
+
29
+ ### Bug Fixes
30
+
31
+ * **beni:** end a hash walk whose visit changes the pair count ([90c5034](https://github.com/elct9620/beni/commit/90c5034053f41f6002a1e12cf71b98e17331ddf6))
32
+ * **beni:** release a hash walk's visit values when the walk returns ([4742bcf](https://github.com/elct9620/beni/commit/4742bcff1576bbf09eb202a06772d4dbf9e3ced8))
33
+ * **tasks:** rebuild the per-ABI mruby trees when the staged release changes ([cbb505d](https://github.com/elct9620/beni/commit/cbb505d84b361f014536a9afc9f2e79c0d4fcd3a))
34
+ * **tasks:** stage the whole vendor tree before a per-ABI or documentation leg ([c00e1c1](https://github.com/elct9620/beni/commit/c00e1c19f08b6c1e379a65cca7ec15a52229e1c2))
35
+ * **vendor:** name a missing built-in checksum without calling it a pin ([000a3a6](https://github.com/elct9620/beni/commit/000a3a60de2639f623349af11a0cfbb6307ffc3f))
36
+ * **vendor:** tell a platform without a built-in checksum how to supply one ([73941cf](https://github.com/elct9620/beni/commit/73941cffb583661b4849a90f37797b69e8422e93))
37
+
3
38
  ## [0.21.0](https://github.com/elct9620/beni/compare/v0.20.0...v0.21.0) (2026-10-07)
4
39
 
5
40
 
data/README.md CHANGED
@@ -6,6 +6,10 @@ the archive it builds. Extracted from the
6
6
  [kobako](https://github.com/elct9620/kobako) project; APIs follow 0.x semver
7
7
  semantics and may still evolve between minor versions.
8
8
 
9
+ ```
10
+ beni gem ──rake beni:build──▶ archive + sidecar ──▶ beni-sys ──▶ beni crate
11
+ ```
12
+
9
13
  > [!WARNING]
10
14
  > The `beni` crate does not yet cover the full mruby C API. Anything missing
11
15
  > stays reachable through the unsafe `beni::sys` escape hatch — issue reports
@@ -38,7 +42,7 @@ Beni::Tasks.new
38
42
  rake beni:build
39
43
  ```
40
44
 
41
- This downloads the pinned mruby release, builds it with mruby's untouched
45
+ This downloads the default mruby release, builds it with mruby's untouched
42
46
  upstream default config, and stages `vendor/mruby/build/host/lib/` with the
43
47
  archive and its `libmruby.flags.mak` compile-flags sidecar — everything the
44
48
  crates need. The archive's own file name follows the toolchain that built it
@@ -137,15 +141,38 @@ WASI_SDK_PATH=$PWD/vendor/wasi-sdk \
137
141
  cargo build --target wasm32-wasip1
138
142
  ```
139
143
 
144
+ ### Prism Source
145
+
146
+ An mruby release whose compiler gem parses with Prism keeps Prism in a
147
+ git submodule, which the release tarball leaves out. Declare the
148
+ `prism` toolchain with that submodule's commit; the definition alone
149
+ selects it, and `beni:vendor:setup` stages it into the mruby tree:
150
+
151
+ ```ruby
152
+ Beni::Tasks.new do
153
+ version "<mruby release>"
154
+
155
+ toolchain "prism" do
156
+ version "<ruby/prism commit>"
157
+ sha256 "…"
158
+ end
159
+ end
160
+ ```
161
+
162
+ The commit is the one the release records for
163
+ `mrbgems/mruby-compiler/lib/prism`.
164
+
140
165
  ## Toolchain
141
166
 
142
167
  beni targets plain mruby and is not bound to WebAssembly. `rust-toolchain.toml`
143
168
  keeps `wasm32-wasip1` only as a build-verification target for downstream wasi
144
- consumers (kobako). For that target the Rust channel and the wasi-sdk version
145
- move in lockstep (the wasm32-wasip1 `crt1-command.o` references
146
- `__wasi_init_tp` from Rust 1.96 onward; wasi-sdk 33's `libc.a` supplies that
147
- symbol) — bump the pair together, in both this repo and kobako. Host builds
148
- are unaffected by the pairing.
169
+ consumers (kobako). For that target two versions move in lockstep, in both this
170
+ repo and kobako; host builds are unaffected.
171
+
172
+ | Version | Lockstep reason |
173
+ |---|---|
174
+ | Rust channel | `crt1-command.o` references `__wasi_init_tp` from 1.96 on |
175
+ | wasi-sdk 33 | its `libc.a` supplies `__wasi_init_tp` |
149
176
 
150
177
  ## Development
151
178
 
@@ -85,12 +85,14 @@ module Beni
85
85
  @targets.keys
86
86
  end
87
87
 
88
- # References plus their transitive dependencies; +mruby+ is always
89
- # selected and leads the set so it stages first.
88
+ # References plus their transitive dependencies, and the toolchains
89
+ # whose definition selects them; +mruby+ is always selected and
90
+ # leads the set so it stages first.
90
91
  def selected_names
91
92
  references = @targets.values.flat_map(&:references)
92
93
  dependencies = references.flat_map { |name| Vendor::DEPENDENCIES.fetch(name, []) }
93
- (%w[mruby] + references + dependencies).uniq
94
+ defined = @definitions.keys & Vendor::SELECTED_BY_DEFINITION
95
+ (%w[mruby] + references + dependencies + defined).uniq
94
96
  end
95
97
 
96
98
  def selected_toolchain(name)
@@ -27,7 +27,7 @@ module Beni
27
27
  "`toolchain #{key.inspect}` inside a target block must not carry a block — " \
28
28
  "definitions live at the top level"
29
29
  end
30
- DSL.assert_known_toolchain!(key)
30
+ DSL.assert_referenceable_toolchain!(key)
31
31
 
32
32
  @references << key unless @references.include?(key)
33
33
  end
data/lib/beni/dsl.rb CHANGED
@@ -17,6 +17,15 @@ module Beni
17
17
 
18
18
  raise Error, "unknown toolchain #{name.inspect} (known: #{Vendor::TOOLCHAIN_FACTORIES.keys.join(", ")})"
19
19
  end
20
+
21
+ # A reference may name any known toolchain except one only a
22
+ # top-level definition selects.
23
+ def assert_referenceable_toolchain!(name)
24
+ assert_known_toolchain!(name)
25
+ return unless Vendor::SELECTED_BY_DEFINITION.include?(name)
26
+
27
+ raise Error, "`toolchain #{name.inspect}` is selected by its top-level definition, never by a reference"
28
+ end
20
29
  end
21
30
  end
22
31
 
data/lib/beni/tasks.rb CHANGED
@@ -26,7 +26,8 @@ module Beni
26
26
  # The block is the declarative DSL from SPEC.md, run on +DSL::Context+:
27
27
  # scalar settings (+version+ / +build_config+ / +vendor_dir+), target
28
28
  # declarations carrying toolchain references, and top-level toolchain
29
- # definitions overriding a built-in pair. Every malformed declaration
29
+ # definitions overriding a built-in pair — or, for +prism+, selecting
30
+ # the toolchain with the only pair it has. Every malformed declaration
30
31
  # raises here — no task defined, nothing downloaded.
31
32
  #
32
33
  # Defined tasks:
@@ -118,12 +119,21 @@ module Beni
118
119
 
119
120
  namespace :setup do
120
121
  desc "Download and unpack #{toolchain.name} #{toolchain.version_label} into #{toolchain.final_dir}"
121
- task toolchain.task_name => toolchain.tarball_path do
122
+ task toolchain.task_name => [*enclosing_setup_tasks(toolchain), toolchain.tarball_path] do
122
123
  toolchain.install
123
124
  end
124
125
  end
125
126
  end
126
127
 
128
+ # A toolchain staged inside another's tree unpacks only once that
129
+ # tree is in place: unpacking the enclosing one replaces everything
130
+ # beneath it.
131
+ def enclosing_setup_tasks(toolchain)
132
+ vendor_toolchains
133
+ .select { |other| toolchain.final_dir.start_with?("#{other.final_dir}/") }
134
+ .map { |other| other.task_name.to_s }
135
+ end
136
+
127
137
  def define_build_task
128
138
  desc "Build vendored mruby for #{configuration.targets.join(" + ")} " \
129
139
  "(stages the archive and its compile-flags sidecar in #{builder.staged_paths.join(", ")})"
@@ -11,7 +11,7 @@ module Beni
11
11
  # not supported and not needed by +Beni::Tasks+.
12
12
  #
13
13
  # A version mismatch (toolchain bump) forces a clean re-extract, so the
14
- # unpacked tree never lags the pinned version. Public contract is the
14
+ # unpacked tree never lags the selected version. Public contract is the
15
15
  # single +#prepare+ entry point; the staging-directory step is internal.
16
16
  class Tarball
17
17
  # Marker stamped inside +final_dir+ after a successful unpack; a matching
@@ -8,14 +8,14 @@ module Beni
8
8
  # +#verify+, +#install+) that +Beni::Tasks+ wires into +file+ /
9
9
  # +task+ declarations.
10
10
  #
11
- # Adding a new tarball-based vendor artifact is a single factory
12
- # method in +Beni::Vendor+; the rake DSL loop in +Beni::Tasks+
11
+ # A new tarball-based toolchain is a factory method in +Beni::Vendor+
12
+ # registered in +TOOLCHAIN_FACTORIES+, with a built-in pair or a place
13
+ # in +SELECTED_BY_DEFINITION+; the rake DSL loop in +Beni::Tasks+
13
14
  # picks it up automatically.
14
15
  #
15
16
  # Fields:
16
17
  #
17
- # * +name+ — display name; also the basename of the unpacked
18
- # tree under +vendor_dir+ and the base for the
18
+ # * +name+ — display name; also the base for the
19
19
  # +setup:<name>+ task identifier.
20
20
  # * +version_label+ — version string; printed in the download log and
21
21
  # stamped into +final_dir+ as the idempotency key
@@ -30,12 +30,21 @@ module Beni
30
30
  # +Tarball#prepare+ under the same name.
31
31
  # * +vendor_dir+ — root of the vendor tree; anchors +final_dir+
32
32
  # and +tarball_path+.
33
+ # * +staged_dir+ — where the unpacked tree lands, relative to
34
+ # +vendor_dir+; defaults to +name+. A toolchain
35
+ # completing another's tree names a path inside
36
+ # it.
33
37
  # * +expected_sha256+ — the toolchain's selected checksum (resolved
34
38
  # by +Beni::Vendor+ from the built-in pair or a
35
39
  # consumer override); +nil+ falls to TOFU
36
40
  # sidecar pinning in +Checksum#verify_or_pin+.
37
41
  class Toolchain <
38
- Data.define(:name, :version_label, :base_url, :tarball_name, :top_level_dir, :vendor_dir, :expected_sha256)
42
+ Data.define(:name, :version_label, :base_url, :tarball_name, :top_level_dir, :vendor_dir, :staged_dir,
43
+ :expected_sha256)
44
+ def initialize(name:, staged_dir: name, **fields)
45
+ super
46
+ end
47
+
39
48
  # Symbol used to identify the +setup:<task_name>+ rake task. Dashes
40
49
  # in +name+ are not valid in rake task identifiers, so we map them
41
50
  # to underscores at this single seam.
@@ -52,7 +61,7 @@ module Beni
52
61
 
53
62
  # Destination under +vendor_dir+ where the unpacked tree is moved.
54
63
  def final_dir
55
- File.join(vendor_dir, name)
64
+ File.join(vendor_dir, staged_dir)
56
65
  end
57
66
 
58
67
  # Local cache path for the downloaded tarball. Lives under
data/lib/beni/vendor.rb CHANGED
@@ -6,7 +6,7 @@ require_relative "vendor/tarball"
6
6
  require_relative "vendor/toolchain"
7
7
 
8
8
  module Beni
9
- # Vendor toolchain façade. Owns the release-vendored toolchain pins and
9
+ # Vendor toolchain façade. Owns each toolchain's built-in pair and
10
10
  # the factory methods that build declarative +Toolchain+ values anchored
11
11
  # on a caller-supplied +vendor_dir+; +Beni::Tasks+ calls the factories
12
12
  # with each selected toolchain's resolved +(version, sha256)+ to wire
@@ -50,6 +50,10 @@ module Beni
50
50
  # task-definition time: referencing wasi-sdk implies mruby.
51
51
  DEPENDENCIES = { "wasi-sdk" => %w[mruby] }.freeze
52
52
 
53
+ # Toolchains only a top-level definition selects. Each completes the
54
+ # mruby source rather than serving a target, and has no built-in pair.
55
+ SELECTED_BY_DEFINITION = %w[prism].freeze
56
+
53
57
  # +RUBY_PLATFORM+ spells the same architecture and operating system
54
58
  # differently across hosts; toolchains key their per-platform tarballs
55
59
  # by one spelling each.
@@ -83,7 +87,8 @@ module Beni
83
87
  # domain the DSL validates against and +Beni::Tasks+ dispatches on.
84
88
  TOOLCHAIN_FACTORIES = {
85
89
  "mruby" => :mruby,
86
- "wasi-sdk" => :wasi_sdk
90
+ "wasi-sdk" => :wasi_sdk,
91
+ "prism" => :prism
87
92
  }.freeze
88
93
 
89
94
  module_function
@@ -116,6 +121,23 @@ module Beni
116
121
  )
117
122
  end
118
123
 
124
+ # The Prism source mruby's compiler gem carries as a git submodule,
125
+ # which a release's source tarball leaves out. +version+ is a
126
+ # +ruby/prism+ commit. It stages where the compiler gem reads the
127
+ # submodule from, so mruby's build does not fetch it.
128
+ def prism(vendor_dir:, version:, sha256:)
129
+ Toolchain.new(
130
+ name: "prism",
131
+ version_label: version,
132
+ base_url: "https://github.com/ruby/prism/archive",
133
+ tarball_name: "#{version}.tar.gz",
134
+ top_level_dir: "prism-#{version}",
135
+ vendor_dir: vendor_dir,
136
+ staged_dir: File.join("mruby", "mrbgems", "mruby-compiler", "lib", "prism"),
137
+ expected_sha256: sha256
138
+ )
139
+ end
140
+
119
141
  # When BENI_VENDOR_BASE_URL is set, all tarballs are fetched from that
120
142
  # base URL (test fixture). The base URL must serve files named exactly
121
143
  # +tarball_name+ for each toolchain.
@@ -141,8 +163,8 @@ module Beni
141
163
 
142
164
  checksum.fetch(platform) do
143
165
  raise Error, "[beni] #{name} #{version} vendors no tarball for build platform " \
144
- "#{platform}; declare the toolchain with its own version and sha256 " \
145
- "to name one beni does not pin here"
166
+ "#{platform}; declare the toolchain with a version and sha256 " \
167
+ "for this platform"
146
168
  end
147
169
  end
148
170
 
data/lib/beni/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Beni
4
- VERSION = "0.21.0"
4
+ VERSION = "0.22.1"
5
5
  end
@@ -17,7 +17,7 @@ bundle check >/dev/null 2>&1 || bundle install
17
17
 
18
18
  # The coverage measure reads its inventory from the vendored mruby headers,
19
19
  # and the session's egress serves the git protocol but not source archives —
20
- # so the source arrives by clone here, at the version the gem pins.
20
+ # so the source arrives by clone here, at the gem's default version.
21
21
  if [ ! -d vendor/mruby ]; then
22
22
  version="$(ruby -Ilib -rbeni/vendor -e 'print Beni::Vendor::BUILT_IN_PAIRS.fetch("mruby").fetch(:version)')"
23
23
  GIT_LFS_SKIP_SMUDGE=1 git -c advice.detachedHead=false clone --quiet --depth 1 \
data/sig/beni/dsl.rbs CHANGED
@@ -1,5 +1,7 @@
1
1
  module Beni
2
2
  module DSL
3
3
  def self?.assert_known_toolchain!: (String name) -> void
4
+
5
+ def self?.assert_referenceable_toolchain!: (String name) -> void
4
6
  end
5
7
  end
data/sig/beni/tasks.rbs CHANGED
@@ -25,6 +25,8 @@ module Beni
25
25
 
26
26
  def define_toolchain_tasks: (Vendor::Toolchain toolchain) -> void
27
27
 
28
+ def enclosing_setup_tasks: (Vendor::Toolchain toolchain) -> Array[String]
29
+
28
30
  def define_build_task: () -> void
29
31
 
30
32
  def define_clean_task: () -> void
@@ -7,9 +7,10 @@ module Beni
7
7
  attr_reader tarball_name: String
8
8
  attr_reader top_level_dir: String
9
9
  attr_reader vendor_dir: String
10
+ attr_reader staged_dir: String
10
11
  attr_reader expected_sha256: String?
11
12
 
12
- def initialize: (name: String, version_label: String, base_url: String, tarball_name: String, top_level_dir: String, vendor_dir: String, expected_sha256: String?) -> void
13
+ def initialize: (name: String, version_label: String, base_url: String, tarball_name: String, top_level_dir: String, vendor_dir: String, ?staged_dir: String, expected_sha256: String?) -> void
13
14
 
14
15
  def task_name: () -> Symbol
15
16
 
data/sig/beni/vendor.rbs CHANGED
@@ -8,6 +8,7 @@ module Beni
8
8
  OS_ALIASES: Hash[Regexp, String]
9
9
  BUILD_PLATFORM: String
10
10
  TOOLCHAIN_FACTORIES: Hash[String, Symbol]
11
+ SELECTED_BY_DEFINITION: Array[String]
11
12
 
12
13
  def self.build_platform: (?String platform) -> String
13
14
 
@@ -19,6 +20,8 @@ module Beni
19
20
 
20
21
  def self?.mruby: (vendor_dir: String, ?version: String?, ?sha256: String?) -> Toolchain
21
22
 
23
+ def self?.prism: (vendor_dir: String, version: String, sha256: String) -> Toolchain
24
+
22
25
  def self?.base_url_for: (String default) -> String
23
26
 
24
27
  def self?.built_in_sha256: (String name, String version, ?String platform) -> String?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beni
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aotokitsuruya
@@ -23,8 +23,8 @@ dependencies:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '13.0'
26
- description: Vendors a pinned mruby and builds libmruby.a through a Rake task library,
27
- with generated build configs for customization. Aims to grow into a full mruby dependency
26
+ description: Vendors mruby and builds libmruby.a through a Rake task library, with
27
+ generated build configs for customization. Aims to grow into a full mruby dependency
28
28
  manager.
29
29
  email:
30
30
  - contact@aotoki.me