Class: Cry::Compiler

Inherits:
Object
  • Object
show all
Defined in:
lib/cry/compiler.rb

Overview

Crystal compiler command wrapper class. This class is used to compile Crystal code to WASM.

Examples:

compiler = Cry::Compiler.new
compiler.build_wasm('puts "Hello, World!"')

Defined Under Namespace

Classes: CompilerError, Options

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCompiler

Returns a new instance of Compiler.



15
16
17
# File 'lib/cry/compiler.rb', line 15

def initialize
  @options = Options.new
end

Instance Attribute Details

#optionsStruct (readonly)

Return compiler options

Returns:

  • (Struct)

    compiler options



21
22
23
# File 'lib/cry/compiler.rb', line 21

def options
  @options
end

Instance Method Details

#build_command(options = @options) ⇒ String

Return build command from options

Parameters:

  • options (Struct) (defaults to: @options)

    compiler options

Returns:

  • (String)

    build command



111
112
113
114
# File 'lib/cry/compiler.rb', line 111

def build_command(options = @options)
  link_flags = "\"#{options.link_flags}" + options.export.map { |n| "--export #{n} " }.join + '"'
  "crystal build #{options.input} -o #{options.output} --target #{options.target} --link-flags=#{link_flags}"
end

#build_wasm(crystal_code, **opts) ⇒ String

Compile Crystal code to WASM

Parameters:

  • crystal_code (String)

    Crystal source code

  • opts (Hash)

    compiler options

Options Hash (**opts):

  • :output (String)

    output wasm file path

  • :release (Boolean)

    release build

  • :export (Array<String>)

    export function names

  • :target (String)

    target triple

  • :link_flags (String)

    link flags

Returns:

  • (String)

    compiled WASM bytes



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/cry/compiler.rb', line 53

def build_wasm(crystal_code, **opts)
  set_options(crystal_code, **opts)

  command = build_command

  stdout, error, status = Open3.capture3(command)
  @input_tempfile&.close

  unless status.success?
    warn build_error_message(crystal_code, command, error)
    raise CompilerError, 'Failed to compile Crystal code to WASM'
  end

  if (options.output = '/dev/stdout')
    stdout
  else
    IO.read(options.output, mode: 'rb')
  end
end

#get_crystal_library_pathString

Return CRYSTAL_LIBRARY_PATH

Returns:

  • (String)

    CRYSTAL_LIBRARY_PATH



39
40
41
# File 'lib/cry/compiler.rb', line 39

def get_crystal_library_path
  ENV['CRYSTAL_LIBRARY_PATH']
end

#set_crystal_library_path(path = nil) ⇒ String

Set CRYSTAL_LIBRARY_PATH If path is not given, set default path

Parameters:

  • path (String) (defaults to: nil)

    path to CRYSTAL_LIBRARY_PATH

Returns:

  • (String)

    CRYSTAL_LIBRARY_PATH



28
29
30
31
32
33
34
# File 'lib/cry/compiler.rb', line 28

def set_crystal_library_path(path = nil)
  if path
    ENV['CRYSTAL_LIBRARY_PATH'] = path
  else
    ENV['CRYSTAL_LIBRARY_PATH'] ||= File.expand_path('../../vendor/wasm32-wasi-libs', __dir__)
  end
end

#set_options(crystal_code, **opts) ⇒ Struct

Set compiler options

Parameters:

  • crystal_code (String)

    Crystal source code

  • opts (Hash)

    compiler options

Options Hash (**opts):

  • :output (String)

    output wasm file path

  • :release (Boolean)

    release build

  • :export (Array<String>)

    export function names

  • :target (String)

    target triple

  • :link_flags (String)

    link flags

Returns:

  • (Struct)

    compiler options



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/cry/compiler.rb', line 83

def set_options(crystal_code, **opts)
  options.output = opts[:output] || nil
  options.release = opts[:release] || false
  options.export = opts[:export] || []
  options.target = opts[:target] || 'wasm32-wasi'
  options.link_flags = opts[:link_flags] || ''

  # Set CRYSTAL_LIBRARY_PATH
  set_crystal_library_path

  # Set output (wasm bytecode) path
  options.output = '/dev/stdout' unless options.output

  # Set input (crystal source) path
  input_tempfile = nil
  unless options.input
    @input_tempfile = Tempfile.create('crystal')
    options.input = @input_tempfile.path
  end
  File.write(options.input, crystal_code)

  options
end