From a5d9071b8719c23cb2070c3cc3294dc7ae099750 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Jun 2026 02:42:49 +0000 Subject: [PATCH 1/4] Fetch JRuby parser jars from Maven instead of shipping them The WebAssembly-backed JRuby parser added in #2998 bundled all of the Chicory and ASM jars (~1MB) inside the -java gem under lib/rbs/wasm/jars. Shipping third-party jars bloats the gem and risks loading conflicting copies when another gem ships the same jars. Follow the established JRuby convention (e.g. Psych): declare the jars as jar-dependencies requirements so they are fetched from Maven Central, the canonical source, at gem install time. Only RBS's own build artifact (rbs_parser.wasm) is shipped. - lib/rbs/wasm/jars.rb: single source of truth for the Maven coordinates, shared by the gemspec, the runtime, and the vendoring rake task. - rbs.gemspec: depend on jar-dependencies and add a `jar` requirement per coordinate; stop adding the jars to spec.files. - runtime.rb: require_jar the coordinates for an installed gem; keep loading vendored jars by path when running from source. - Rakefile: derive the vendor download URLs from the shared coordinates; the vendored dir is gitignored and only used to run the suite from source. Refs #3018 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RtMsDQEmuayTdn3rYsteYT --- .gitignore | 4 ++- Rakefile | 30 +++++++++------------ Steepfile | 1 + docs/release.md | 10 ++++--- lib/rbs/wasm/jars.rb | 59 +++++++++++++++++++++++++++++++++++++++++ lib/rbs/wasm/runtime.rb | 49 ++++++++++++++++++++-------------- rbs.gemspec | 15 ++++++++--- 7 files changed, 122 insertions(+), 46 deletions(-) create mode 100644 lib/rbs/wasm/jars.rb diff --git a/.gitignore b/.gitignore index 93c5b4a5c..e9f188f73 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,8 @@ rust/ruby-rbs/vendor/rbs/ # Compiled WebAssembly module (built by rake wasm:build) wasm/*.wasm -# JRuby runtime artifacts (assembled by rake wasm:jruby_setup, bundled in the JRuby gem) +# JRuby runtime artifacts (assembled by rake wasm:jruby_setup). The .wasm is +# bundled in the -java gem; the jars are only for running from source (the gem +# fetches them from Maven via jar-dependencies). lib/rbs/wasm/*.wasm lib/rbs/wasm/jars/ diff --git a/Rakefile b/Rakefile index c5b2aacac..5db3448c2 100644 --- a/Rakefile +++ b/Rakefile @@ -627,37 +627,31 @@ namespace :wasm do end end - # Where the runtime looks for the module and jars by default (see - # RBS::WASM::Runtime). These are build artifacts, bundled into the JRuby gem. + # Where the runtime looks for the module by default (see RBS::WASM::Runtime). JRUBY_WASM_DIR = File.expand_path("lib/rbs/wasm", __dir__) - CHICORY_VERSION = ENV.fetch("CHICORY_VERSION", "1.7.5") - # `compiler` is Chicory's AOT compiler (wasm -> JVM bytecode); the asm* jars - # are the ow2 ASM libraries it depends on. Keep ASM_VERSION in sync with what - # the pinned Chicory release declares. - CHICORY_JARS = %w[wasm runtime log wasi compiler].freeze - ASM_VERSION = ENV.fetch("ASM_VERSION", "9.9.1") - ASM_JARS = %w[asm asm-tree asm-util asm-commons asm-analysis].freeze - - desc "Download the Chicory and ASM jars the JRuby runtime needs into lib/rbs/wasm/jars" + + desc "Download the Chicory and ASM jars the JRuby runtime needs into lib/rbs/wasm/jars (for running the test suite from source; not shipped in the gem)" task :vendor_jars do require "open-uri" require "fileutils" + # Coordinates live in the runtime so the gem (jar-dependencies) and this + # source-only download stay in sync. The released gem fetches these from + # Maven via jar-dependencies instead; this directory is gitignored. + require_relative "lib/rbs/wasm/jars" jars_dir = File.join(JRUBY_WASM_DIR, "jars") FileUtils.mkdir_p(jars_dir) - downloads = CHICORY_JARS.map { |name| ["#{name}.jar", "https://repo1.maven.org/maven2/com/dylibso/chicory/#{name}/#{CHICORY_VERSION}/#{name}-#{CHICORY_VERSION}.jar"] } - downloads += ASM_JARS.map { |name| ["#{name}.jar", "https://repo1.maven.org/maven2/org/ow2/asm/#{name}/#{ASM_VERSION}/#{name}-#{ASM_VERSION}.jar"] } - - downloads.each do |filename, url| + RBS::WASM::ALL_JARS.each do |group, artifact, version| + url = RBS::WASM.maven_url(group, artifact, version) puts "Downloading #{url}" - URI.open(url) { |io| File.binwrite(File.join(jars_dir, filename), io.read) } # steep:ignore + URI.open(url) { |io| File.binwrite(File.join(jars_dir, "#{artifact}.jar"), io.read) } # steep:ignore end - puts "Vendored Chicory #{CHICORY_VERSION} + ASM #{ASM_VERSION} into #{jars_dir}" + puts "Vendored Chicory #{RBS::WASM::CHICORY_VERSION} + ASM #{RBS::WASM::ASM_VERSION} into #{jars_dir}" end - desc "Assemble everything the JRuby gem needs: the .wasm and the Chicory jars" + desc "Assemble what the test suite needs to run on JRuby from source: the .wasm and the Chicory jars" task :jruby_setup => [:build, :vendor_jars] do cp WASM_OUTPUT, File.join(JRUBY_WASM_DIR, "rbs_parser.wasm") puts "JRuby runtime is ready under #{JRUBY_WASM_DIR}" diff --git a/Steepfile b/Steepfile index d1bc69f40..7534f8e87 100644 --- a/Steepfile +++ b/Steepfile @@ -13,6 +13,7 @@ target :lib do "lib/rbs/wasm/location.rb", "lib/rbs/wasm/runtime.rb", "lib/rbs/wasm/parser.rb", + "lib/rbs/wasm/jars.rb", ) library "pathname", "json", "logger", "monitor", "tsort", "uri", 'dbm', 'pstore', 'singleton', 'shellwords', 'fileutils', 'find', 'digest', 'prettyprint', 'yaml', "psych", "securerandom" diff --git a/docs/release.md b/docs/release.md index 459195828..ced17b022 100644 --- a/docs/release.md +++ b/docs/release.md @@ -7,9 +7,10 @@ Each release ships **two gems**: | `rbs-X.Y.Z.gem` | `ruby` (MRI) | C extension | `rake release` (re-builds it) | | `rbs-X.Y.Z-java.gem` | `java` (JRuby) | WebAssembly (`lib/rbs/wasm`) | Docker image, pushed manually | -The `-java` gem contains no native code — just `rbs_parser.wasm` plus the -Chicory/ASM jars — so it can be built once in any environment and runs on every -JRuby. +The `-java` gem contains no native code — just `rbs_parser.wasm`. The Chicory/ASM +jars it needs are not shipped in the gem; they are declared as `jar-dependencies` +requirements and fetched from Maven when the gem is installed. So the gem can be +built once in any environment and runs on every JRuby. ## Prerequisites @@ -44,7 +45,8 @@ The `java` gem is not built by `rake release`, so build and push it manually: # Build from the committed state (the gemspec's file list comes from `git ls-files`). $ docker build -f Dockerfile.jruby -t rbs-jruby . -# Assemble rbs_parser.wasm + jars and build the -java gem into ./pkg on the host. +# Build rbs_parser.wasm and the -java gem into ./pkg on the host. The Chicory/ASM +# jars are not bundled; they are fetched from Maven when the gem is installed. $ docker run --rm -e RBS_PLATFORM=java -v "$PWD/pkg:/out" rbs-jruby \ gem build rbs.gemspec -o /out/rbs-X.Y.Z-java.gem diff --git a/lib/rbs/wasm/jars.rb b/lib/rbs/wasm/jars.rb new file mode 100644 index 000000000..398af0e3e --- /dev/null +++ b/lib/rbs/wasm/jars.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module RBS + module WASM + # Single source of truth for the Maven coordinates of the jars the JRuby + # WebAssembly runtime needs. These jars are NOT shipped inside the gem; they + # are fetched from Maven Central, the canonical source, so that everyone + # resolves the same version and conflicting copies cannot be loaded at once. + # + # Three consumers share these coordinates: + # + # * rbs.gemspec - turns them into `jar-dependencies` requirements so + # the jars are downloaded when the `-java` gem is + # installed (see RBS::WASM.jar_requirements). + # * RBS::WASM::Runtime - `require_jar`s them at load time. + # * rake wasm:vendor_jars - downloads them into a gitignored directory for + # running the test suite from source. + CHICORY_VERSION = "1.7.5" + + # ow2 ASM, the bytecode library Chicory's AOT compiler depends on. Keep in + # sync with what the pinned Chicory release declares. + ASM_VERSION = "9.9.1" + + # Jars Chicory needs to load and run the module. + REQUIRED_JARS = [ + ["com.dylibso.chicory", "wasm", CHICORY_VERSION], + ["com.dylibso.chicory", "runtime", CHICORY_VERSION], + ["com.dylibso.chicory", "log", CHICORY_VERSION], + ["com.dylibso.chicory", "wasi", CHICORY_VERSION], + ].freeze + + # Jars for Chicory's ahead-of-time compiler (wasm -> JVM bytecode), which + # runs the parser ~8x faster than the interpreter. Optional: the runtime + # falls back to the interpreter when they are absent. `compiler` is Chicory's + # AOT compiler; the asm* jars are the ow2 ASM libraries it depends on. + OPTIONAL_JARS = [ + ["com.dylibso.chicory", "compiler", CHICORY_VERSION], + ["org.ow2.asm", "asm", ASM_VERSION], + ["org.ow2.asm", "asm-tree", ASM_VERSION], + ["org.ow2.asm", "asm-util", ASM_VERSION], + ["org.ow2.asm", "asm-commons", ASM_VERSION], + ["org.ow2.asm", "asm-analysis", ASM_VERSION], + ].freeze + + # Every jar the runtime can use, in load order. + ALL_JARS = (REQUIRED_JARS + OPTIONAL_JARS).freeze + + # The `spec.requirements` strings jar-dependencies reads at gem install time + # to fetch the jars from Maven, e.g. "jar com.dylibso.chicory:runtime, 1.7.5". + def self.jar_requirements + ALL_JARS.map { |group, artifact, version| "jar #{group}:#{artifact}, #{version}" } + end + + # The Maven Central download URL for a [group, artifact, version] coordinate. + def self.maven_url(group, artifact, version) + "https://repo1.maven.org/maven2/#{group.tr(".", "/")}/#{artifact}/#{version}/#{artifact}-#{version}.jar" + end + end +end diff --git a/lib/rbs/wasm/runtime.rb b/lib/rbs/wasm/runtime.rb index 5065b85e4..d2367842d 100644 --- a/lib/rbs/wasm/runtime.rb +++ b/lib/rbs/wasm/runtime.rb @@ -2,6 +2,7 @@ require "java" require "monitor" +require_relative "jars" module RBS module WASM @@ -15,16 +16,6 @@ module WASM class Runtime include MonitorMixin - # The Chicory jars the runtime needs at load time. - # Jars Chicory needs to load and run the module. - JARS = %w[wasm runtime log wasi].freeze - - # Jars for Chicory's ahead-of-time compiler (wasm -> JVM bytecode), which - # runs the parser ~8x faster than the interpreter. Optional: the runtime - # falls back to the interpreter when they are absent. asm* are the ow2 ASM - # libraries the compiler depends on. - OPTIONAL_JARS = %w[compiler asm asm-tree asm-util asm-commons asm-analysis].freeze - class << self def instance @instance ||= new @@ -34,8 +25,12 @@ def wasm_path ENV["RBS_WASM_PARSER"] || File.expand_path("rbs_parser.wasm", __dir__) end - def jars_dir - ENV["RBS_WASM_JARS"] || File.expand_path("jars", __dir__) + # A directory of jars vendored for running from source (development/CI), + # set by `rake wasm:vendor_jars` or `RBS_WASM_JARS`. Returns nil for an + # installed gem, where the jars come from Maven via jar-dependencies. + def local_jars_dir + dir = ENV["RBS_WASM_JARS"] || File.expand_path("jars", __dir__) + File.directory?(dir) ? dir : nil end end @@ -201,17 +196,31 @@ def machine_factory(wasm_module) nil end + # Puts the Chicory/ASM jars on the classpath. When running from source the + # jars are vendored into a local directory (see `rake wasm:vendor_jars`) and + # loaded by path; in the installed `-java` gem they are fetched from Maven + # by jar-dependencies and loaded with `require_jar`. The optional AOT + # compiler jars degrade gracefully: a missing or incompatible jar just + # leaves Chicory on the interpreter (see #machine_factory). def load_jars - JARS.each { |name| require jar_path(name) } - OPTIONAL_JARS.each do |name| - path = jar_path(name) - require path if File.exist?(path) + if (dir = self.class.local_jars_dir) + RBS::WASM::REQUIRED_JARS.each { |_group, artifact, _version| require File.join(dir, "#{artifact}.jar") } + RBS::WASM::OPTIONAL_JARS.each do |_group, artifact, _version| + path = File.join(dir, "#{artifact}.jar") + require path if File.exist?(path) + end + else + require "jar_dependencies" + RBS::WASM::REQUIRED_JARS.each { |group, artifact, version| require_jar(group, artifact, version) } + RBS::WASM::OPTIONAL_JARS.each do |group, artifact, version| + begin + require_jar(group, artifact, version) + rescue LoadError, StandardError, Java::JavaLang::LinkageError + # AOT compiler unavailable; the interpreter is used instead. + end + end end end - - def jar_path(name) - File.join(self.class.jars_dir, "#{name}.jar") - end end end end diff --git a/rbs.gemspec b/rbs.gemspec index ee78e0426..e765c89e1 100644 --- a/rbs.gemspec +++ b/rbs.gemspec @@ -38,18 +38,27 @@ Gem::Specification.new do |spec| # JRuby cannot load the MRI C extension. On JRuby (and in the `java` platform # gem, built with RBS_PLATFORM=java) RBS runs the WebAssembly-backed parser, so - # ship the prebuilt parser and the Chicory jars (assembled by - # `rake wasm:jruby_setup`) and skip the C extension. + # ship the prebuilt parser (built by `rake wasm:build`) and skip the C + # extension. The Chicory/ASM jars the runtime needs are NOT shipped in the gem: + # they are declared as `jar-dependencies` requirements below and fetched from + # Maven Central at install time (see lib/rbs/wasm/jars.rb). building_java_gem = ENV["RBS_PLATFORM"] == "java" on_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" if building_java_gem || on_jruby + require "rbs/wasm/jars" + # Only stamp the platform when building the release gem; leave it unset for # local development on JRuby so it still matches a `ruby` platform lockfile. spec.platform = "java" if building_java_gem spec.files += Dir.chdir(File.expand_path('..', __FILE__)) do - Dir.glob("lib/rbs/wasm/rbs_parser.wasm") + Dir.glob("lib/rbs/wasm/jars/*.jar") + Dir.glob("lib/rbs/wasm/rbs_parser.wasm") end + + # jar-dependencies (bundled with JRuby) downloads these jars from Maven when + # the gem is installed, keeping the gem small and avoiding conflicting copies. + spec.add_dependency "jar-dependencies", ">= 0.1.7" + RBS::WASM.jar_requirements.each { |requirement| spec.requirements << requirement } else spec.extensions = %w{ext/rbs_extension/extconf.rb} end From baf70dc99a14b3b6fe3826b9ca309f08889b6559 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Jun 2026 13:49:48 +0000 Subject: [PATCH 2/4] Load JRuby jars from ~/.m2 via require_jar only Follow Psych's model more closely and drop the development-only branch: the runtime now always loads the Chicory/ASM jars from the local Maven repository (~/.m2) with require_jar, both for the installed gem and when running from source. - runtime.rb: load_jars just require_jars each coordinate; the local vendored-directory path and the shared coordinates helper are gone. - Rakefile: `wasm:install_jars` runs Jars::Installer against rbs.gemspec to download the jars into ~/.m2 (the same path `gem install` uses), without copying them into the gem. Replaces the curl-based vendoring. - jruby.yml: download the jars on JRuby (jar-dependencies resolves through the JVM), after building the wasm on CRuby. - Remove lib/rbs/wasm/jars.rb; inline the coordinates in the gemspec and the runtime instead of abstracting them. Refs #3018 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RtMsDQEmuayTdn3rYsteYT --- .dockerignore | 3 +- .github/workflows/jruby.yml | 6 +++- .gitignore | 6 ++-- Dockerfile.jruby | 11 ++++--- Rakefile | 33 +++++++------------- Steepfile | 1 - lib/rbs/wasm/jars.rb | 59 ------------------------------------ lib/rbs/wasm/runtime.rb | 60 +++++++++++++++++-------------------- rbs.gemspec | 14 +++++++-- wasm/README.md | 7 +++-- 10 files changed, 66 insertions(+), 134 deletions(-) delete mode 100644 lib/rbs/wasm/jars.rb diff --git a/.dockerignore b/.dockerignore index a7ff961b4..0d2292965 100644 --- a/.dockerignore +++ b/.dockerignore @@ -19,9 +19,8 @@ doc/ datasets/ tmp/ -# Build artifacts — rebuilt inside the image by `rake wasm:jruby_setup` +# Build artifact — rebuilt inside the image by `rake wasm:jruby_setup` lib/rbs/wasm/*.wasm -lib/rbs/wasm/jars/ *.gem ext/**/*.o ext/**/*.so diff --git a/.github/workflows/jruby.yml b/.github/workflows/jruby.yml index c9131094f..75225f614 100644 --- a/.github/workflows/jruby.yml +++ b/.github/workflows/jruby.yml @@ -53,7 +53,7 @@ jobs: mkdir -p "$HOME/wasi-sdk" curl -sSL "$url" | tar xz --strip-components=1 -C "$HOME/wasi-sdk" echo "WASI_SDK_PATH=$HOME/wasi-sdk" >> "$GITHUB_ENV" - - name: Assemble the JRuby runtime (rbs_parser.wasm + Chicory jars) + - name: Build rbs_parser.wasm run: bundle exec rake wasm:jruby_setup - name: Set up JRuby @@ -63,5 +63,9 @@ jobs: bundler: none - name: Install runtime and test gems run: gem install prism rake rake-compiler test-unit rdoc rspec minitest json-schema pry --no-document + # jar-dependencies resolves through the JVM, so download the Chicory/ASM + # jars into ~/.m2 here on JRuby (not in the CRuby step above). + - name: Download the Chicory and ASM jars + run: jruby -S rake wasm:install_jars - name: Run the test suite on JRuby run: jruby -S rake test diff --git a/.gitignore b/.gitignore index e9f188f73..4e72d6ef8 100644 --- a/.gitignore +++ b/.gitignore @@ -33,8 +33,6 @@ rust/ruby-rbs/vendor/rbs/ # Compiled WebAssembly module (built by rake wasm:build) wasm/*.wasm -# JRuby runtime artifacts (assembled by rake wasm:jruby_setup). The .wasm is -# bundled in the -java gem; the jars are only for running from source (the gem -# fetches them from Maven via jar-dependencies). +# JRuby runtime artifact (built by rake wasm:jruby_setup, bundled in the -java +# gem). The Chicory/ASM jars are not here; they live in ~/.m2 (jar-dependencies). lib/rbs/wasm/*.wasm -lib/rbs/wasm/jars/ diff --git a/Dockerfile.jruby b/Dockerfile.jruby index 95715cffb..8d23516bd 100644 --- a/Dockerfile.jruby +++ b/Dockerfile.jruby @@ -3,8 +3,8 @@ # RBS can't load its MRI C extension on JRuby, so it parses through a # WebAssembly build of the parser (see lib/rbs/wasm and docs/wasm_serialization.md). # This single-stage image installs the WASI SDK, compiles rbs_parser.wasm and -# vendors the Chicory/ASM jars into lib/rbs/wasm/, then runs the test suite on -# JRuby. It mirrors .github/workflows/jruby.yml but is fully self-contained. +# downloads the Chicory/ASM jars into ~/.m2 (via jar-dependencies), then runs the +# test suite on JRuby. It mirrors .github/workflows/jruby.yml but is self-contained. # # docker build -f Dockerfile.jruby -t rbs-jruby . # docker run --rm rbs-jruby # run the test suite @@ -46,9 +46,8 @@ RUN gem install prism rake rake-compiler test-unit rdoc rspec minitest json-sche WORKDIR /rbs COPY . . -# Assemble the JRuby runtime: compile rbs_parser.wasm and download the -# Chicory + ASM jars into lib/rbs/wasm/. Runs on JRuby (clang is a subprocess, -# so the build is engine independent). -RUN rake wasm:jruby_setup +# Compile rbs_parser.wasm (clang is a subprocess, so the build is engine +# independent) and download the Chicory + ASM jars into ~/.m2 via jar-dependencies. +RUN rake wasm:jruby_setup wasm:install_jars CMD ["rake", "test"] diff --git a/Rakefile b/Rakefile index 5db3448c2..24bc29e5b 100644 --- a/Rakefile +++ b/Rakefile @@ -630,31 +630,20 @@ namespace :wasm do # Where the runtime looks for the module by default (see RBS::WASM::Runtime). JRUBY_WASM_DIR = File.expand_path("lib/rbs/wasm", __dir__) - desc "Download the Chicory and ASM jars the JRuby runtime needs into lib/rbs/wasm/jars (for running the test suite from source; not shipped in the gem)" - task :vendor_jars do - require "open-uri" - require "fileutils" - # Coordinates live in the runtime so the gem (jar-dependencies) and this - # source-only download stay in sync. The released gem fetches these from - # Maven via jar-dependencies instead; this directory is gitignored. - require_relative "lib/rbs/wasm/jars" - - jars_dir = File.join(JRUBY_WASM_DIR, "jars") - FileUtils.mkdir_p(jars_dir) - - RBS::WASM::ALL_JARS.each do |group, artifact, version| - url = RBS::WASM.maven_url(group, artifact, version) - puts "Downloading #{url}" - URI.open(url) { |io| File.binwrite(File.join(jars_dir, "#{artifact}.jar"), io.read) } # steep:ignore - end - - puts "Vendored Chicory #{RBS::WASM::CHICORY_VERSION} + ASM #{RBS::WASM::ASM_VERSION} into #{jars_dir}" + desc "Download the Chicory and ASM jars into the local Maven repository (~/.m2) for running the test suite from source. Run on JRuby." + task :install_jars do + # Reads the `jar` requirements from rbs.gemspec and downloads them (and their + # transitive deps) into ~/.m2, the same way `gem install` does. The jars are + # not copied into the gem, so nothing is shipped; RBS::WASM::Runtime loads + # them from ~/.m2 with require_jar. + require "jars/installer" + Jars::Installer.new("rbs.gemspec").install_jars(write_require_file: false) end - desc "Assemble what the test suite needs to run on JRuby from source: the .wasm and the Chicory jars" - task :jruby_setup => [:build, :vendor_jars] do + desc "Build rbs_parser.wasm and copy it next to RBS::WASM::Runtime" + task :jruby_setup => [:build] do cp WASM_OUTPUT, File.join(JRUBY_WASM_DIR, "rbs_parser.wasm") - puts "JRuby runtime is ready under #{JRUBY_WASM_DIR}" + puts "rbs_parser.wasm is ready under #{JRUBY_WASM_DIR}" end end diff --git a/Steepfile b/Steepfile index 7534f8e87..d1bc69f40 100644 --- a/Steepfile +++ b/Steepfile @@ -13,7 +13,6 @@ target :lib do "lib/rbs/wasm/location.rb", "lib/rbs/wasm/runtime.rb", "lib/rbs/wasm/parser.rb", - "lib/rbs/wasm/jars.rb", ) library "pathname", "json", "logger", "monitor", "tsort", "uri", 'dbm', 'pstore', 'singleton', 'shellwords', 'fileutils', 'find', 'digest', 'prettyprint', 'yaml', "psych", "securerandom" diff --git a/lib/rbs/wasm/jars.rb b/lib/rbs/wasm/jars.rb deleted file mode 100644 index 398af0e3e..000000000 --- a/lib/rbs/wasm/jars.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -module RBS - module WASM - # Single source of truth for the Maven coordinates of the jars the JRuby - # WebAssembly runtime needs. These jars are NOT shipped inside the gem; they - # are fetched from Maven Central, the canonical source, so that everyone - # resolves the same version and conflicting copies cannot be loaded at once. - # - # Three consumers share these coordinates: - # - # * rbs.gemspec - turns them into `jar-dependencies` requirements so - # the jars are downloaded when the `-java` gem is - # installed (see RBS::WASM.jar_requirements). - # * RBS::WASM::Runtime - `require_jar`s them at load time. - # * rake wasm:vendor_jars - downloads them into a gitignored directory for - # running the test suite from source. - CHICORY_VERSION = "1.7.5" - - # ow2 ASM, the bytecode library Chicory's AOT compiler depends on. Keep in - # sync with what the pinned Chicory release declares. - ASM_VERSION = "9.9.1" - - # Jars Chicory needs to load and run the module. - REQUIRED_JARS = [ - ["com.dylibso.chicory", "wasm", CHICORY_VERSION], - ["com.dylibso.chicory", "runtime", CHICORY_VERSION], - ["com.dylibso.chicory", "log", CHICORY_VERSION], - ["com.dylibso.chicory", "wasi", CHICORY_VERSION], - ].freeze - - # Jars for Chicory's ahead-of-time compiler (wasm -> JVM bytecode), which - # runs the parser ~8x faster than the interpreter. Optional: the runtime - # falls back to the interpreter when they are absent. `compiler` is Chicory's - # AOT compiler; the asm* jars are the ow2 ASM libraries it depends on. - OPTIONAL_JARS = [ - ["com.dylibso.chicory", "compiler", CHICORY_VERSION], - ["org.ow2.asm", "asm", ASM_VERSION], - ["org.ow2.asm", "asm-tree", ASM_VERSION], - ["org.ow2.asm", "asm-util", ASM_VERSION], - ["org.ow2.asm", "asm-commons", ASM_VERSION], - ["org.ow2.asm", "asm-analysis", ASM_VERSION], - ].freeze - - # Every jar the runtime can use, in load order. - ALL_JARS = (REQUIRED_JARS + OPTIONAL_JARS).freeze - - # The `spec.requirements` strings jar-dependencies reads at gem install time - # to fetch the jars from Maven, e.g. "jar com.dylibso.chicory:runtime, 1.7.5". - def self.jar_requirements - ALL_JARS.map { |group, artifact, version| "jar #{group}:#{artifact}, #{version}" } - end - - # The Maven Central download URL for a [group, artifact, version] coordinate. - def self.maven_url(group, artifact, version) - "https://repo1.maven.org/maven2/#{group.tr(".", "/")}/#{artifact}/#{version}/#{artifact}-#{version}.jar" - end - end -end diff --git a/lib/rbs/wasm/runtime.rb b/lib/rbs/wasm/runtime.rb index d2367842d..7af153cc4 100644 --- a/lib/rbs/wasm/runtime.rb +++ b/lib/rbs/wasm/runtime.rb @@ -2,7 +2,6 @@ require "java" require "monitor" -require_relative "jars" module RBS module WASM @@ -11,8 +10,9 @@ module WASM # source string into the module's linear memory, runs the parser, and returns # the serialized result for RBS::WASM::Deserializer to rebuild. # - # Chicory is a pure-Java runtime, so there is no native dependency: only the - # `.wasm` and the Chicory jars need to ship with the gem. + # Chicory is a pure-Java runtime, so there is no native dependency. The + # `.wasm` ships in the gem; the Chicory jars are fetched from Maven by + # jar-dependencies (see load_jars and rbs.gemspec). class Runtime include MonitorMixin @@ -24,14 +24,6 @@ def instance def wasm_path ENV["RBS_WASM_PARSER"] || File.expand_path("rbs_parser.wasm", __dir__) end - - # A directory of jars vendored for running from source (development/CI), - # set by `rake wasm:vendor_jars` or `RBS_WASM_JARS`. Returns nil for an - # installed gem, where the jars come from Maven via jar-dependencies. - def local_jars_dir - dir = ENV["RBS_WASM_JARS"] || File.expand_path("jars", __dir__) - File.directory?(dir) ? dir : nil - end end def initialize @@ -196,29 +188,31 @@ def machine_factory(wasm_module) nil end - # Puts the Chicory/ASM jars on the classpath. When running from source the - # jars are vendored into a local directory (see `rake wasm:vendor_jars`) and - # loaded by path; in the installed `-java` gem they are fetched from Maven - # by jar-dependencies and loaded with `require_jar`. The optional AOT - # compiler jars degrade gracefully: a missing or incompatible jar just - # leaves Chicory on the interpreter (see #machine_factory). + # Loads the Chicory/ASM jars onto the classpath. jar-dependencies finds them + # in the local Maven repository (~/.m2); they get there when the gem is + # installed, or via `rake wasm:install_jars` when running from source. Keep + # these versions in sync with the `jar` requirements in rbs.gemspec. def load_jars - if (dir = self.class.local_jars_dir) - RBS::WASM::REQUIRED_JARS.each { |_group, artifact, _version| require File.join(dir, "#{artifact}.jar") } - RBS::WASM::OPTIONAL_JARS.each do |_group, artifact, _version| - path = File.join(dir, "#{artifact}.jar") - require path if File.exist?(path) - end - else - require "jar_dependencies" - RBS::WASM::REQUIRED_JARS.each { |group, artifact, version| require_jar(group, artifact, version) } - RBS::WASM::OPTIONAL_JARS.each do |group, artifact, version| - begin - require_jar(group, artifact, version) - rescue LoadError, StandardError, Java::JavaLang::LinkageError - # AOT compiler unavailable; the interpreter is used instead. - end - end + require "jar_dependencies" + + # Needed to load and run the module. + require_jar "com.dylibso.chicory", "wasm", "1.7.5" + require_jar "com.dylibso.chicory", "runtime", "1.7.5" + require_jar "com.dylibso.chicory", "log", "1.7.5" + require_jar "com.dylibso.chicory", "wasi", "1.7.5" + + # Chicory's ahead-of-time compiler (and the ASM libraries it depends on) + # runs the parser ~8x faster than the interpreter. Optional: if a jar is + # missing or incompatible, fall back to the interpreter (see machine_factory). + begin + require_jar "com.dylibso.chicory", "compiler", "1.7.5" + require_jar "org.ow2.asm", "asm", "9.9.1" + require_jar "org.ow2.asm", "asm-tree", "9.9.1" + require_jar "org.ow2.asm", "asm-util", "9.9.1" + require_jar "org.ow2.asm", "asm-commons", "9.9.1" + require_jar "org.ow2.asm", "asm-analysis", "9.9.1" + rescue LoadError, StandardError, Java::JavaLang::LinkageError + # AOT compiler unavailable; the interpreter is used instead. end end end diff --git a/rbs.gemspec b/rbs.gemspec index e765c89e1..8b848742a 100644 --- a/rbs.gemspec +++ b/rbs.gemspec @@ -46,8 +46,6 @@ Gem::Specification.new do |spec| on_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" if building_java_gem || on_jruby - require "rbs/wasm/jars" - # Only stamp the platform when building the release gem; leave it unset for # local development on JRuby so it still matches a `ruby` platform lockfile. spec.platform = "java" if building_java_gem @@ -57,8 +55,18 @@ Gem::Specification.new do |spec| # jar-dependencies (bundled with JRuby) downloads these jars from Maven when # the gem is installed, keeping the gem small and avoiding conflicting copies. + # Keep the versions in sync with RBS::WASM::Runtime#load_jars. spec.add_dependency "jar-dependencies", ">= 0.1.7" - RBS::WASM.jar_requirements.each { |requirement| spec.requirements << requirement } + spec.requirements << "jar com.dylibso.chicory:wasm, 1.7.5" + spec.requirements << "jar com.dylibso.chicory:runtime, 1.7.5" + spec.requirements << "jar com.dylibso.chicory:log, 1.7.5" + spec.requirements << "jar com.dylibso.chicory:wasi, 1.7.5" + spec.requirements << "jar com.dylibso.chicory:compiler, 1.7.5" + spec.requirements << "jar org.ow2.asm:asm, 9.9.1" + spec.requirements << "jar org.ow2.asm:asm-tree, 9.9.1" + spec.requirements << "jar org.ow2.asm:asm-util, 9.9.1" + spec.requirements << "jar org.ow2.asm:asm-commons, 9.9.1" + spec.requirements << "jar org.ow2.asm:asm-analysis, 9.9.1" else spec.extensions = %w{ext/rbs_extension/extconf.rb} end diff --git a/wasm/README.md b/wasm/README.md index 71e513a63..89a652cfd 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -19,9 +19,10 @@ The build needs the [WASI SDK](https://github.com/WebAssembly/wasi-sdk/releases) ```console $ export WASI_SDK_PATH=/path/to/wasi-sdk -$ rake wasm:build # compile rbs_parser.wasm -$ rake wasm:check # also smoke-test it (needs wasmtime) -$ rake wasm:jruby_setup # assemble lib/rbs/wasm/ for JRuby (wasm + Chicory jars) +$ rake wasm:build # compile rbs_parser.wasm +$ rake wasm:check # also smoke-test it (needs wasmtime) +$ rake wasm:jruby_setup # copy rbs_parser.wasm into lib/rbs/wasm/ for JRuby +$ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 (run on JRuby) ``` The compiled `rbs_parser.wasm` is a build artifact and is not checked in. From 38446c5afbd02fa7837b2262f1f0dd1714065bc1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 13:02:40 +0000 Subject: [PATCH 3/4] Load jars via a generated rbs_jars.rb instead of a hand-written list jar-dependencies can generate the require_jar calls from the gem's `jar` requirements, so the runtime no longer repeats the coordinate list that the gemspec already declares. - `rake wasm:install_jars` now runs Jars::Installer with its default require-file generation: it downloads the jars into ~/.m2 and writes lib/rbs_jars.rb (require_jar calls for the whole resolved set). - runtime.rb: load_jars is just `require "rbs_jars"`. - rbs.gemspec: ship the generated lib/rbs_jars.rb alongside rbs_parser.wasm; the `jar` requirements stay the single source. - lib/rbs_jars.rb is a build artifact (gitignored, Steep-ignored, rebuilt in the Docker image and CI). Refs #3018 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RtMsDQEmuayTdn3rYsteYT --- .dockerignore | 4 +++- .github/workflows/jruby.yml | 5 +++-- .gitignore | 6 ++++-- Rakefile | 10 +++++----- Steepfile | 2 ++ lib/rbs/wasm/runtime.rb | 30 +++++------------------------- rbs.gemspec | 7 +++++-- wasm/README.md | 3 ++- 8 files changed, 29 insertions(+), 38 deletions(-) diff --git a/.dockerignore b/.dockerignore index 0d2292965..2c7707a18 100644 --- a/.dockerignore +++ b/.dockerignore @@ -19,8 +19,10 @@ doc/ datasets/ tmp/ -# Build artifact — rebuilt inside the image by `rake wasm:jruby_setup` +# Build artifacts — rebuilt inside the image by `rake wasm:jruby_setup` and +# `rake wasm:install_jars` lib/rbs/wasm/*.wasm +lib/rbs_jars.rb *.gem ext/**/*.o ext/**/*.so diff --git a/.github/workflows/jruby.yml b/.github/workflows/jruby.yml index 75225f614..c8612b01a 100644 --- a/.github/workflows/jruby.yml +++ b/.github/workflows/jruby.yml @@ -64,8 +64,9 @@ jobs: - name: Install runtime and test gems run: gem install prism rake rake-compiler test-unit rdoc rspec minitest json-schema pry --no-document # jar-dependencies resolves through the JVM, so download the Chicory/ASM - # jars into ~/.m2 here on JRuby (not in the CRuby step above). - - name: Download the Chicory and ASM jars + # jars into ~/.m2 and generate lib/rbs_jars.rb here on JRuby (jar-dependencies + # is not available in the CRuby step above). + - name: Download the jars and generate rbs_jars.rb run: jruby -S rake wasm:install_jars - name: Run the test suite on JRuby run: jruby -S rake test diff --git a/.gitignore b/.gitignore index 4e72d6ef8..b11758538 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,8 @@ rust/ruby-rbs/vendor/rbs/ # Compiled WebAssembly module (built by rake wasm:build) wasm/*.wasm -# JRuby runtime artifact (built by rake wasm:jruby_setup, bundled in the -java -# gem). The Chicory/ASM jars are not here; they live in ~/.m2 (jar-dependencies). +# JRuby runtime artifacts, bundled in the -java gem: the parser (rake +# wasm:jruby_setup) and the generated require_jar file (rake wasm:install_jars). +# The Chicory/ASM jars themselves live in ~/.m2 (jar-dependencies), not here. lib/rbs/wasm/*.wasm +lib/rbs_jars.rb diff --git a/Rakefile b/Rakefile index 24bc29e5b..929282daf 100644 --- a/Rakefile +++ b/Rakefile @@ -630,14 +630,14 @@ namespace :wasm do # Where the runtime looks for the module by default (see RBS::WASM::Runtime). JRUBY_WASM_DIR = File.expand_path("lib/rbs/wasm", __dir__) - desc "Download the Chicory and ASM jars into the local Maven repository (~/.m2) for running the test suite from source. Run on JRuby." + desc "Download the Chicory/ASM jars into ~/.m2 and generate lib/rbs_jars.rb. Run on JRuby." task :install_jars do # Reads the `jar` requirements from rbs.gemspec and downloads them (and their - # transitive deps) into ~/.m2, the same way `gem install` does. The jars are - # not copied into the gem, so nothing is shipped; RBS::WASM::Runtime loads - # them from ~/.m2 with require_jar. + # transitive deps) into ~/.m2, the same way `gem install` does, then writes + # lib/rbs_jars.rb with the require_jar calls RBS::WASM::Runtime loads. The jars + # themselves are not copied into the gem, so nothing extra is shipped. require "jars/installer" - Jars::Installer.new("rbs.gemspec").install_jars(write_require_file: false) + Jars::Installer.new("rbs.gemspec").install_jars end desc "Build rbs_parser.wasm and copy it next to RBS::WASM::Runtime" diff --git a/Steepfile b/Steepfile index d1bc69f40..e9267ee99 100644 --- a/Steepfile +++ b/Steepfile @@ -13,6 +13,8 @@ target :lib do "lib/rbs/wasm/location.rb", "lib/rbs/wasm/runtime.rb", "lib/rbs/wasm/parser.rb", + # Generated by `rake wasm:install_jars` (jar-dependencies require_jar calls). + "lib/rbs_jars.rb", ) library "pathname", "json", "logger", "monitor", "tsort", "uri", 'dbm', 'pstore', 'singleton', 'shellwords', 'fileutils', 'find', 'digest', 'prettyprint', 'yaml', "psych", "securerandom" diff --git a/lib/rbs/wasm/runtime.rb b/lib/rbs/wasm/runtime.rb index 7af153cc4..0203c4499 100644 --- a/lib/rbs/wasm/runtime.rb +++ b/lib/rbs/wasm/runtime.rb @@ -188,32 +188,12 @@ def machine_factory(wasm_module) nil end - # Loads the Chicory/ASM jars onto the classpath. jar-dependencies finds them - # in the local Maven repository (~/.m2); they get there when the gem is - # installed, or via `rake wasm:install_jars` when running from source. Keep - # these versions in sync with the `jar` requirements in rbs.gemspec. + # Loads the Chicory/ASM jars onto the classpath. lib/rbs_jars.rb is generated + # from the `jar` requirements in rbs.gemspec (by `rake wasm:install_jars`, and + # refreshed by jar-dependencies at gem install); it require_jars each jar from + # the local Maven repository (~/.m2). def load_jars - require "jar_dependencies" - - # Needed to load and run the module. - require_jar "com.dylibso.chicory", "wasm", "1.7.5" - require_jar "com.dylibso.chicory", "runtime", "1.7.5" - require_jar "com.dylibso.chicory", "log", "1.7.5" - require_jar "com.dylibso.chicory", "wasi", "1.7.5" - - # Chicory's ahead-of-time compiler (and the ASM libraries it depends on) - # runs the parser ~8x faster than the interpreter. Optional: if a jar is - # missing or incompatible, fall back to the interpreter (see machine_factory). - begin - require_jar "com.dylibso.chicory", "compiler", "1.7.5" - require_jar "org.ow2.asm", "asm", "9.9.1" - require_jar "org.ow2.asm", "asm-tree", "9.9.1" - require_jar "org.ow2.asm", "asm-util", "9.9.1" - require_jar "org.ow2.asm", "asm-commons", "9.9.1" - require_jar "org.ow2.asm", "asm-analysis", "9.9.1" - rescue LoadError, StandardError, Java::JavaLang::LinkageError - # AOT compiler unavailable; the interpreter is used instead. - end + require "rbs_jars" end end end diff --git a/rbs.gemspec b/rbs.gemspec index 8b848742a..cceeea867 100644 --- a/rbs.gemspec +++ b/rbs.gemspec @@ -49,13 +49,16 @@ Gem::Specification.new do |spec| # Only stamp the platform when building the release gem; leave it unset for # local development on JRuby so it still matches a `ruby` platform lockfile. spec.platform = "java" if building_java_gem + # rbs_parser.wasm and the generated rbs_jars.rb (the require_jar calls the + # runtime loads) are build artifacts produced by `rake wasm:jruby_setup` and + # `rake wasm:install_jars`; they are not tracked in git, so add them here. spec.files += Dir.chdir(File.expand_path('..', __FILE__)) do - Dir.glob("lib/rbs/wasm/rbs_parser.wasm") + Dir.glob("lib/rbs/wasm/rbs_parser.wasm") + Dir.glob("lib/rbs_jars.rb") end # jar-dependencies (bundled with JRuby) downloads these jars from Maven when # the gem is installed, keeping the gem small and avoiding conflicting copies. - # Keep the versions in sync with RBS::WASM::Runtime#load_jars. + # `rake wasm:install_jars` turns these requirements into lib/rbs_jars.rb. spec.add_dependency "jar-dependencies", ">= 0.1.7" spec.requirements << "jar com.dylibso.chicory:wasm, 1.7.5" spec.requirements << "jar com.dylibso.chicory:runtime, 1.7.5" diff --git a/wasm/README.md b/wasm/README.md index 89a652cfd..a5ae57a09 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -22,7 +22,8 @@ $ export WASI_SDK_PATH=/path/to/wasi-sdk $ rake wasm:build # compile rbs_parser.wasm $ rake wasm:check # also smoke-test it (needs wasmtime) $ rake wasm:jruby_setup # copy rbs_parser.wasm into lib/rbs/wasm/ for JRuby -$ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 (run on JRuby) +$ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 and + # generate lib/rbs_jars.rb (run on JRuby) ``` The compiled `rbs_parser.wasm` is a build artifact and is not checked in. From 46c8ddc15cdef9573734e436dc3be8af07ec82a8 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 14:29:19 +0000 Subject: [PATCH 4/4] Commit a hand-maintained rbs_jars.rb for the JRuby jar loading Runtime loads the Chicory/ASM jars with a single `require "rbs_jars"`. lib/rbs_jars.rb is committed and hand-maintained rather than generated: jar-dependencies' require-file generator mangles the `com.dylibso.chicory:runtime` artifact id into `jar` (the artifact name collides with a Maven scope keyword), which would make the installed gem fail to load Chicory's runtime jar. Omitting the "this is a generated file" marker also stops jar-dependencies from overwriting the file at gem install. Verified on JRuby 10.0.6: `rake wasm:install_jars` resolves the `jar` requirements to exactly these ten jars and downloads them into ~/.m2, `require "rbs_jars"` loads them, and the Chicory classes the runtime uses link successfully. - runtime.rb: inline `require "rbs_jars"` (drop the load_jars method). - Rakefile: install_jars forces the java platform (the installer skips non-java gems) and downloads only (the require file is hand-maintained). - ship lib/rbs_jars.rb via git ls-files; drop its ignore entries. Refs #3018 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RtMsDQEmuayTdn3rYsteYT --- .dockerignore | 4 +--- .github/workflows/jruby.yml | 6 +++--- .gitignore | 7 +++---- Rakefile | 16 ++++++++++------ lib/rbs/wasm/runtime.rb | 14 +++++--------- lib/rbs_jars.rb | 21 +++++++++++++++++++++ rbs.gemspec | 9 ++++----- wasm/README.md | 3 +-- 8 files changed, 48 insertions(+), 32 deletions(-) create mode 100644 lib/rbs_jars.rb diff --git a/.dockerignore b/.dockerignore index 2c7707a18..0d2292965 100644 --- a/.dockerignore +++ b/.dockerignore @@ -19,10 +19,8 @@ doc/ datasets/ tmp/ -# Build artifacts — rebuilt inside the image by `rake wasm:jruby_setup` and -# `rake wasm:install_jars` +# Build artifact — rebuilt inside the image by `rake wasm:jruby_setup` lib/rbs/wasm/*.wasm -lib/rbs_jars.rb *.gem ext/**/*.o ext/**/*.so diff --git a/.github/workflows/jruby.yml b/.github/workflows/jruby.yml index c8612b01a..8b4dbbaf1 100644 --- a/.github/workflows/jruby.yml +++ b/.github/workflows/jruby.yml @@ -64,9 +64,9 @@ jobs: - name: Install runtime and test gems run: gem install prism rake rake-compiler test-unit rdoc rspec minitest json-schema pry --no-document # jar-dependencies resolves through the JVM, so download the Chicory/ASM - # jars into ~/.m2 and generate lib/rbs_jars.rb here on JRuby (jar-dependencies - # is not available in the CRuby step above). - - name: Download the jars and generate rbs_jars.rb + # jars into ~/.m2 here on JRuby (jar-dependencies is not available in the + # CRuby step above). + - name: Download the Chicory and ASM jars run: jruby -S rake wasm:install_jars - name: Run the test suite on JRuby run: jruby -S rake test diff --git a/.gitignore b/.gitignore index b11758538..9ab87e2db 100644 --- a/.gitignore +++ b/.gitignore @@ -33,8 +33,7 @@ rust/ruby-rbs/vendor/rbs/ # Compiled WebAssembly module (built by rake wasm:build) wasm/*.wasm -# JRuby runtime artifacts, bundled in the -java gem: the parser (rake -# wasm:jruby_setup) and the generated require_jar file (rake wasm:install_jars). -# The Chicory/ASM jars themselves live in ~/.m2 (jar-dependencies), not here. +# JRuby runtime artifact (built by rake wasm:jruby_setup, bundled in the -java +# gem). The require_jar file lib/rbs_jars.rb is committed; the Chicory/ASM jars +# themselves live in ~/.m2 (jar-dependencies), not here. lib/rbs/wasm/*.wasm -lib/rbs_jars.rb diff --git a/Rakefile b/Rakefile index 929282daf..bc1f34f0a 100644 --- a/Rakefile +++ b/Rakefile @@ -630,14 +630,18 @@ namespace :wasm do # Where the runtime looks for the module by default (see RBS::WASM::Runtime). JRUBY_WASM_DIR = File.expand_path("lib/rbs/wasm", __dir__) - desc "Download the Chicory/ASM jars into ~/.m2 and generate lib/rbs_jars.rb. Run on JRuby." + desc "Download the Chicory/ASM jars into the local Maven repository (~/.m2). Run on JRuby." task :install_jars do - # Reads the `jar` requirements from rbs.gemspec and downloads them (and their - # transitive deps) into ~/.m2, the same way `gem install` does, then writes - # lib/rbs_jars.rb with the require_jar calls RBS::WASM::Runtime loads. The jars - # themselves are not copied into the gem, so nothing extra is shipped. + # Resolves the `jar` requirements from rbs.gemspec via Maven and downloads + # them (and their transitive deps) into ~/.m2, the same way `gem install` + # does; the jars are not copied into the gem. The platform is forced to java + # because Jars::Installer skips non-java gems, and write_require_file is false + # because lib/rbs_jars.rb is hand-maintained (the generator mangles the + # `com.dylibso.chicory:runtime` artifact id). require "jars/installer" - Jars::Installer.new("rbs.gemspec").install_jars + spec = Gem::Specification.load("rbs.gemspec") + spec.platform = "java" + Jars::Installer.new(spec).install_jars(write_require_file: false) end desc "Build rbs_parser.wasm and copy it next to RBS::WASM::Runtime" diff --git a/lib/rbs/wasm/runtime.rb b/lib/rbs/wasm/runtime.rb index 0203c4499..40859c9eb 100644 --- a/lib/rbs/wasm/runtime.rb +++ b/lib/rbs/wasm/runtime.rb @@ -12,7 +12,7 @@ module WASM # # Chicory is a pure-Java runtime, so there is no native dependency. The # `.wasm` ships in the gem; the Chicory jars are fetched from Maven by - # jar-dependencies (see load_jars and rbs.gemspec). + # jar-dependencies (see lib/rbs_jars.rb and rbs.gemspec). class Runtime include MonitorMixin @@ -28,7 +28,10 @@ def wasm_path def initialize super() - load_jars + # rbs_jars.rb require_jars the Chicory/ASM jars from the local Maven + # repository (~/.m2), where jar-dependencies puts them at gem install (or + # `rake wasm:install_jars` when running from source). + require "rbs_jars" @wasm = build_instance @memory = @wasm.memory @alloc = @wasm.export("rbs_wasm_alloc") @@ -188,13 +191,6 @@ def machine_factory(wasm_module) nil end - # Loads the Chicory/ASM jars onto the classpath. lib/rbs_jars.rb is generated - # from the `jar` requirements in rbs.gemspec (by `rake wasm:install_jars`, and - # refreshed by jar-dependencies at gem install); it require_jars each jar from - # the local Maven repository (~/.m2). - def load_jars - require "rbs_jars" - end end end end diff --git a/lib/rbs_jars.rb b/lib/rbs_jars.rb new file mode 100644 index 000000000..d0c0a8f2d --- /dev/null +++ b/lib/rbs_jars.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true +# +# Loads the Chicory/ASM jars for the JRuby WebAssembly parser (RBS::WASM::Runtime) +# from the local Maven repository. Hand-maintained, NOT auto-generated: the +# jar-dependencies generator mangles the `com.dylibso.chicory:runtime` artifact id +# into `jar` (its artifact name collides with a Maven scope keyword). Leaving out +# the usual "this is a generated file" marker also stops jar-dependencies from +# overwriting this file at gem install. Keep this list in sync with the `jar` +# requirements in rbs.gemspec. +require "jar_dependencies" + +require_jar "com.dylibso.chicory", "wasm", "1.7.5" +require_jar "com.dylibso.chicory", "runtime", "1.7.5" +require_jar "com.dylibso.chicory", "log", "1.7.5" +require_jar "com.dylibso.chicory", "wasi", "1.7.5" +require_jar "com.dylibso.chicory", "compiler", "1.7.5" +require_jar "org.ow2.asm", "asm", "9.9.1" +require_jar "org.ow2.asm", "asm-tree", "9.9.1" +require_jar "org.ow2.asm", "asm-util", "9.9.1" +require_jar "org.ow2.asm", "asm-commons", "9.9.1" +require_jar "org.ow2.asm", "asm-analysis", "9.9.1" diff --git a/rbs.gemspec b/rbs.gemspec index cceeea867..f155c616b 100644 --- a/rbs.gemspec +++ b/rbs.gemspec @@ -49,16 +49,15 @@ Gem::Specification.new do |spec| # Only stamp the platform when building the release gem; leave it unset for # local development on JRuby so it still matches a `ruby` platform lockfile. spec.platform = "java" if building_java_gem - # rbs_parser.wasm and the generated rbs_jars.rb (the require_jar calls the - # runtime loads) are build artifacts produced by `rake wasm:jruby_setup` and - # `rake wasm:install_jars`; they are not tracked in git, so add them here. + # rbs_parser.wasm is a build artifact (not tracked in git), so add it + # explicitly. lib/rbs_jars.rb is committed, so git ls-files already has it. spec.files += Dir.chdir(File.expand_path('..', __FILE__)) do - Dir.glob("lib/rbs/wasm/rbs_parser.wasm") + Dir.glob("lib/rbs_jars.rb") + Dir.glob("lib/rbs/wasm/rbs_parser.wasm") end # jar-dependencies (bundled with JRuby) downloads these jars from Maven when # the gem is installed, keeping the gem small and avoiding conflicting copies. - # `rake wasm:install_jars` turns these requirements into lib/rbs_jars.rb. + # lib/rbs_jars.rb require_jars them at runtime; keep the two lists in sync. spec.add_dependency "jar-dependencies", ">= 0.1.7" spec.requirements << "jar com.dylibso.chicory:wasm, 1.7.5" spec.requirements << "jar com.dylibso.chicory:runtime, 1.7.5" diff --git a/wasm/README.md b/wasm/README.md index a5ae57a09..89a652cfd 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -22,8 +22,7 @@ $ export WASI_SDK_PATH=/path/to/wasi-sdk $ rake wasm:build # compile rbs_parser.wasm $ rake wasm:check # also smoke-test it (needs wasmtime) $ rake wasm:jruby_setup # copy rbs_parser.wasm into lib/rbs/wasm/ for JRuby -$ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 and - # generate lib/rbs_jars.rb (run on JRuby) +$ rake wasm:install_jars # download the Chicory/ASM jars into ~/.m2 (run on JRuby) ``` The compiled `rbs_parser.wasm` is a build artifact and is not checked in.