Class: Node::Compiler

Inherits:
Object
  • Object
show all
Defined in:
lib/node/compiler.rb,
lib/node/compiler/error.rb,
lib/node/compiler/version.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

VENDOR_DIR =
File.expand_path('../../../vendor', __FILE__)
MEMFS =
'/__enclose_io_memfs__'
VERSION =
"0.9.0"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(module_name = nil, module_version = nil, bin_name = nil, output_path = nil) ⇒ Compiler

Returns a new instance of Compiler.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/node/compiler.rb', line 18

def initialize(module_name = nil,
               module_version = nil,
               bin_name = nil,
               output_path = nil)
  @node_version = self.class.node_version
  @module_name = module_name
  @module_version = module_version
  @bin_name = bin_name
  @output_path = output_path

  @vendor_dir = File.expand_path("./#{@node_version}", VENDOR_DIR)
  unless File.exist?(@vendor_dir)
    msg = "Does not support #{@node_version}, supported: #{::Node::Compiler.node_version}"
    raise Error, msg
  end
end

Class Method Details

.node_versionObject



14
15
16
# File 'lib/node/compiler.rb', line 14

def self.node_version
  Dir[VENDOR_DIR+'/node-*'].map {|x| x.gsub(VENDOR_DIR+'/', '')}.first
end

Instance Method Details

#clean_work_dirObject



147
148
149
# File 'lib/node/compiler.rb', line 147

def clean_work_dir
  FileUtils.remove_entry_secure @work_dir
end

#compileObject



118
119
120
121
122
123
124
# File 'lib/node/compiler.rb', line 118

def compile
  chdir(@vendor_dir) do
    run("./configure #{ENV['ENCLOSE_IO_CONFIGURE_ARGS']}")
    run("make #{ENV['ENCLOSE_IO_MAKE_ARGS']}")
  end
  FileUtils.cp(File.join(@vendor_dir, 'out/Release/node'), @output_path)
end

#compile_winObject



111
112
113
114
115
116
# File 'lib/node/compiler.rb', line 111

def compile_win
  chdir(@vendor_dir) do
    run("call vcbuild.bat #{ENV['ENCLOSE_IO_VCBUILD_ARGS']}")
  end
  FileUtils.cp(File.join(@vendor_dir, 'Release\\node.exe'), @output_path)
end

#inject_entranceObject



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/node/compiler.rb', line 80

def inject_entrance
  target = File.expand_path('./lib/enclose_io_entrance.js', @vendor_dir)
  prj_home = File.expand_path("node_modules/#{@module_name}", @work_dir)
  bin = File.expand_path(@binaries[@bin_name], prj_home)
  path = mempath bin
  File.open(target, "w") { |f| f.puts %Q`module.exports = "#{path}";` }
  # remove shebang
  lines = File.read(bin).lines
  lines[0] = "// #{lines[0]}" if '#!' == lines[0][0..1]
  File.open(bin, "w") { |f| f.print lines.join }
end

#inject_memfs(source) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/node/compiler.rb', line 92

def inject_memfs(source)
  target = File.expand_path("./lib#{MEMFS}", @vendor_dir)
  FileUtils.remove_entry_secure(target) if File.exist?(target)
  FileUtils.cp_r(source, target)
  manifest = File.expand_path('./enclose_io_manifest.txt', @vendor_dir)
  File.open(manifest, "w") do |f|
    Dir["#{target}/**/*"].each do |fullpath|
      next unless File.file?(fullpath)
      if 0 == File.size(fullpath) && Gem.win_platform?
        # Fix VC++ Error C2466
        # TODO: what about empty file semantics?
        File.open(fullpath, 'w') { |f| f.puts ' ' }
      end
      entry = "lib#{fullpath[(fullpath.index MEMFS)..-1]}"
      f.puts entry
    end
  end
end

#npm_installObject



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/node/compiler.rb', line 50

def npm_install
  chdir(@work_dir) do
    File.open("package.json", "w") do |f|
      package = %Q({"dependencies": {"#{@module_name}": "#{@module_version}"}})
      f.puts package
    end
    npm = ENV['ENCLOSE_IO_NPM'] || 'npm'
    run("#{npm} -v")
    run("#{npm} install #{ENV['ENCLOSE_IO_NPM_INSTALL_ARGS']}")
  end
end

#parse_binariesObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/node/compiler.rb', line 62

def parse_binaries
  unless File.exist?(@package_path)
    raise Error, "No package.json exist at #{@package_path}."
  end
  @package_json = JSON.parse File.read @package_path
  @binaries = @package_json['bin']
  if @binaries
    STDERR.puts "Detected binaries: #{@binaries}"
  else
    raise Error, "No binaries detected inside #{@package_path}."
  end
  if @binaries[@bin_name]
    STDERR.puts "Using #{@bin_name} at #{@binaries[@bin_name]}"
  else
    raise Error, "No such binary: #{@bin_name}"
  end
end

#prepare_varsObject



44
45
46
47
48
# File 'lib/node/compiler.rb', line 44

def prepare_vars
  @work_dir = File.expand_path("./enclose-io/nodec/#{@module_name}-#{@module_version}", Dir.tmpdir)
  FileUtils.mkdir_p(@work_dir)
  @package_path = File.join(@work_dir, "node_modules/#{@module_name}/package.json")
end

#run!Object



35
36
37
38
39
40
41
42
# File 'lib/node/compiler.rb', line 35

def run!
  prepare_vars
  npm_install
  parse_binaries
  inject_entrance
  inject_memfs(@work_dir)
  Gem.win_platform? ? compile_win : compile
end

#test!Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/node/compiler.rb', line 126

def test!
  chdir(@vendor_dir) do
    inject_memfs(File.expand_path('./test/fixtures', @vendor_dir))
    FileUtils.rm_f(Gem.win_platform? ? 'Release\\node.exe' : 'out/Release/node')
    File.open(File.expand_path('./lib/enclose_io_entrance.js', @vendor_dir), "w") { |f| f.puts 'module.exports = false;' }
    test_env = {
                 'FLAKY_TESTS_MODE' => 'dontcare',
                 'FLAKY_TESTS' => 'dontcare',
                 'ENCLOSE_IO_USE_ORIGINAL_NODE' => '1',
                 'ENCLOSE_IO_ALWAYS_USE_ORIGINAL_NODE' => '1',
               }
    if Gem.win_platform?
      run(test_env, 'call vcbuild.bat nosign test-ci ignore-flaky')
    else
      run("./configure #{ENV['ENCLOSE_IO_CONFIGURE_ARGS']}")
      run("make #{ENV['ENCLOSE_IO_MAKE_ARGS']}")
      run(test_env, "make test-ci")
    end
  end
end