Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: Introduce BuildExecutor to manage actual command invocation #307

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions lib/ruby_wasm/build.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,34 @@
require_relative "build/toolchain"

module RubyWasm
# Build executor to run the actual build commands.
class BuildExecutor
def system(*args, **kwargs)
Kernel.system(*args, **kwargs)
end

def rm_rf(list)
FileUtils.rm_rf(list)
end

def rm_f(list)
FileUtils.rm_f(list)
end

def cp_r(src, dest)
FileUtils.cp_r(src, dest)
end

def mv(src, dest)
FileUtils.mv(src, dest)
end

def mkdir_p(list)
FileUtils.mkdir_p(list)
end

def write(path, data)
File.write(path, data)
end
end
end
10 changes: 5 additions & 5 deletions lib/ruby_wasm/build/product/baseruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ def name
"baseruby-#{@channel}"
end

def build
FileUtils.mkdir_p product_build_dir
@source.build
def build(executor)
executor.mkdir_p product_build_dir
@source.build(executor)
return if Dir.exist?(install_dir)
Dir.chdir(product_build_dir) do
system "#{@source.configure_file} --prefix=#{install_dir} --disable-install-doc"
system "make install"
executor.system "#{@source.configure_file} --prefix=#{install_dir} --disable-install-doc"
executor.system "make install"
end
end
end
Expand Down
74 changes: 40 additions & 34 deletions lib/ruby_wasm/build/product/crossruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,22 @@ def make_args(crossruby)
make_args
end

