Skip to content

Commit 91e6010

Browse files
Merge pull request #310 from ruby/katei/new-build-system
Re-organize build system output
2 parents 07f1fdc + fc66f9f commit 91e6010

File tree

13 files changed

+267
-82
lines changed

13 files changed

+267
-82
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ jobs:
121121
run: rake ${{ matrix.entry.prerelease }}[${{ inputs.prerel_name }}]
122122
if: ${{ inputs.prerel_name != '' && matrix.entry.prerelease != '' }}
123123
- name: rake ${{ matrix.entry.task }}
124-
run: docker run -v "$GITHUB_WORKSPACE:/home/me/build" -w /home/me/build -e "RUBYWASM_UID=$(id -u)" -e "RUBYWASM_GID=$(id -g)" -e "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" ${{ steps.builder-image.outputs.imageid }} rake ${{ matrix.entry.task }}
124+
run: docker run -v "$GITHUB_WORKSPACE:/home/me/build" -w /home/me/build -e "ENABLE_GITHUB_ACTIONS_MARKUP=true" -e "RUBYWASM_UID=$(id -u)" -e "RUBYWASM_GID=$(id -g)" -e "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" ${{ steps.builder-image.outputs.imageid }} rake --verbose ${{ matrix.entry.task }}
125125
- name: rake ${{ matrix.entry.test }}
126126
run: rake ${{ matrix.entry.test }}
127127
if: ${{ matrix.entry.test != '' }}

Steepfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ target :lib do
1212
library "fileutils"
1313
library "open-uri"
1414
library "uri"
15+
library "shellwords"
1516

1617
configure_code_diagnostics(D::Ruby.default)
1718
end

ext/extinit.c.erb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
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
213

314
exts = ARGV
4-
puts ERB.new(DATA.read).run
15+
16+
c_src = ERB.new(DATA.read).result
17+
IO.popen("#{@cc} -c -xc - -o #{@o}", "w") {|f| f << c_src }
518

619
__END__
720
#define init(func, name) { \

lib/ruby_wasm/build.rb

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,63 @@
55
module RubyWasm
66
# Build executor to run the actual build commands.
77
class BuildExecutor
8-
def system(*args, **kwargs)
9-
Kernel.system(*args, **kwargs)
8+
def initialize(verbose: false)
9+
@verbose = verbose
10+
@github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil
11+
end
12+
13+
def system(*args, chdir: nil, out: nil, env: nil)
14+
_print_command(args, env)
15+
16+
if @verbose
17+
out ||= $stdout
18+
else
19+
# Capture stdout by default
20+
out_pipe = IO.pipe
21+
out = out_pipe[1]
22+
end
23+
# @type var kwargs: Hash[Symbol, untyped]
24+
kwargs = { exception: true, out: out }
25+
kwargs[:chdir] = chdir if chdir
26+
begin
27+
if env
28+
Kernel.system(env, *args.to_a.map(&:to_s), **kwargs)
29+
else
30+
Kernel.system(*args.to_a.map(&:to_s), **kwargs)
31+
end
32+
ensure
33+
out.close if out_pipe
34+
end
35+
rescue => e
36+
if out_pipe
37+
# Print the output of the failed command
38+
puts out_pipe[0].read
39+
end
40+
$stdout.flush
41+
raise e
42+
end
43+
44+
def begin_section(klass, name, note)
45+
message = "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- #{note}\e[0m"
46+
if @github_actions_markup
47+
puts "::group::#{message}"
48+
else
49+
puts message
50+
end
51+
52+
# Record the start time
53+
@start_times ||= Hash.new
54+
@start_times[[klass, name]] = Time.now
55+
56+
$stdout.flush
57+
end
58+
59+
def end_section(klass, name)
60+
took = Time.now - @start_times[[klass, name]]
61+
if @github_actions_markup
62+
puts "::endgroup::"
63+
end
64+
puts "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- done in #{took.round(2)}s\e[0m"
1065
end
1166

1267
def rm_rf(list)
@@ -32,5 +87,15 @@ def mkdir_p(list)
3287
def write(path, data)
3388
File.write(path, data)
3489
end
90+
91+
private
92+
93+
def _print_command(args, env)
94+
require "shellwords"
95+
# Bold cyan
96+
print "\e[1;36m ==>\e[0m "
97+
print "env " + env.map { |k, v| "#{k}=#{v}" }.join(" ") + " " if env
98+
print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n"
99+
end
35100
end
36101
end

