Module: Rpdfium::Binary

Defined in:
lib/rpdfium/binary.rb,
lib/rpdfium/binary/version.rb,
lib/rpdfium/binary/downloader.rb

Overview

Companion gem distributing prebuilt PDFium binaries.

In una gemma “platform-specific” (es. rpdfium-binary-0.1.7811-x86_64-linux), il binario è già impacchettato in ‘vendor/lib/` ed è disponibile alla prima require senza I/O di rete.

La gemma “ruby” generica (platform=ruby) NON include il binario: alla prima ‘library_path` lo scarica da pdfium-binaries di bblanchon, lo verifica via SHA256 (se forniti) e lo cache nella user data dir (`~/.local/share/rpdfium/binaries/<version>/<platform>/`).

Il path viene poi esposto a rpdfium via ‘Rpdfium::Binary.library_path`, che `rpdfium/raw.rb` interroga prima di tentare il caricamento di sistema.

Defined Under Namespace

Modules: Downloader Classes: ChecksumError, DownloadError, Error, UnsupportedPlatform

Constant Summary collapse

PDFIUM_BUILD =

Versione di PDFium impacchettato. Estratta dal file VERSION o dalla build info se presente, fallback al numero in VERSION costante.

ENV.fetch("RPDFIUM_BINARY_PDFIUM_BUILD",
Rpdfium::Binary::VERSION.split(".").last)
VERSION =

Schema: <gem_major>.<gem_minor>.<pdfium_build> Es. 0.1.7811 = prima minor di rpdfium-binary, basata su pdfium chromium/7811. Il PDFium build number è leggibile dal nome della release upstream (github.com/bblanchon/pdfium-binaries/releases).

"0.1.7811"

Class Method Summary collapse

Class Method Details

.bundled?Boolean

Restituisce true se il binario è già pre-impacchettato (gemma platform-specific). In quel caso non c’è I/O di rete a runtime.

Returns:

  • (Boolean)


118
119
120
# File 'lib/rpdfium/binary.rb', line 118

def self.bundled?
  !locate_bundled.nil?
end

.cache_dirObject

—- Download fallback —-



142
143
144
145
146
147
# File 'lib/rpdfium/binary.rb', line 142

def self.cache_dir
  base = ENV["RPDFIUM_BINARY_CACHE"] ||
         ENV["XDG_DATA_HOME"] ||
         File.expand_path("~/.local/share")
  File.join(base, "rpdfium", "binaries", PDFIUM_BUILD, platform_key)
end

.detect_platform_keyObject



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rpdfium/binary.rb', line 39

def self.detect_platform_key
  cpu = host_cpu
  case host_os
  when :linux
    musl = libc_is_musl? ? "musl-" : ""
    "linux-#{musl}#{cpu}"
  when :darwin then "mac-#{cpu}"
  when :windows then "win-#{cpu}"
  else
    raise UnsupportedPlatform,
          "Unsupported OS: #{RbConfig::CONFIG['host_os']}"
  end
end

.download_and_cacheObject

Raises:



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/rpdfium/binary.rb', line 149

def self.download_and_cache
  target_dir = cache_dir
  target = File.join(target_dir, library_filename)
  return target if File.file?(target)

  require_relative "binary/downloader"
  Downloader.fetch!(
    url:           Downloader.asset_url(platform_key, PDFIUM_BUILD),
    dest_dir:      target_dir,
    library_name:  library_filename,
    sha256:        Downloader.expected_sha256(platform_key, PDFIUM_BUILD)
  )
  raise DownloadError, "binary not found at #{target}" unless File.file?(target)

  target
end

.host_cpuObject



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rpdfium/binary.rb', line 62

def self.host_cpu
  cpu = RbConfig::CONFIG["host_cpu"]
  case cpu
  when /x86_64|amd64/ then "x64"
  when /aarch64|arm64/ then "arm64"
  when /i[3-6]86/      then "x86"
  when /^arm/          then "arm"
  else
    raise UnsupportedPlatform, "Unsupported CPU: #{cpu}"
  end
end

.host_osObject



53
54
55
56
57
58
59
60
# File 'lib/rpdfium/binary.rb', line 53

def self.host_os
  case RbConfig::CONFIG["host_os"]
  when /linux/  then :linux
  when /darwin/ then :darwin
  when /mingw|mswin|cygwin/ then :windows
  else :unknown
  end
end

.libc_is_musl?Boolean

Detection musl libc su Linux. Su glibc questa system call fallisce silenziosamente, su Alpine restituisce un path che contiene ‘musl’. Fallback: ldd –version (alpine ldd non supporta –version e va in stderr con “musl libc”).

Returns:

  • (Boolean)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/rpdfium/binary.rb', line 78

def self.libc_is_musl?
  return false unless host_os == :linux

  # Strategia 1: Look at ldd output
  out = `ldd --version 2>&1`
  return true if out.include?("musl")

  # Strategia 2: ispeziona /usr/bin/ldd se è uno script
  ldd_path = `command -v ldd 2>/dev/null`.strip
  if !ldd_path.empty? && File.readable?(ldd_path)
    head = File.read(ldd_path, 1024) rescue ""
    return true if head.include?("musl")
  end

  false
rescue StandardError
  false
end

.library_filenameObject

Nome file libreria nativa per la piattaforma corrente.



98
99
100
101
102
103
104
# File 'lib/rpdfium/binary.rb', line 98

def self.library_filename
  case host_os
  when :darwin  then "libpdfium.dylib"
  when :windows then "pdfium.dll"
  else               "libpdfium.so"
  end
end

.library_pathObject

Restituisce il path assoluto al .so/.dylib/.dll di PDFium. In una gemma platform-specific lo trova subito; altrimenti scarica.



110
111
112
113
114
# File 'lib/rpdfium/binary.rb', line 110

def self.library_path
  return @library_path if defined?(@library_path) && @library_path

  @library_path = locate_bundled || download_and_cache
end

.locate_bundledObject

—- Cerca binario impacchettato nella gemma —-



130
131
132
133
134
135
136
137
138
# File 'lib/rpdfium/binary.rb', line 130

def self.locate_bundled
  candidates = [
    File.expand_path("../../vendor/lib/#{library_filename}", __dir__),
    File.expand_path("../../vendor/#{platform_key}/lib/#{library_filename}", __dir__)
  ]
  candidates.find { |p| File.file?(p) }
rescue UnsupportedPlatform
  nil
end

.platform_keyObject

Restituisce il “platform key” usato internamente, es. “linux-x64”, “mac-arm64”, “win-x64”. Stesso schema dei file di bblanchon.



35
36
37
# File 'lib/rpdfium/binary.rb', line 35

def self.platform_key
  @platform_key ||= detect_platform_key
end

.reset!Object

Reset (utile per test)



123
124
125
126
# File 'lib/rpdfium/binary.rb', line 123

def self.reset!
  remove_instance_variable(:@library_path) if defined?(@library_path)
  remove_instance_variable(:@platform_key) if defined?(@platform_key)
end