leptris 1.9.174.0 → 1.9.174.2

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: 7e3fde2c39415a90a71f3505346bc86012166fccc1fa63b1918e97d1d6c7d0d3
4
- data.tar.gz: 3df812e0ed1b0c00cbceacff3c59c37fbe468ada8a05eb411ad6e89b792cb09e
3
+ metadata.gz: fb172d69b816cff764e249cd5708a2394e7e4886a5c5281bf69160f876550c20
4
+ data.tar.gz: 22ff15b7a5dbaee59a9643f150662321e6f52267cb96b47c6621e73957615f46
5
5
  SHA512:
6
- metadata.gz: 5f89f5a33495dfe354d6f87302981f998249c10fc0e7c64901c0b85234cb4d621c43612b221322e7e199a608217db9f94b5b4c728eb58ff2a905f352dc0f0fcf
7
- data.tar.gz: b0245f06f74abbf56462dd2596e071a5034f903b0567a45c57987e96d94f36552f1aba1d0d0b2f476f4715d20cef5512384da4118da567fe00c150fa8fd9e5df
6
+ metadata.gz: d86e101b19a89c87b3ff67fc6fae563da827d3b389618fbada51cb9bcd387e772b474315e4d3d9f21bd6dd4bb1429df5b5f1de624787fc02db889dd6b1dc6efc
7
+ data.tar.gz: c20c6f8446a7aef0b0d08c672deccf1d5aaa7653fe04e8f69c6a8a1b0f641f6bb5221d44f0c28f0cabcfb901ce2762ce5eed3ed6fa427b2231935bda1c6bd9b9
data/CHANGELOG.md CHANGED
@@ -5,6 +5,42 @@ All notable changes to Leptris will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.9.174.2] - 2026-09-15
9
+
10
+ ### Changed
11
+
12
+ - **The native layer returns to Windows, one DLL per Ruby minor
13
+ (#227)**: a PE DLL must bind its build Ruby's runtime, so the
14
+ Windows platform gems now ship `native-3.3.so` / `native-3.4.so`
15
+ / `native-4.0.so` and the loader picks by `RUBY_VERSION` at
16
+ require. The release workflow compiles each minor's artifact on
17
+ the Windows legs (a minor unavailable on a runner degrades to
18
+ the loud FFI fallback for that cell); local `rake compile` on
19
+ Windows builds the current minor's DLL. Windows test legs now
20
+ exercise the full native suite instead of FFI-only.
21
+
22
+ ## [1.9.174.1] - 2026-09-15
23
+
24
+ ### Fixed
25
+
26
+ - **Prebuilt native layer now loads on every Ruby minor (#207)**:
27
+ the Linux bundles were linked by mkmf against
28
+ `libruby.so.3.3` (plus a runner-specific RUNPATH), so they
29
+ failed to load on Ruby 3.4/4.0 — darwin's
30
+ `-undefined dynamic_lookup` contract now applies on Linux too:
31
+ the .so links without libruby and resolves rb_* from the
32
+ loading interpreter, one artifact serving every Ruby minor. A
33
+ build-log guard fails the compile if the artifact ever
34
+ references libruby again.
35
+ - **Windows platform gems no longer ship the native bundle**: a
36
+ PE DLL cannot leave Ruby imports unresolved — it would bind to
37
+ the build Ruby's `x64-ucrt-rubyNNN.dll` and fail on other
38
+ minors. The FFI surface is the Windows contract.
39
+ - **The auto-enable fallback is loud**: a failed native load now
40
+ warns (reason + FFI notice) on stderr instead of degrading
41
+ silently — the silent fallback is what hid #207 behind a
42
+ walk-speed regression.
43
+
8
44
  ## [1.9.174.0] - 2026-09-15
9
45
 
10
46
  ### Changed
data/Rakefile CHANGED
@@ -127,33 +127,54 @@ task :compile do
127
127
  # Opt-in native read layer ext (#185): built and vendored beside
128
128
  # the library — no compile at install; resolves libleptris at
129
129
  # require time via dlsym.
130
- ext_dir = "ext/leptris/native"
131
- Dir.chdir(ext_dir) do
132
- sh "ruby extconf.rb"
130
+ if Gem.win_platform?
131
+ # #207: a PE DLL cannot leave Ruby imports unresolved — it
132
+ # binds the build Ruby's x64-ucrt-rubyNNN.dll. The Windows
133
+ # gems therefore ship one DLL per supported Ruby minor
134
+ # (native-<minor>.so), and native_layer picks by RUBY_VERSION
135
+ # (#227). Local compile builds just the current minor's DLL;
136
+ # the release workflow runs the build script under 3.3/3.4/
137
+ # 4.0 to produce the full set.
138
+ sh "#{RbConfig.ruby} ext/build_windows_native.rb"
139
+ else
140
+ ext_dir = "ext/leptris/native"
141
+ Dir.chdir(ext_dir) do
142
+ sh "ruby extconf.rb"
143
+ if RUBY_PLATFORM =~ /darwin/
144
+ # Link the bundle ourselves: setup-ruby's custom rubies
145
+ # make mkmf link libruby by absolute runner path no matter
146
+ # which RbConfig entries are cleared, and any libruby
147
+ # LC_LOAD_DYLIB is unresolvable on user machines. Compile
148
+ # via the Makefile, link with pure -undefined
149
+ # dynamic_lookup (Ruby symbols resolve from the loading
150
+ # interpreter) and a conservative deployment target.
151
+ sh "make native.o"
152
+ sh "cc -dynamic -bundle -undefined dynamic_lookup " \
153
+ "-mmacosx-version-min=#{ENV['MACOSX_DEPLOYMENT_TARGET'] || '11.0'} " \
154
+ "-o native.bundle native.o"
155
+ else
156
+ # #207: the darwin contract on Linux too — mkmf's `make`
157
+ # linked libruby.so.3.3 (plus a runner runpath), which
158
+ # failed to load on 3.4/4.0. Link WITHOUT libruby: one
159
+ # .so serves every Ruby minor; rb_* resolve from the
160
+ # loading interpreter at dlopen (static rubies export
161
+ # their symbols via -rdynamic, like any extension .so).
162
+ sh "make native.o"
163
+ sh "#{RbConfig::CONFIG['CC']} -shared -fPIC -o native.so native.o"
164
+ # Guard the contract in the build log.
165
+ sh "if strings native.so | grep -q libruby; then " \
166
+ "echo 'ERROR: native.so links libruby (#207)'; exit 1; fi"
167
+ end
168
+ end
169
+ bundle = Dir.glob("#{ext_dir}/native.{bundle,so,dll}").first
170
+ raise "native layer bundle not found after build" unless bundle
133
171
  if RUBY_PLATFORM =~ /darwin/
134
- # Link the bundle ourselves: setup-ruby's custom rubies make
135
- # mkmf link libruby by absolute runner path no matter which
136
- # RbConfig entries are cleared, and any libruby
137
- # LC_LOAD_DYLIB is unresolvable on user machines. Compile
138
- # via the Makefile, link with pure -undefined dynamic_lookup
139
- # (Ruby symbols resolve from the loading interpreter) and a
140
- # conservative deployment target.
141
- sh "make native.o"
142
- sh "cc -dynamic -bundle -undefined dynamic_lookup " \
143
- "-mmacosx-version-min=#{ENV['MACOSX_DEPLOYMENT_TARGET'] || '11.0'} " \
144
- "-o native.bundle native.o"
145
- else
146
- sh "make"
172
+ # Build-log proof of the linkage contract: libSystem only.
173
+ puts `otool -L #{bundle}`
147
174
  end
175
+ cp(bundle, "lib/leptris/xml/#{File.basename(bundle)}")
176
+ puts "Vendored native layer (#{File.basename(bundle)}) into lib/leptris/xml/"
148
177
  end
149
- bundle = Dir.glob("#{ext_dir}/native.{bundle,so,dll}").first
150
- raise "native layer bundle not found after build" unless bundle
151
- if RUBY_PLATFORM =~ /darwin/
152
- # Build-log proof of the linkage contract: libSystem only.
153
- puts `otool -L #{bundle}`
154
- end
155
- cp(bundle, "lib/leptris/xml/#{File.basename(bundle)}")
156
- puts "Vendored native layer (#{File.basename(bundle)}) into lib/leptris/xml/"
157
178
  end
158
179
 
159
180
  task spec: :compile unless ENV.key?("LEPTRIS_LIB_PATH")
@@ -264,7 +285,12 @@ platforms.each do |platform|
264
285
  spec.platform = Gem::Platform.new(platform)
265
286
  spec.files += Dir.glob("lib/libleptris.{dll,so,dylib}")
266
287
  spec.files += Dir.glob("lib/{libutf8proc.3.dylib,libutf8proc.so.3,libutf8proc.so,utf8proc.dll}")
267
- spec.files += Dir.glob("lib/leptris/xml/native.{bundle,so,dll}")
288
+ if platform.include?("mingw")
289
+ # #207/#227: per-Ruby-minor DLLs (PE must bind its Ruby).
290
+ spec.files += Dir.glob("lib/leptris/xml/native-*.so")
291
+ else
292
+ spec.files += Dir.glob("lib/leptris/xml/native.{bundle,so,dll}")
293
+ end
268
294
  task = Gem::PackageTask.new(spec)
269
295
  task.define
270
296
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Builds the native read layer DLL for the CURRENT Ruby and
4
+ # installs it under its minor-versioned name
5
+ # (lib/leptris/xml/native-<major.minor>.so).
6
+ #
7
+ # #207/#227: a PE DLL cannot resolve Ruby imports lazily — it
8
+ # must bind the build Ruby's x64-ucrt-rubyNNN.dll. One DLL per
9
+ # supported minor therefore ships in the Windows platform gems,
10
+ # and native_layer picks by RUBY_VERSION at require.
11
+ #
12
+ # Standalone by design: the release workflow runs this under each
13
+ # Ruby minor (3.3/3.4/4.0) with no bundler context.
14
+
15
+ require "rbconfig"
16
+ require "fileutils"
17
+
18
+ root = File.expand_path("..", __dir__)
19
+ ext_dir = File.join(root, "ext", "leptris", "native")
20
+ minor = RUBY_VERSION[/\A\d+\.\d+/]
21
+
22
+ Dir.chdir(ext_dir) do
23
+ system(RbConfig.ruby, "extconf.rb") or abort "extconf failed under #{RUBY_VERSION}"
24
+ # mkmf's link binds the CURRENT Ruby's runtime DLL — exactly
25
+ # what the versioned naming is for.
26
+ success = system("make")
27
+ abort "make failed under #{RUBY_VERSION}" unless success
28
+ so = Dir.glob("native.{so,dll}").first
29
+ abort "native bundle not produced under #{RUBY_VERSION}" unless so
30
+ dest = File.join(root, "lib", "leptris", "xml", "native-#{minor}.so")
31
+ # The artifact must reference only this minor's Ruby DLL.
32
+ imported = `strings #{so} 2>/dev/null`[/[a-z0-9-]*ruby\d{3,}\.dll/i]
33
+ if imported && !imported.include?("ruby#{minor.delete('.')}")
34
+ abort "#{so} imports #{imported} but was built under #{RUBY_VERSION} — refuse to mis-name it"
35
+ end
36
+ FileUtils.cp(so, dest)
37
+ puts "Installed native layer for Ruby #{minor} -> #{dest} (#{imported || 'no ruby dll string found'})"
38
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leptris
4
- VERSION = "1.9.174.0"
4
+ VERSION = "1.9.174.2"
5
5
  end
@@ -17,11 +17,17 @@
17
17
  require "ffi" unless defined?(::FFI::Library)
18
18
 
19
19
  begin
20
- # The compiled bundle (feature "leptris/xml/native" resolves
21
- # native.bundle). A sanctioned require exception: a .bundle
22
- # cannot go through autoload. Missing in installs that do not
23
- # vendor it (ruby-platform gem).
24
- require "leptris/xml/native"
20
+ # The compiled bundle. A sanctioned require exception: a
21
+ # .bundle/.so cannot go through autoload. Missing in installs
22
+ # that do not vendor it (ruby-platform gem). Windows names the
23
+ # artifact per Ruby minor (#207/#227): a PE DLL must bind its
24
+ # build Ruby's runtime, so one DLL per supported minor ships
25
+ # and RUBY_VERSION selects.
26
+ if Gem.win_platform?
27
+ require "leptris/xml/native-#{RUBY_VERSION[/\A\d+\.\d+/]}"
28
+ else
29
+ require "leptris/xml/native"
30
+ end
25
31
  rescue LoadError => e
26
32
  raise LoadError, <<~MSG
27
33
  leptris: the compiled native read layer is not available in
data/lib/leptris.rb CHANGED
@@ -42,7 +42,12 @@ end
42
42
  unless ENV["LEPTRIS_NO_NATIVE"] == "1"
43
43
  begin
44
44
  require "leptris/xml/native_layer"
45
- rescue LoadError
46
- nil
45
+ rescue LoadError => e
46
+ # #207: a silent fallback hides a platform-gem packaging bug
47
+ # behind a walk-speed regression. Say so, then continue on
48
+ # the FFI surface (the explicit require still raises its full
49
+ # error for callers that opt in).
50
+ warn "leptris: native acceleration unavailable " \
51
+ "(#{e.message.lines.first.strip}); using the FFI surface"
47
52
  end
48
53
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.174.0
4
+ version: 1.9.174.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -115,6 +115,7 @@ files:
115
115
  - docs/adr/0004-lifetime-guard.md
116
116
  - docs/adr/0005-autoload-manifest-ordering.md
117
117
  - docs/adr/0006-ruby-variant-policy.md
118
+ - ext/build_windows_native.rb
118
119
  - ext/leptris/native/extconf.rb
119
120
  - ext/leptris/native/native.c
120
121
  - leptris.gemspec