ruby_wasm 2.5.0-x64-mingw-ucrt
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.clang-format +8 -0
- data/CONTRIBUTING.md +126 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/NOTICE +1293 -0
- data/README.md +153 -0
- data/Rakefile +163 -0
- data/Steepfile +24 -0
- data/benchmarks/vm_deep_call.rb +55 -0
- data/builders/wasm32-unknown-emscripten/Dockerfile +43 -0
- data/builders/wasm32-unknown-emscripten/entrypoint.sh +7 -0
- data/builders/wasm32-unknown-wasi/Dockerfile +47 -0
- data/builders/wasm32-unknown-wasi/entrypoint.sh +7 -0
- data/docs/api.md +2 -0
- data/docs/cheat_sheet.md +195 -0
- data/docs/faq.md +25 -0
- data/exe/rbwasm +7 -0
- data/ext/.gitignore +2 -0
- data/ext/README.md +11 -0
- data/ext/extinit.c.erb +32 -0
- data/lib/ruby_wasm/3.1/ruby_wasm.so +0 -0
- data/lib/ruby_wasm/3.2/ruby_wasm.so +0 -0
- data/lib/ruby_wasm/build/build_params.rb +3 -0
- data/lib/ruby_wasm/build/downloader.rb +18 -0
- data/lib/ruby_wasm/build/executor.rb +187 -0
- data/lib/ruby_wasm/build/product/baseruby.rb +37 -0
- data/lib/ruby_wasm/build/product/crossruby.rb +330 -0
- data/lib/ruby_wasm/build/product/libyaml.rb +68 -0
- data/lib/ruby_wasm/build/product/openssl.rb +88 -0
- data/lib/ruby_wasm/build/product/product.rb +39 -0
- data/lib/ruby_wasm/build/product/ruby_source.rb +103 -0
- data/lib/ruby_wasm/build/product/wasi_vfs.rb +45 -0
- data/lib/ruby_wasm/build/product/zlib.rb +68 -0
- data/lib/ruby_wasm/build/product.rb +8 -0
- data/lib/ruby_wasm/build/toolchain/wit_bindgen.rb +31 -0
- data/lib/ruby_wasm/build/toolchain.rb +193 -0
- data/lib/ruby_wasm/build.rb +88 -0
- data/lib/ruby_wasm/cli.rb +217 -0
- data/lib/ruby_wasm/packager/core.rb +156 -0
- data/lib/ruby_wasm/packager/file_system.rb +158 -0
- data/lib/ruby_wasm/packager.rb +159 -0
- data/lib/ruby_wasm/rake_task.rb +59 -0
- data/lib/ruby_wasm/util.rb +15 -0
- data/lib/ruby_wasm/version.rb +3 -0
- data/lib/ruby_wasm.rb +33 -0
- data/package-lock.json +9500 -0
- data/package.json +12 -0
- data/rakelib/check.rake +37 -0
- data/rakelib/ci.rake +152 -0
- data/rakelib/doc.rake +29 -0
- data/rakelib/format.rake +35 -0
- data/rakelib/gem.rake +22 -0
- data/rakelib/packaging.rake +151 -0
- data/rakelib/version.rake +40 -0
- data/sig/open_uri.rbs +4 -0
- data/sig/ruby_wasm/build.rbs +318 -0
- data/sig/ruby_wasm/cli.rbs +27 -0
- data/sig/ruby_wasm/ext.rbs +13 -0
- data/sig/ruby_wasm/packager.rbs +91 -0
- data/sig/ruby_wasm/util.rbs +5 -0
- data/tools/clang-format-diff.sh +18 -0
- data/tools/exe/rbminify +12 -0
- data/tools/lib/syntax_tree/minify_ruby.rb +63 -0
- metadata +113 -0
data/docs/cheat_sheet.md
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
[[**Cheat Sheet**]](./cheat_sheet.md)
|
2
|
+
[[**FAQ**]](./faq.md)
|
3
|
+
[[**API Reference**]](./api.md)
|
4
|
+
[[**Complete Examples**]](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example)
|
5
|
+
[[**Community Showcase**]](https://github.com/ruby/ruby.wasm/wiki/Showcase)
|
6
|
+
|
7
|
+
# ruby.wasm Cheat Sheet
|
8
|
+
|
9
|
+
## Node.js
|
10
|
+
|
11
|
+
To install the package, install `@ruby/3.3-wasm-wasi` and `@ruby/wasm-wasi` from npm:
|
12
|
+
|
13
|
+
```console
|
14
|
+
npm install --save @ruby/3.3-wasm-wasi @ruby/wasm-wasi
|
15
|
+
```
|
16
|
+
|
17
|
+
Then instantiate a Ruby VM by the following code:
|
18
|
+
|
19
|
+
```javascript
|
20
|
+
import fs from "fs/promises";
|
21
|
+
import { DefaultRubyVM } from "@ruby/wasm-wasi/dist/node";
|
22
|
+
|
23
|
+
const binary = await fs.readFile("./node_modules/@ruby/3.3-wasm-wasi/dist/ruby.wasm");
|
24
|
+
const module = await WebAssembly.compile(binary);
|
25
|
+
const { vm } = await DefaultRubyVM(module);
|
26
|
+
vm.eval(`puts "hello world"`);
|
27
|
+
```
|
28
|
+
|
29
|
+
Then run the example code with `--experimental-wasi-unstable-preview1` flag to enable WASI support:
|
30
|
+
|
31
|
+
```console
|
32
|
+
$ node --experimental-wasi-unstable-preview1 index.mjs
|
33
|
+
```
|
34
|
+
|
35
|
+
## Browser
|
36
|
+
|
37
|
+
The easiest way to run Ruby on browser is to use `browser.script.iife.js` script from CDN:
|
38
|
+
|
39
|
+
```html
|
40
|
+
<html>
|
41
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.0/dist/browser.script.iife.js"></script>
|
42
|
+
<script type="text/ruby">
|
43
|
+
require "js"
|
44
|
+
JS.global[:document].write "Hello, world!"
|
45
|
+
</script>
|
46
|
+
</html>
|
47
|
+
```
|
48
|
+
|
49
|
+
If you want to control Ruby VM from JavaScript, you can use `@ruby/wasm-wasi` package API:
|
50
|
+
|
51
|
+
```html
|
52
|
+
<html>
|
53
|
+
<script type="module">
|
54
|
+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.0/dist/browser/+esm";
|
55
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.0/dist/ruby+stdlib.wasm");
|
56
|
+
const module = await WebAssembly.compileStreaming(response);
|
57
|
+
const { vm } = await DefaultRubyVM(module);
|
58
|
+
|
59
|
+
vm.eval(`
|
60
|
+
require "js"
|
61
|
+
JS.global[:document].write "Hello, world!"
|
62
|
+
`);
|
63
|
+
</script>
|
64
|
+
</html>
|
65
|
+
```
|
66
|
+
|
67
|
+
<details>
|
68
|
+
<summary>Alternative: Without ES Modules</summary>
|
69
|
+
|
70
|
+
```html
|
71
|
+
<html>
|
72
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.0/dist/browser.umd.js"></script>
|
73
|
+
<script>
|
74
|
+
const main = async () => {
|
75
|
+
const { DefaultRubyVM } = window["ruby-wasm-wasi"];
|
76
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.0/dist/ruby+stdlib.wasm");
|
77
|
+
const module = await WebAssembly.compileStreaming(response);
|
78
|
+
const { vm } = await DefaultRubyVM(module);
|
79
|
+
|
80
|
+
vm.eval(`
|
81
|
+
require "js"
|
82
|
+
JS.global[:document].write "Hello, world!"
|
83
|
+
`);
|
84
|
+
}
|
85
|
+
main()
|
86
|
+
</script>
|
87
|
+
</html>
|
88
|
+
```
|
89
|
+
</details>
|
90
|
+
|
91
|
+
## Use JavaScript from Ruby
|
92
|
+
|
93
|
+
### Get/set JavaScript variables from Ruby
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
require "js"
|
97
|
+
|
98
|
+
document = JS.global[:document]
|
99
|
+
document[:title] = "Hello, world!"
|
100
|
+
```
|
101
|
+
|
102
|
+
### Call JavaScript methods from Ruby
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
require "js"
|
106
|
+
|
107
|
+
JS.global[:document].createElement("div")
|
108
|
+
|
109
|
+
JS.global[:document].call(:createElement, "div".to_js) # same as above
|
110
|
+
```
|
111
|
+
|
112
|
+
### Pass Ruby `Proc` to JavaScript (Callback to Ruby)
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
require "js"
|
116
|
+
|
117
|
+
JS.global.setTimeout(proc { puts "Hello, world!" }, 1000)
|
118
|
+
|
119
|
+
input = JS.global[:document].querySelector("input")
|
120
|
+
input.addEventListener("change") do |event|
|
121
|
+
puts event[:target][:value].to_s
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
### `await` JavaScript `Promise` from Ruby
|
126
|
+
|
127
|
+
`data-eval="async"` attribute is required to use `await` in `<script>` tag:
|
128
|
+
|
129
|
+
```html
|
130
|
+
<html>
|
131
|
+
<script src="https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.0/dist/browser.script.iife.js"></script>
|
132
|
+
<script type="text/ruby" data-eval="async">
|
133
|
+
require "js"
|
134
|
+
|
135
|
+
response = JS.global.fetch("https://www.ruby-lang.org/").await
|
136
|
+
puts response[:status]
|
137
|
+
</script>
|
138
|
+
</html>
|
139
|
+
```
|
140
|
+
|
141
|
+
Or using `@ruby/wasm-wasi` package API `RubyVM#evalAsync`:
|
142
|
+
|
143
|
+
```html
|
144
|
+
<html>
|
145
|
+
<script type="module">
|
146
|
+
import { DefaultRubyVM } from "https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@2.5.0/dist/browser/+esm";
|
147
|
+
const response = await fetch("https://cdn.jsdelivr.net/npm/@ruby/3.3-wasm-wasi@2.5.0/dist/ruby+stdlib.wasm");
|
148
|
+
const module = await WebAssembly.compileStreaming(response);
|
149
|
+
const { vm } = await DefaultRubyVM(module);
|
150
|
+
|
151
|
+
vm.evalAsync(`
|
152
|
+
require "js"
|
153
|
+
|
154
|
+
response = JS.global.fetch("https://www.ruby-lang.org/").await
|
155
|
+
puts response[:status]
|
156
|
+
`);
|
157
|
+
</script>
|
158
|
+
</html>
|
159
|
+
```
|
160
|
+
|
161
|
+
### `new` JavaScript instance from Ruby
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
require "js"
|
165
|
+
|
166
|
+
JS.global[:Date].new(2000, 9, 13)
|
167
|
+
```
|
168
|
+
|
169
|
+
### Convert returned JavaScript `String` value to Ruby `String`
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
require "js"
|
173
|
+
|
174
|
+
title = JS.global[:document].title # => JS::Object("Hello, world!")
|
175
|
+
title.to_s # => "Hello, world!"
|
176
|
+
```
|
177
|
+
|
178
|
+
### Convert JavaScript `Boolean` value to Ruby `true`/`false`
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
require "js"
|
182
|
+
|
183
|
+
JS.global[:document].hasFocus? # => true
|
184
|
+
JS.global[:document].hasFocus # => JS::Object(true)
|
185
|
+
```
|
186
|
+
|
187
|
+
### Convert JavaScript `Number` value to Ruby `Integer`/`Float`
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
require "js"
|
191
|
+
|
192
|
+
rand = JS.global[:Math].random # JS::Object(0.123456789)
|
193
|
+
rand.to_i # => 0
|
194
|
+
rand.to_f # => 0.123456789
|
195
|
+
```
|
data/docs/faq.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
[[**Cheat Sheet**]](./cheat_sheet.md)
|
2
|
+
[[**FAQ**]](./faq.md)
|
3
|
+
[[**API Reference**]](./api.md)
|
4
|
+
[[**Complete Examples**]](https://github.com/ruby/ruby.wasm/tree/main/packages/npm-packages/ruby-wasm-wasi/example)
|
5
|
+
[[**Community Showcase**]](https://github.com/ruby/ruby.wasm/wiki/Showcase)
|
6
|
+
|
7
|
+
# FAQ
|
8
|
+
|
9
|
+
## Where my `puts` output goes?
|
10
|
+
|
11
|
+
By default, `puts` output goes to `STDOUT` which is a JavaScript `console.log` function. You can override it by setting `$stdout` to a Ruby object which has `write` method.
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
$stdout = Object.new.tap do |obj|
|
15
|
+
def obj.write(str)
|
16
|
+
JS.global[:document].write(str)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
puts "Hello, world!" # => Prints "Hello, world!" to the HTML document
|
21
|
+
```
|
22
|
+
|
23
|
+
## How to run WebAssembly in Ruby
|
24
|
+
|
25
|
+
Use [`wasmtime` Ruby gem](https://rubygems.org/gems/wasmtime).
|
data/exe/rbwasm
ADDED
data/ext/.gitignore
ADDED
data/ext/README.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Ruby extensions
|
2
|
+
`ruby.wasm` uses two C extensions to turn Ruby in to a guest module.
|
3
|
+
The `js` extension enables Ruby to use JavaScript APIs.
|
4
|
+
The `witapi` extension exports Ruby's interpreter interface to allow the host to use the Ruby interpreter.
|
5
|
+
In other words, `js` allows Ruby to talk to Javascript and `witapi` allows a host to talk to Ruby.
|
6
|
+
|
7
|
+
Under each subdirectory, there is a `bindgen/*.wit` file outlining the interfaces for each form of communication.
|
8
|
+
Specifically, `bindgen/rb-js-abi-host.wit` describes embedder's requirements and `bindgen/rb-js-abi-guest.wit` describes exported API from Ruby interpreter.
|
9
|
+
The `.c` and `.h` files are autogenerated from [wit-bindgen](https://github.com/bytecodealliance/wit-bindgen#host-runtimes-for-components).
|
10
|
+
You can read more about it in the [contributing guide](/CONTRIBUTING.md#re-bindgen-from-wit-files).
|
11
|
+
Note that we currently do not use the latest version of wit-bindgen because of how fast it is changing, with features being changed or even [removed](https://github.com/bytecodealliance/wit-bindgen/pull/346) at times.
|
data/ext/extinit.c.erb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "optparse"
|
3
|
+
|
4
|
+
opts = OptionParser.new
|
5
|
+
opts.on("--cc CC") {|cc| @cc = cc }
|
6
|
+
opts.on("--output FILE") {|o| @o = o }
|
7
|
+
|
8
|
+
opts.parse!(ARGV)
|
9
|
+
if @cc.nil? || @o.nil?
|
10
|
+
puts opts.help
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
exts = ARGV
|
15
|
+
|
16
|
+
c_src = ERB.new(DATA.read).result
|
17
|
+
IO.popen([@cc, "-c", "-xc", "-", "-o", @o], "w") {|f| f << c_src }
|
18
|
+
exit $?.exitstatus
|
19
|
+
|
20
|
+
__END__
|
21
|
+
#define init(func, name) { \
|
22
|
+
extern void func(void); \
|
23
|
+
ruby_init_ext(name".so", func); \
|
24
|
+
}
|
25
|
+
|
26
|
+
void ruby_init_ext(const char *name, void (*init)(void));
|
27
|
+
|
28
|
+
void Init_extra_exts(void) {
|
29
|
+
<% exts.each do |ext| %>
|
30
|
+
init(<%= "Init_#{File.basename ext}" %>, "<%= ext %>");
|
31
|
+
<% end %>
|
32
|
+
}
|
Binary file
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RubyWasm
|
2
|
+
class Downloader
|
3
|
+
def download(url, dest, message)
|
4
|
+
require "open-uri"
|
5
|
+
content_length = 0
|
6
|
+
uri = URI.parse(url)
|
7
|
+
OpenURI.open_uri(
|
8
|
+
uri,
|
9
|
+
content_length_proc: ->(len) { content_length = len },
|
10
|
+
progress_proc: ->(size) do
|
11
|
+
print "\r#{message} (#{SizeFormatter.format(content_length)}) %.2f%%" %
|
12
|
+
(size.to_f / content_length * 100)
|
13
|
+
end
|
14
|
+
) { |f| File.open(dest, "wb") { |out| out.write f.read } }
|
15
|
+
puts "\r"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
module RubyWasm
|
2
|
+
# Build executor to run the actual build commands.
|
3
|
+
class BuildExecutor
|
4
|
+
attr_reader :process_count
|
5
|
+
|
6
|
+
def initialize(verbose: false, process_count: nil)
|
7
|
+
@verbose = verbose
|
8
|
+
@github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil
|
9
|
+
__skip__ =
|
10
|
+
begin
|
11
|
+
require "etc"
|
12
|
+
@process_count = process_count || Etc.nprocessors
|
13
|
+
rescue LoadError
|
14
|
+
@process_count = process_count || 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def system(*args, chdir: nil, env: nil)
|
19
|
+
require "open3"
|
20
|
+
|
21
|
+
_print_command(args, env)
|
22
|
+
|
23
|
+
# @type var kwargs: Hash[Symbol, untyped]
|
24
|
+
kwargs = {}
|
25
|
+
kwargs[:chdir] = chdir if chdir
|
26
|
+
|
27
|
+
args = args.to_a.map(&:to_s)
|
28
|
+
# TODO: Remove __skip__ once we have open3 RBS definitions.
|
29
|
+
__skip__ =
|
30
|
+
if @verbose || !$stdout.tty?
|
31
|
+
kwargs[:exception] = true
|
32
|
+
if env
|
33
|
+
Kernel.system(env, *args, **kwargs)
|
34
|
+
else
|
35
|
+
Kernel.system(*args, **kwargs)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
printer = StatusPrinter.new
|
39
|
+
block =
|
40
|
+
proc do |stdin, stdout, stderr, wait_thr|
|
41
|
+
mux = Mutex.new
|
42
|
+
out = String.new
|
43
|
+
err = String.new
|
44
|
+
readers =
|
45
|
+
[
|
46
|
+
[stdout, :stdout, out],
|
47
|
+
[stderr, :stderr, err]
|
48
|
+
].map do |io, name, str|
|
49
|
+
reader =
|
50
|
+
Thread.new do
|
51
|
+
while (line = io.gets)
|
52
|
+
mux.synchronize do
|
53
|
+
printer.send(name, line)
|
54
|
+
str << line
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
reader.report_on_exception = false
|
59
|
+
reader
|
60
|
+
end
|
61
|
+
|
62
|
+
readers.each(&:join)
|
63
|
+
|
64
|
+
[out, err, wait_thr.value]
|
65
|
+
end
|
66
|
+
begin
|
67
|
+
stdout, stderr, status =
|
68
|
+
if env
|
69
|
+
Open3.popen3(env, *args, **kwargs, &block)
|
70
|
+
else
|
71
|
+
Open3.popen3(*args, **kwargs, &block)
|
72
|
+
end
|
73
|
+
unless status.success?
|
74
|
+
$stderr.puts stdout
|
75
|
+
$stderr.puts stderr
|
76
|
+
cmd_to_print = args.map { |a| "'#{a}'" }.join(" ")
|
77
|
+
raise "Command failed with status (#{status.exitstatus}): #{cmd_to_print}"
|
78
|
+
end
|
79
|
+
ensure
|
80
|
+
printer.done
|
81
|
+
end
|
82
|
+
end
|
83
|
+
return
|
84
|
+
rescue => e
|
85
|
+
$stdout.flush
|
86
|
+
$stderr.puts "Try running with `rake --verbose` for more complete output."
|
87
|
+
raise e
|
88
|
+
end
|
89
|
+
|
90
|
+
def begin_section(klass, name, note)
|
91
|
+
message = "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- #{note}\e[0m"
|
92
|
+
if @github_actions_markup
|
93
|
+
puts "::group::#{message}"
|
94
|
+
else
|
95
|
+
puts message
|
96
|
+
end
|
97
|
+
|
98
|
+
# Record the start time
|
99
|
+
@start_times ||= Hash.new
|
100
|
+
@start_times[[klass, name]] = Time.now
|
101
|
+
|
102
|
+
$stdout.flush
|
103
|
+
end
|
104
|
+
|
105
|
+
def end_section(klass, name)
|
106
|
+
took = Time.now - @start_times[[klass, name]]
|
107
|
+
puts "::endgroup::" if @github_actions_markup
|
108
|
+
puts "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- done in #{took.round(2)}s\e[0m"
|
109
|
+
end
|
110
|
+
|
111
|
+
def rm_rf(list)
|
112
|
+
FileUtils.rm_rf(list)
|
113
|
+
end
|
114
|
+
|
115
|
+
def rm_f(list)
|
116
|
+
FileUtils.rm_f(list)
|
117
|
+
end
|
118
|
+
|
119
|
+
def cp_r(src, dest)
|
120
|
+
FileUtils.cp_r(src, dest)
|
121
|
+
end
|
122
|
+
|
123
|
+
def mv(src, dest)
|
124
|
+
FileUtils.mv(src, dest)
|
125
|
+
end
|
126
|
+
|
127
|
+
def mkdir_p(list)
|
128
|
+
FileUtils.mkdir_p(list)
|
129
|
+
end
|
130
|
+
|
131
|
+
def write(path, data)
|
132
|
+
File.write(path, data)
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def _print_command(args, env)
|
138
|
+
require "shellwords"
|
139
|
+
# Bold cyan
|
140
|
+
print "\e[1;36m ==>\e[0m "
|
141
|
+
print "env " + env.map { |k, v| "#{k}=#{v}" }.join(" ") + " " if env
|
142
|
+
print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Human readable status printer for the build.
|
147
|
+
class StatusPrinter
|
148
|
+
def initialize
|
149
|
+
@mutex = Mutex.new
|
150
|
+
@counter = 0
|
151
|
+
@indicators = "|/-\\"
|
152
|
+
end
|
153
|
+
|
154
|
+
def stdout(message)
|
155
|
+
require "io/console"
|
156
|
+
@mutex.synchronize do
|
157
|
+
$stdout.print "\e[K"
|
158
|
+
first_line = message.lines(chomp: true).first || ""
|
159
|
+
|
160
|
+
# Make sure we don't line-wrap the output
|
161
|
+
size =
|
162
|
+
__skip__ =
|
163
|
+
IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize
|
164
|
+
terminal_width = size[1].to_i.nonzero? || 80
|
165
|
+
width_limit = terminal_width / 2 - 3
|
166
|
+
|
167
|
+
if first_line.length > width_limit
|
168
|
+
first_line = (first_line[0..width_limit - 5] || "") + "..."
|
169
|
+
end
|
170
|
+
indicator = @indicators[@counter] || " "
|
171
|
+
to_print = " " + indicator + " " + first_line
|
172
|
+
$stdout.print to_print
|
173
|
+
$stdout.print "\e[1A\n"
|
174
|
+
@counter += 1
|
175
|
+
@counter = 0 if @counter >= @indicators.length
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def stderr(message)
|
180
|
+
@mutex.synchronize { $stdout.print message }
|
181
|
+
end
|
182
|
+
|
183
|
+
def done
|
184
|
+
@mutex.synchronize { $stdout.print "\e[K" }
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "./product"
|
2
|
+
|
3
|
+
module RubyWasm
|
4
|
+
class BaseRubyProduct < BuildProduct
|
5
|
+
def initialize(build_dir, source)
|
6
|
+
@build_dir = build_dir
|
7
|
+
@source = source
|
8
|
+
@channel = source.name
|
9
|
+
end
|
10
|
+
|
11
|
+
def product_build_dir
|
12
|
+
File.join(@build_dir, RbConfig::CONFIG["host"], "baseruby-#{@channel}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def install_dir
|
16
|
+
File.join(product_build_dir, "opt")
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
"baseruby-#{@channel}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def build(executor)
|
24
|
+
executor.mkdir_p product_build_dir
|
25
|
+
@source.build(executor)
|
26
|
+
return if Dir.exist?(install_dir)
|
27
|
+
executor.system @source.configure_file,
|
28
|
+
"--prefix=#{install_dir}",
|
29
|
+
"--disable-install-doc",
|
30
|
+
chdir: product_build_dir
|
31
|
+
executor.system "make",
|
32
|
+
"-j#{executor.process_count}",
|
33
|
+
"install",
|
34
|
+
chdir: product_build_dir
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|