def build(crossruby)
def build(executor, crossruby)
lib = @name
objdir = product_build_dir crossruby
FileUtils.mkdir_p objdir
do_extconf crossruby
system %Q(make -C "#{objdir}" #{make_args(crossruby).join(" ")} #{lib}.a)
executor.mkdir_p objdir
do_extconf executor, crossruby
executor.system %Q(make -C "#{objdir}" #{make_args(crossruby).join(" ")} #{lib}.a)
# A ext can provide link args by link.filelist. It contains only built archive file by default.
unless File.exist?(linklist(crossruby))
File.write(linklist(crossruby), Dir.glob("#{objdir}/*.a").join("\n"))
executor.write(
linklist(crossruby),
Dir.glob("#{objdir}/*.a").join("\n")
)
end
end

def do_extconf(crossruby)
def do_extconf(executor, crossruby)
objdir = product_build_dir crossruby
source = crossruby.source
extconf_args = [
Expand All @@ -63,14 +66,14 @@ def do_extconf(crossruby)
"-I#{crossruby.build_dir}"
]
# Clear RUBYOPT to avoid loading unrelated bundle setup
system ({ "RUBYOPT" => "" }),
"#{crossruby.baseruby_path} #{extconf_args.join(" ")}",
chdir: objdir
executor.system ({ "RUBYOPT" => "" }),
"#{crossruby.baseruby_path} #{extconf_args.join(" ")}",
chdir: objdir
end

def do_install_rb(crossruby)
def do_install_rb(executor, crossruby)
objdir = product_build_dir crossruby
system %Q(make -C "#{objdir}" #{make_args(crossruby).join(" ")} install-rb)
executor.system %Q(make -C "#{objdir}" #{make_args(crossruby).join(" ")} install-rb)
end

def cache_key(digest)
Expand Down Expand Up @@ -123,45 +126,48 @@ def initialize(
super(@params.target, @toolchain)
end

def configure(reconfigure: false)
def configure(executor, reconfigure: false)
if !File.exist?("#{build_dir}/Makefile") || reconfigure
args = configure_args(RbConfig::CONFIG["host"], toolchain)
system "#{source.configure_file} #{args.join(" ")}", chdir: build_dir
executor.system "#{source.configure_file} #{args.join(" ")}",
chdir: build_dir
end
# NOTE: we need rbconfig.rb at configuration time to build user given extensions with mkmf
system "make rbconfig.rb", chdir: build_dir
executor.system "make rbconfig.rb", chdir: build_dir
end

def build_exts
@user_exts.each { |prod| prod.build(self) }
FileUtils.mkdir_p File.dirname(extinit_obj)
system %Q(ruby #{extinit_c_erb} #{@user_exts.map(&:name).join(" ")} | #{toolchain.cc} -c -x c - -o #{extinit_obj})
def build_exts(executor)
@user_exts.each { |prod| prod.build(executor, self) }
executor.mkdir_p File.dirname(extinit_obj)
executor.system %Q(ruby #{extinit_c_erb} #{@user_exts.map(&:name).join(" ")} | #{toolchain.cc} -c -x c - -o #{extinit_obj})
end

def build(remake: false, reconfigure: false)
FileUtils.mkdir_p dest_dir
FileUtils.mkdir_p build_dir
def build(executor, remake: false, reconfigure: false)
executor.mkdir_p dest_dir
executor.mkdir_p build_dir
@toolchain.install
[@source, @baseruby, @libyaml, @zlib, @openssl, @wasi_vfs].each(&:build)
configure(reconfigure: reconfigure)
build_exts
[@source, @baseruby, @libyaml, @zlib, @openssl, @wasi_vfs].each do |prod|
prod.build(executor)
end
configure(executor, reconfigure: reconfigure)
build_exts(executor)

install_dir = File.join(build_dir, "install")
if !File.exist?(install_dir) || remake || reconfigure
system "make install DESTDIR=#{install_dir}", chdir: build_dir
executor.system "make install DESTDIR=#{install_dir}", chdir: build_dir
end

FileUtils.rm_rf dest_dir
FileUtils.cp_r install_dir, dest_dir
@user_exts.each { |ext| ext.do_install_rb(self) }
system "tar cfz #{artifact} -C rubies #{name}"
executor.rm_rf dest_dir
executor.cp_r install_dir, dest_dir
@user_exts.each { |ext| ext.do_install_rb(executor, self) }
executor.system "tar cfz #{artifact} -C rubies #{name}"
end

def clean
FileUtils.rm_rf dest_dir
FileUtils.rm_rf build_dir
FileUtils.rm_rf ext_build_dir
FileUtils.rm_f artifact
def clean(executor)
executor.rm_rf dest_dir
executor.rm_rf build_dir
executor.rm_rf ext_build_dir
executor.rm_f artifact
end

def name
Expand Down
20 changes: 11 additions & 9 deletions lib/ruby_wasm/build/product/libyaml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,22 @@ def name
product_build_dir
end

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

FileUtils.mkdir_p File.dirname(product_build_dir)
FileUtils.rm_rf product_build_dir
system "curl -L https://github.com/yaml/libyaml/releases/download/#{LIBYAML_VERSION}/yaml-#{LIBYAML_VERSION}.tar.gz | tar xz",
chdir: File.dirname(product_build_dir)
executor.mkdir_p File.dirname(product_build_dir)
executor.rm_rf product_build_dir
executor.system "curl -L https://github.com/yaml/libyaml/releases/download/#{LIBYAML_VERSION}/yaml-#{LIBYAML_VERSION}.tar.gz | tar xz",
chdir: File.dirname(product_build_dir)

# obtain the latest config.guess and config.sub for Emscripten and WASI triple support
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'"
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'"
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'"
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'"

system "./configure #{configure_args.join(" ")}", chdir: product_build_dir
system "make install DESTDIR=#{destdir}", chdir: product_build_dir
executor.system "./configure #{configure_args.join(" ")}",
chdir: product_build_dir
executor.system "make install DESTDIR=#{destdir}",
chdir: product_build_dir
end
end
end
16 changes: 9 additions & 7 deletions lib/ruby_wasm/build/product/openssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,20 @@ def configure_args
args + tools_args
end

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

FileUtils.mkdir_p File.dirname(product_build_dir)
FileUtils.rm_rf product_build_dir
system "curl -L https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz | tar xz",
chdir: File.dirname(product_build_dir)
executor.mkdir_p File.dirname(product_build_dir)
executor.rm_rf product_build_dir
executor.system "curl -L https://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz | tar xz",
chdir: File.dirname(product_build_dir)

system "./Configure #{configure_args.join(" ")}", chdir: product_build_dir
executor.system "./Configure #{configure_args.join(" ")}",
chdir: product_build_dir
# Use "install_sw" instead of "install" because it tries to install docs and it's very slow.
# OpenSSL build system doesn't have well support for parallel build, so force -j1.
system "make -j1 install_sw DESTDIR=#{destdir}", chdir: product_build_dir
executor.system "make -j1 install_sw DESTDIR=#{destdir}",
chdir: product_build_dir
end
end
end
30 changes: 16 additions & 14 deletions lib/ruby_wasm/build/product/ruby_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,37 +31,39 @@ def configure_file
File.join(src_dir, "configure")
end

def fetch
def fetch(executor)
case @params[:type]
when "github"
repo_url = "https://github.com/#{@params[:repo]}.git"
FileUtils.mkdir_p src_dir
system "git init", chdir: src_dir
system "git remote add origin #{repo_url}", chdir: src_dir
system(
executor.mkdir_p src_dir
executor.system "git init", chdir: src_dir
executor.system "git remote add origin #{repo_url}", chdir: src_dir
executor.system(
"git fetch --depth 1 origin #{@params[:rev]}:origin/#{@params[:rev]}",
chdir: src_dir
) or raise "failed to clone #{repo_url}"
system("git checkout origin/#{@params[:rev]}", chdir: src_dir) or
raise "failed to checkout #{@params[:rev]}"
executor.system(
"git checkout origin/#{@params[:rev]}",
chdir: src_dir
) or raise "failed to checkout #{@params[:rev]}"
when "local"
FileUtils.mkdir_p File.dirname(src_dir)
FileUtils.cp_r @params[:src], src_dir
executor.mkdir_p File.dirname(src_dir)
executor.cp_r @params[:src], src_dir
else
raise "unknown source type: #{@params[:type]}"
end
(@params[:patches] || []).each do |patch_path|
system "patch -p1 < #{patch_path}", chdir: src_dir
executor.system "patch -p1 < #{patch_path}", chdir: src_dir
end
end

def build
fetch unless File.exist?(src_dir)
def build(executor)
fetch(executor) unless File.exist?(src_dir)
unless File.exist?(configure_file)
Dir.chdir(src_dir) do
system "ruby tool/downloader.rb -d tool -e gnu config.guess config.sub" or
executor.system "ruby tool/downloader.rb -d tool -e gnu config.guess config.sub" or
raise "failed to download config.guess and config.sub"
system "./autogen.sh" or raise "failed to run autogen.sh"
executor.system "./autogen.sh" or raise "failed to run autogen.sh"
end
end
end
Expand Down
10 changes: 5 additions & 5 deletions lib/ruby_wasm/build/product/wasi_vfs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ def name
lib_product_build_dir
end

def build
def build(executor)
return if !@need_fetch_lib || File.exist?(lib_wasi_vfs_a)
require "tmpdir"
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|
system "curl -L #{lib_wasi_vfs_url} -o #{tmpdir}/libwasi_vfs.zip"
system "unzip #{tmpdir}/libwasi_vfs.zip -d #{tmpdir}"
FileUtils.mkdir_p File.dirname(lib_wasi_vfs_a)
FileUtils.mv File.join(tmpdir, "libwasi_vfs.a"), lib_wasi_vfs_a
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
end
end

Expand Down
19 changes: 10 additions & 9 deletions lib/ruby_wasm/build/product/zlib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,20 @@ def configure_args
args + tools_args
end

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

FileUtils.mkdir_p File.dirname(product_build_dir)
FileUtils.rm_rf product_build_dir
executor.mkdir_p File.dirname(product_build_dir)
executor.rm_rf product_build_dir

system "curl -L https://zlib.net/zlib-#{ZLIB_VERSION}.tar.gz | tar xz",
chdir: File.dirname(product_build_dir),
exception: true
executor.system "curl -L https://zlib.net/zlib-#{ZLIB_VERSION}.tar.gz | tar xz",
chdir: File.dirname(product_build_dir),
exception: true

system "#{configure_args.join(" ")} ./configure --static",
chdir: product_build_dir
system "make install DESTDIR=#{destdir}", chdir: product_build_dir
executor.system "#{configure_args.join(" ")} ./configure --static",
chdir: product_build_dir
executor.system "make install DESTDIR=#{destdir}",
chdir: product_build_dir
end
end
end
10 changes: 6 additions & 4 deletions lib/ruby_wasm/rake_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,22 @@ def initialize(
@crossruby.with_wasi_vfs @wasi_vfs
@crossruby.with_openssl @openssl

executor = RubyWasm::BuildExecutor.new

desc "Cross-build Ruby for #{@target}"
task name do
next if File.exist? @crossruby.artifact
@crossruby.build
@crossruby.build(executor)
end
namespace name do
task :remake do
@crossruby.build(remake: true)
@crossruby.build(executor, remake: true)
end
task :reconfigure do
@crossruby.build(reconfigure: true)
@crossruby.build(executor, reconfigure: true)
end
task :clean do
@crossruby.clean
@crossruby.clean(executor)
end
end
end
Expand Down