Module: Sonicop::Runner

Defined in:
lib/sonicop/runner.rb

Class Method Summary collapse

Class Method Details

.candidates(root: gem_root, env: ENV, specification: installed_specification, windows: Gem.win_platform?) ⇒ Object

優先順位は「明示指定 > platform gem 同梱 > ソース gem のビルド成果物 > 開発ツリー」。



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/sonicop/runner.rb', line 40

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 を渡して候補順を検証する。



34
35
36
37
# File 'lib/sonicop/runner.rb', line 34

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_rootObject



57
58
59
# File 'lib/sonicop/runner.rb', line 57

def gem_root
  File.expand_path('../..', __dir__)
end

.installed_specificationObject



61
62
63
64
65
# File 'lib/sonicop/runner.rb', line 61

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
# 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
    exec(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.message}
      The installed platform gem probably does not match this system.
      Reinstall from source with: gem install sonicop --platform ruby
    MESSAGE
  end
end