From 3cc8c0595e19c80c0e03da21501249205f67666d Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 22 Nov 2023 12:14:05 +0000 Subject: [PATCH 1/2] build: Fix pipe stuck without --verbose and better progress indicator --- Steepfile | 1 + lib/ruby_wasm/build.rb | 107 +++++++++++++++++++++++++++++++--------- sig/ruby_wasm/build.rbs | 13 ++++- 3 files changed, 97 insertions(+), 24 deletions(-) diff --git a/Steepfile b/Steepfile index f705d75bc8..98977dcd8d 100644 --- a/Steepfile +++ b/Steepfile @@ -13,6 +13,7 @@ target :lib do library "open-uri" library "uri" library "shellwords" + library "io-console" configure_code_diagnostics(D::Ruby.default) end diff --git a/lib/ruby_wasm/build.rb b/lib/ruby_wasm/build.rb index efe1e30fa6..2c68f1957d 100644 --- a/lib/ruby_wasm/build.rb +++ b/lib/ruby_wasm/build.rb @@ -10,34 +10,53 @@ def initialize(verbose: false) @github_actions_markup = ENV["ENABLE_GITHUB_ACTIONS_MARKUP"] != nil end - def system(*args, chdir: nil, out: nil, env: nil) + def system(*args, chdir: nil, env: nil) + require "open3" + _print_command(args, env) - if @verbose - out ||= $stdout - else - # Capture stdout by default - out_pipe = IO.pipe - out = out_pipe[1] - end # @type var kwargs: Hash[Symbol, untyped] - kwargs = { exception: true, out: out } + kwargs = {} kwargs[:chdir] = chdir if chdir - begin - if env - Kernel.system(env, *args.to_a.map(&:to_s), **kwargs) - else - Kernel.system(*args.to_a.map(&:to_s), **kwargs) + + args = args.to_a.map(&:to_s) + # TODO: Remove __skip__ once we have open3 RBS definitions. + __skip__ = if @verbose || !$stdout.tty? + kwargs[:exception] = true + env ? Kernel.system(env, *args, **kwargs) : Kernel.system(*args, **kwargs) + else + printer = StatusPrinter.new + block = proc do |stdin, stdout, stderr, wait_thr| + mux = Mutex.new + out = String.new + err = String.new + readers = [[stdout, :stdout, out], [stderr, :stderr, err]].map do |io, name, str| + reader = Thread.new { + while (line = io.gets) + mux.synchronize { + printer.send(name, line) + str << line + } + end + } + reader.report_on_exception = false + reader + end + + readers.each(&:join) + + [out, err, wait_thr.value] + end + begin + env ? Open3.popen3(env, *args, **kwargs, &block) : Open3.popen3(*args, **kwargs, &block) + ensure + printer.done end - ensure - out.close if out_pipe end + rescue => e - if out_pipe - # Print the output of the failed command - puts out_pipe[0].read - end $stdout.flush + $stderr.puts "Try running with `rake --verbose` for more complete output." raise e end @@ -58,9 +77,7 @@ def begin_section(klass, name, note) def end_section(klass, name) took = Time.now - @start_times[[klass, name]] - if @github_actions_markup - puts "::endgroup::" - end + puts "::endgroup::" if @github_actions_markup puts "\e[1;36m==>\e[0m \e[1m#{klass}(#{name}) -- done in #{took.round(2)}s\e[0m" end @@ -98,4 +115,48 @@ def _print_command(args, env) print args.map { |arg| Shellwords.escape(arg.to_s) }.join(" ") + "\n" end end + + # Human readable status printer for the build. + class StatusPrinter + def initialize + @mutex = Mutex.new + @counter = 0 + @indicators = "|/-\\" + end + + def stdout(message) + require "io/console" + @mutex.synchronize { + $stdout.print "\e[K" + first_line = message.lines(chomp: true).first || "" + + # Make sure we don't line-wrap the output + size = __skip__ = IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize + terminal_width = size[1].to_i.nonzero? || 80 + width_limit = terminal_width / 2 - 3 + + if first_line.length > width_limit + first_line = (first_line[0..width_limit - 5] || "") + "..." + end + indicator = @indicators[@counter] || " " + to_print = " " + indicator + " " + first_line + $stdout.print to_print + $stdout.print "\e[1A\n" + @counter += 1 + @counter = 0 if @counter >= @indicators.length + } + end + + def stderr(message) + @mutex.synchronize { + $stdout.print message + } + end + + def done + @mutex.synchronize { + $stdout.print "\e[K" + } + end + end end diff --git a/sig/ruby_wasm/build.rbs b/sig/ruby_wasm/build.rbs index 05cf78c5af..396d533135 100644 --- a/sig/ruby_wasm/build.rbs +++ b/sig/ruby_wasm/build.rbs @@ -227,7 +227,7 @@ module RubyWasm @start_times: Hash[[Class, String], Time] def initialize: (?verbose: bool) -> void - def system: (*_ToS args, ?chdir: String?, ?out: Kernel::redirect_fd?, ?env: Hash[String, String]?) -> void + def system: (*_ToS args, ?chdir: String?, ?env: Hash[String, String]?) -> void def rm_rf: (FileUtils::pathlist list) -> void def rm_f: (FileUtils::pathlist list) -> void def cp_r: (FileUtils::pathlist src, path dest) -> void @@ -241,6 +241,17 @@ module RubyWasm private def _print_command: (Array[_ToS] command, Hash[String, String]? env) -> void end + class StatusPrinter + @mutex: Mutex + @counter: Integer + @indicators: String + + def initialize: () -> void + def stdout: (String message) -> void + def stderr: (String message) -> void + def done: () -> void + end + class Downloader def format_size: (Integer size) -> String From f0dbac1809f84de56ea6996b44f9256a4ae527e4 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Wed, 22 Nov 2023 12:21:26 +0000 Subject: [PATCH 2/2] [skip ci] rake format --- lib/ruby_wasm/build.rb | 92 ++++++++++++++----------- lib/ruby_wasm/build/product/wasi_vfs.rb | 6 +- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/lib/ruby_wasm/build.rb b/lib/ruby_wasm/build.rb index 2c68f1957d..026929cf87 100644 --- a/lib/ruby_wasm/build.rb +++ b/lib/ruby_wasm/build.rb @@ -21,39 +21,53 @@ def system(*args, chdir: nil, env: nil) args = args.to_a.map(&:to_s) # TODO: Remove __skip__ once we have open3 RBS definitions. - __skip__ = if @verbose || !$stdout.tty? - kwargs[:exception] = true - env ? Kernel.system(env, *args, **kwargs) : Kernel.system(*args, **kwargs) - else - printer = StatusPrinter.new - block = proc do |stdin, stdout, stderr, wait_thr| - mux = Mutex.new - out = String.new - err = String.new - readers = [[stdout, :stdout, out], [stderr, :stderr, err]].map do |io, name, str| - reader = Thread.new { - while (line = io.gets) - mux.synchronize { - printer.send(name, line) - str << line - } - end - } - reader.report_on_exception = false - reader + __skip__ = + if @verbose || !$stdout.tty? + kwargs[:exception] = true + if env + Kernel.system(env, *args, **kwargs) + else + Kernel.system(*args, **kwargs) + end + else + printer = StatusPrinter.new + block = + proc do |stdin, stdout, stderr, wait_thr| + mux = Mutex.new + out = String.new + err = String.new + readers = + [ + [stdout, :stdout, out], + [stderr, :stderr, err] + ].map do |io, name, str| + reader = + Thread.new do + while (line = io.gets) + mux.synchronize do + printer.send(name, line) + str << line + end + end + end + reader.report_on_exception = false + reader + end + + readers.each(&:join) + + [out, err, wait_thr.value] + end + begin + if env + Open3.popen3(env, *args, **kwargs, &block) + else + Open3.popen3(*args, **kwargs, &block) + end + ensure + printer.done end - - readers.each(&:join) - - [out, err, wait_thr.value] - end - begin - env ? Open3.popen3(env, *args, **kwargs, &block) : Open3.popen3(*args, **kwargs, &block) - ensure - printer.done end - end - rescue => e $stdout.flush $stderr.puts "Try running with `rake --verbose` for more complete output." @@ -126,12 +140,14 @@ def initialize def stdout(message) require "io/console" - @mutex.synchronize { + @mutex.synchronize do $stdout.print "\e[K" first_line = message.lines(chomp: true).first || "" # Make sure we don't line-wrap the output - size = __skip__ = IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize + size = + __skip__ = + IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize terminal_width = size[1].to_i.nonzero? || 80 width_limit = terminal_width / 2 - 3 @@ -144,19 +160,15 @@ def stdout(message) $stdout.print "\e[1A\n" @counter += 1 @counter = 0 if @counter >= @indicators.length - } + end end def stderr(message) - @mutex.synchronize { - $stdout.print message - } + @mutex.synchronize { $stdout.print message } end def done - @mutex.synchronize { - $stdout.print "\e[K" - } + @mutex.synchronize { $stdout.print "\e[K" } end end end diff --git a/lib/ruby_wasm/build/product/wasi_vfs.rb b/lib/ruby_wasm/build/product/wasi_vfs.rb index 81022d52ee..1d27b0730b 100644 --- a/lib/ruby_wasm/build/product/wasi_vfs.rb +++ b/lib/ruby_wasm/build/product/wasi_vfs.rb @@ -48,7 +48,11 @@ def build(executor) lib_wasi_vfs_url = "https://github.com/kateinoigakukun/wasi-vfs/releases/download/v#{WASI_VFS_VERSION}/libwasi_vfs-wasm32-unknown-unknown.zip" Dir.mktmpdir do |tmpdir| - executor.system "curl", "-L", lib_wasi_vfs_url, "-o", "#{tmpdir}/libwasi_vfs.zip" + executor.system "curl", + "-L", + lib_wasi_vfs_url, + "-o", + "#{tmpdir}/libwasi_vfs.zip" executor.system "unzip", "#{tmpdir}/libwasi_vfs.zip", "-d", tmpdir executor.mkdir_p File.dirname(lib_wasi_vfs_a) executor.mv File.join(tmpdir, "libwasi_vfs.a"), lib_wasi_vfs_a