lib/ruby_wasm/build/product/baseruby.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ def build(executor)
2424
executor.mkdir_p product_build_dir
2525
@source.build(executor)
2626
return if Dir.exist?(install_dir)
27-
Dir.chdir(product_build_dir) do
28-
executor.system "#{@source.configure_file} --prefix=#{install_dir} --disable-install-doc"
29-
executor.system "make install"
30-
end
27+
executor.system @source.configure_file,
28+
"--prefix=#{install_dir}",
29+
"--disable-install-doc",
30+
chdir: product_build_dir
31+
executor.system "make", "install", chdir: product_build_dir
3132
end
3233
end
3334
end

lib/ruby_wasm/build/product/crossruby.rb

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ def build(executor, crossruby)
3232
objdir = product_build_dir crossruby
3333
executor.mkdir_p objdir
3434
do_extconf executor, crossruby
35-
executor.system %Q(make -C "#{objdir}" #{make_args(crossruby).join(" ")} #{lib}.a)
35+
executor.system "make",
36+
"-C",
37+
"#{objdir}",
38+
*make_args(crossruby),
39+
"#{lib}.a"
3640
# A ext can provide link args by link.filelist. It contains only built archive file by default.
3741
unless File.exist?(linklist(crossruby))
3842
executor.write(
@@ -49,31 +53,34 @@ def do_extconf(executor, crossruby)
4953
"--disable=gems",
5054
# HACK: top_srcdir is required to find ruby headers
5155
"-e",
52-
%Q('$top_srcdir="#{source.src_dir}"'),
56+
%Q($top_srcdir="#{source.src_dir}"),
5357
# HACK: extout is required to find config.h
5458
"-e",
55-
%Q('$extout="#{crossruby.build_dir}/.ext"'),
59+
%Q($extout="#{crossruby.build_dir}/.ext"),
5660
# HACK: force static ext build by imitating extmk
5761
"-e",
58-
"'$static = true; trace_var(:$static) {|v| $static = true }'",
62+
"$static = true; trace_var(:$static) {|v| $static = true }",
5963
# HACK: $0 should be extconf.rb path due to mkmf source file detection
6064
# and we want to insert some hacks before it. But -e and $0 cannot be
6165
# used together, so we rewrite $0 in -e.
6266
"-e",
63-
%Q('$0="#{@srcdir}/extconf.rb"'),
67+
%Q($0="#{@srcdir}/extconf.rb"),
6468
"-e",
65-
%Q('require_relative "#{@srcdir}/extconf.rb"'),
69+
%Q(require_relative "#{@srcdir}/extconf.rb"),
6670
"-I#{crossruby.build_dir}"
6771
]
6872
# Clear RUBYOPT to avoid loading unrelated bundle setup
69-
executor.system ({ "RUBYOPT" => "" }),
70-
"#{crossruby.baseruby_path} #{extconf_args.join(" ")}",
71-
chdir: objdir
73+
executor.system crossruby.baseruby_path,
74+
*extconf_args,
75+
chdir: objdir,
76+
env: {
77+
"RUBYOPT" => ""
78+
}
7279
end
7380

7481
def do_install_rb(executor, crossruby)
7582
objdir = product_build_dir crossruby
76-
executor.system %Q(make -C "#{objdir}" #{make_args(crossruby).join(" ")} install-rb)
83+
executor.system "make", "-C", objdir, *make_args(crossruby), "install-rb"
7784
end
7885

7986
def cache_key(digest)
@@ -129,38 +136,58 @@ def initialize(
129136
def configure(executor, reconfigure: false)
130137
if !File.exist?("#{build_dir}/Makefile") || reconfigure
131138
args = configure_args(RbConfig::CONFIG["host"], toolchain)
132-
executor.system "#{source.configure_file} #{args.join(" ")}",
133-
chdir: build_dir
139+
executor.system source.configure_file, *args, chdir: build_dir
134140
end
135141
# NOTE: we need rbconfig.rb at configuration time to build user given extensions with mkmf
136-
executor.system "make rbconfig.rb", chdir: build_dir
142+
executor.system "make", "rbconfig.rb", chdir: build_dir
137143
end
138144

139145
def build_exts(executor)
140-
@user_exts.each { |prod| prod.build(executor, self) }
141-
executor.mkdir_p File.dirname(extinit_obj)
142-
executor.system %Q(ruby #{extinit_c_erb} #{@user_exts.map(&:name).join(" ")} | #{toolchain.cc} -c -x c - -o #{extinit_obj})
146+
@user_exts.each do |prod|
147+
executor.begin_section prod.class, prod.name, "Building"
148+
prod.build(executor, self)
149+
executor.end_section prod.class, prod.name
150+
end
143151
end
144152

145153
def build(executor, remake: false, reconfigure: false)
146154
executor.mkdir_p dest_dir
147155
executor.mkdir_p build_dir
148156
@toolchain.install
149157
[@source, @baseruby, @libyaml, @zlib, @openssl, @wasi_vfs].each do |prod|
158+
executor.begin_section prod.class, prod.name, "Building"
150159
prod.build(executor)
160+
executor.end_section prod.class, prod.name
151161
end
162+
executor.begin_section self.class, name, "Configuring"
152163
configure(executor, reconfigure: reconfigure)
164+
executor.end_section self.class, name
165+
153166
build_exts(executor)
154167

168+
executor.begin_section self.class, name, "Building"
169+
executor.mkdir_p File.dirname(extinit_obj)
170+
executor.system "ruby",
171+
extinit_c_erb,
172+
*@user_exts.map(&:name),
173+
"--cc",
174+
toolchain.cc,
175+
"--output",
176+
extinit_obj
155177
install_dir = File.join(build_dir, "install")
156178
if !File.exist?(install_dir) || remake || reconfigure
157-
executor.system "make install DESTDIR=#{install_dir}", chdir: build_dir
179+
executor.system "make",
180+
"install",
181+
"DESTDIR=#{install_dir}",
182+
chdir: build_dir
158183
end
159184

160185
executor.rm_rf dest_dir
161186
executor.cp_r install_dir, dest_dir
162187
@user_exts.each { |ext| ext.do_install_rb(executor, self) }
163-
executor.system "tar cfz #{artifact} -C rubies #{name}"
188+
executor.system "tar", "cfz", artifact, "-C", "rubies", name
189+
190+
executor.end_section self.class, name
164191
end
165192

166193
def clean(executor)
@@ -241,11 +268,11 @@ def configure_args(build_triple, toolchain)
241268

242269
args = self.system_triplet_args + ["--build", build_triple]
243270
args << "--with-static-linked-ext"
244-
args << %Q(--with-ext="#{default_exts}")
245-
args << %Q(--with-libyaml-dir="#{@libyaml.install_root}")
246-
args << %Q(--with-zlib-dir="#{@zlib.install_root}")
247-
args << %Q(--with-openssl-dir="#{@openssl.install_root}") if @openssl
248-
args << %Q(--with-baseruby="#{baseruby_path}")
271+
args << %Q(--with-ext=#{default_exts})
272+
args << %Q(--with-libyaml-dir=#{@libyaml.install_root})
273+
args << %Q(--with-zlib-dir=#{@zlib.install_root})
274+
args << %Q(--with-openssl-dir=#{@openssl.install_root}) if @openssl
275+
args << %Q(--with-baseruby=#{baseruby_path})
249276

250277
case target
251278
when "wasm32-unknown-wasi"
@@ -270,13 +297,13 @@ def configure_args(build_triple, toolchain)
270297
xcflags << "-DWASM_FIBER_STACK_BUFFER_SIZE=24576"
271298
xcflags << "-DWASM_SCAN_STACK_BUFFER_SIZE=24576"
272299

273-
args << %Q(LDFLAGS="#{ldflags.join(" ")}")
274-
args << %Q(XLDFLAGS="#{xldflags.join(" ")}")
275-
args << %Q(XCFLAGS="#{xcflags.join(" ")}")
276-
args << %Q(debugflags="#{@debugflags.join(" ")}")
277-
args << %Q(cppflags="#{@cppflags.join(" ")}")
300+
args << %Q(LDFLAGS=#{ldflags.join(" ")})
301+
args << %Q(XLDFLAGS=#{xldflags.join(" ")})
302+
args << %Q(XCFLAGS=#{xcflags.join(" ")})
303+
args << %Q(debugflags=#{@debugflags.join(" ")})
304+
args << %Q(cppflags=#{@cppflags.join(" ")})
278305
unless wasmoptflags.empty?
279-
args << %Q(wasmoptflags="#{@wasmoptflags.join(" ")}")
306+
args << %Q(wasmoptflags=#{@wasmoptflags.join(" ")})
280307
end
281308
args << "--disable-install-doc"
282309
args

lib/ruby_wasm/build/product/libyaml.rb

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,43 @@ def install_root
2525
end
2626

2727
def name
28-
product_build_dir
28+
"libyaml-#{LIBYAML_VERSION}-#{target}"
2929
end
3030

3131
def build(executor)
3232
return if Dir.exist?(install_root)
3333

3434
executor.mkdir_p File.dirname(product_build_dir)
3535
executor.rm_rf product_build_dir
36-
executor.system "curl -L https://github.com/yaml/libyaml/releases/download/#{LIBYAML_VERSION}/yaml-#{LIBYAML_VERSION}.tar.gz | tar xz",
37-
chdir: File.dirname(product_build_dir)
36+
executor.mkdir_p product_build_dir
37+
tarball_path =
38+
File.join(product_build_dir, "libyaml-#{LIBYAML_VERSION}.tar.gz")
39+
executor.system "curl",
40+
"-o",
41+
tarball_path,
42+
"-L",
43+
"https://github.com/yaml/libyaml/releases/download/#{LIBYAML_VERSION}/yaml-#{LIBYAML_VERSION}.tar.gz"
44+
executor.system "tar",
45+
"xzf",
46+
tarball_path,
47+
"-C",
48+
product_build_dir,
49+
"--strip-components=1"
3850

3951
# obtain the latest config.guess and config.sub for Emscripten and WASI triple support
40-
executor.system "curl -o #{product_build_dir}/config/config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'"
41-
executor.system "curl -o #{product_build_dir}/config/config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'"
52+
executor.system "curl",
53+
"-o",
54+
"#{product_build_dir}/config/config.guess",
55+
"https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD"
56+
executor.system "curl",
57+
"-o",
58+
"#{product_build_dir}/config/config.sub",
59+
"https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD"
4260

43-
executor.system "./configure #{configure_args.join(" ")}",
44-
chdir: product_build_dir
45-
executor.system "make install DESTDIR=#{destdir}",
61+
executor.system "./configure", *configure_args, chdir: product_build_dir
62+
executor.system "make",
63+
"install",
64+
"DESTDIR=#{destdir}",
4665
chdir: product_build_dir
4766
end
4867
end

lib/ruby_wasm/build/product/openssl.rb

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def install_root
2626
end
2727

2828
def name
29-
product_build_dir
29+
"openssl-#{OPENSSL_VERSION}-#{target}"
3030
end
3131

3232
def configure_args
@@ -59,14 +59,28 @@ def build(executor)
5959

6060
executor.mkdir_p File.dirname(product_build_dir)
6161
executor.rm_rf product_build_dir
62-
executor.system "curl -L https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz | tar xz",
63-
chdir: File.dirname(product_build_dir)
62+
executor.mkdir_p product_build_dir
63+
tarball_path =
64+
File.join(product_build_dir, "openssl-#{OPENSSL_VERSION}.tar.gz")
65+
executor.system "curl",
66+
"-o",
67+
tarball_path,
68+
"-L",
69+
"https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
70+
executor.system "tar",
71+
"xzf",
72+
tarball_path,
73+
"-C",
74+
product_build_dir,
75+
"--strip-components=1"
6476

65-
executor.system "./Configure #{configure_args.join(" ")}",
66-
chdir: product_build_dir
77+
executor.system "./Configure", *configure_args, chdir: product_build_dir
6778
# Use "install_sw" instead of "install" because it tries to install docs and it's very slow.
6879
# OpenSSL build system doesn't have well support for parallel build, so force -j1.
69-
executor.system "make -j1 install_sw DESTDIR=#{destdir}",
80+
executor.system "make",
81+
"-j1",
82+
"install_sw",
83+
"DESTDIR=#{destdir}",
7084
chdir: product_build_dir
7185
end
7286
end

0 commit comments

Comments
 (0)