Module: Sonicop::Runner
- Defined in:
- lib/sonicop/runner.rb
Class Method Summary collapse
-
.candidates(root: gem_root, env: ENV, specification: installed_specification, windows: Gem.win_platform?) ⇒ Object
優先順位は「明示指定 > platform gem 同梱 > ソース gem のビルド成果物 > 開発ツリー」。.
-
.find_binary(root: gem_root, env: ENV, specification: installed_specification, windows: Gem.win_platform?) ⇒ Object
環境依存の入力はすべて引数にしてある。既定値は本番の解決経路そのもので、 テストからは偽のツリー・偽の spec を渡して候補順を検証する。.
- .gem_root ⇒ Object
- .installed_specification ⇒ Object
- .run(arguments = ARGV) ⇒ Object
Class Method Details
.candidates(root: gem_root, env: ENV, specification: installed_specification, windows: Gem.win_platform?) ⇒ Object
優先順位は「明示指定 > platform gem 同梱 > ソース gem のビルド成果物 > 開発ツリー」。
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/sonicop/runner.rb', line 46 def candidates(root: gem_root, env: ENV, specification: installed_specification, windows: Gem.win_platform?) executable = windows ? 'sonicop.exe' : 'sonicop' installed_executable = windows ? 'sonicop-bin.exe' : 'sonicop-bin' paths = [] paths << env['SONICOP_BINARY'] if env['SONICOP_BINARY'] paths << File.join(root, 'libexec', executable) if specification paths << File.join(specification.extension_dir, executable) paths << File.join(specification.extension_dir, installed_executable) paths << File.join(specification.full_gem_path, 'lib', installed_executable) end paths << File.join(root, 'target', 'release', executable) paths << File.join(root, 'target', 'debug', executable) paths end |
.find_binary(root: gem_root, env: ENV, specification: installed_specification, windows: Gem.win_platform?) ⇒ Object
環境依存の入力はすべて引数にしてある。既定値は本番の解決経路そのもので、 テストからは偽のツリー・偽の spec を渡して候補順を検証する。
40 41 42 43 |
# File 'lib/sonicop/runner.rb', line 40 def find_binary(root: gem_root, env: ENV, specification: installed_specification, windows: Gem.win_platform?) candidates(root: root, env: env, specification: specification, windows: windows) .find { |path| File.file?(path) && File.executable?(path) } end |
.gem_root ⇒ Object
63 64 65 |
# File 'lib/sonicop/runner.rb', line 63 def gem_root File.('../..', __dir__) end |
.installed_specification ⇒ Object
67 68 69 70 71 |
# File 'lib/sonicop/runner.rb', line 67 def installed_specification Gem::Specification.find_by_name('sonicop', Sonicop::VERSION) rescue Gem::LoadError nil # Running from a source checkout. end |
.run(arguments = ARGV) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/sonicop/runner.rb', line 10 def run(arguments = ARGV) binary = find_binary abort <<~MESSAGE unless binary Sonicop's native executable was not found (platform: #{Gem::Platform.local}). Reinstall the gem with a Rust toolchain available, or install a platform-specific gem. MESSAGE begin # `[binary, binary]` = exec 形式の強制。`exec(binary, *arguments)` は arguments が空、 # つまり「カレントディレクトリを見る素の `sonicop`」という最も普通の呼び出しのとき # `exec(String)` = commandline 形式に落ちる。この形式は空白で単語分割し、メタ文字が # あればまるごと /bin/sh に渡すため、binary のパス次第で ENOENT や exit 127 になる。 # パスの出所は SONICOP_BINARY と gem の install 先で、どちらもメタ文字を含まない保証がない。 # argv0 は multi-arg 形式が既定で入れるものと同じ値を明示している。 exec([binary, binary], *arguments) rescue SystemCallError => error # 実行できない典型は「platform gem は入ったが実行環境と ABI が違う」ケース # (musl 環境に glibc ビルドが入るなど)。素の errno だけでは原因が読めない。 abort <<~MESSAGE Sonicop's native executable could not be started (platform: #{Gem::Platform.local}). #{binary} #{error.class}: #{error.} The installed platform gem probably does not match this system. Reinstall from source with: gem install sonicop --platform ruby MESSAGE end end |