diff --git a/ruby/private/binary.bzl b/ruby/private/binary.bzl index 3c8761a..a354d73 100644 --- a/ruby/private/binary.bzl +++ b/ruby/private/binary.bzl @@ -12,6 +12,13 @@ def _to_manifest_path(ctx, file): return ("%s/%s" % (ctx.workspace_name, file.short_path)) def _ruby_binary_impl(ctx): + return _ruby_binary_rules_impl( + ctx, + program = None, + program_opts = ["--disable-gems"], + ) + +def _ruby_binary_rules_impl(ctx, program, program_opts=[]): sdk = ctx.toolchains[TOOLCHAIN_TYPE_NAME].ruby_runtime interpreter = sdk.interpreter[DefaultInfo].files_to_run.executable @@ -29,7 +36,7 @@ def _ruby_binary_impl(ctx): "main", ) - if sdk.is_host: + if sdk.is_host and not program: interpreter_file_deps = [] interpreter_trans_deps = [] else: @@ -49,10 +56,18 @@ def _ruby_binary_impl(ctx): template = ctx.file._wrapper_template, output = intermediate_executable, substitutions = { + # The ruby interpreter + "{interpreter}": _to_manifest_path(ctx, interpreter), + # $LOAD_PATH "{loadpaths}": repr(deps.incpaths.to_list()), + # options for the ruby interpreter "{rubyopt}": repr(rubyopt), + # program which evaluates the main script. e.g. ruby, erb, or rake + "{program}": repr(program) if program else 'nil', + # options for the program. + "{program_opts}": repr(program_opts), + # the main script "{main}": repr(_to_manifest_path(ctx, main)), - "{interpreter}": _to_manifest_path(ctx, interpreter), }, ) if sdk.is_host: diff --git a/ruby/private/binary_wrapper.tpl b/ruby/private/binary_wrapper.tpl index 765dd7a..8df515e 100644 --- a/ruby/private/binary_wrapper.tpl +++ b/ruby/private/binary_wrapper.tpl @@ -24,6 +24,7 @@ # require 'rbconfig' +require 'shellwords' def find_runfiles stub_filename = File.absolute_path($0) @@ -89,13 +90,26 @@ def runfiles_envvar(runfiles) end end -def find_ruby_binary +def find_ruby_program File.join( RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'], ) end +def expand_vars(args) + args.map do |arg| + arg.gsub(/\${(.+?)}/o) do + case $1 + when 'RUNFILES_DIR' + runfiles + else + ENV[$1] + end + end + end +end + def main(args) custom_loadpaths = {loadpaths} runfiles = find_runfiles @@ -108,21 +122,20 @@ def main(args) runfiles_envkey, runfiles_envvalue = runfiles_envvar(runfiles) ENV[runfiles_envkey] = runfiles_envvalue if runfiles_envkey - ruby_program = find_ruby_binary + program_name = {program} + if program_name + program = File.join(runfiles, program_name) + else + program = find_ruby_program + end + program_opts = expand_vars({program_opts}) main = {main} main = File.join(runfiles, main) - rubyopt = {rubyopt}.map do |opt| - opt.gsub(/\${(.+?)}/o) do - case $1 - when 'RUNFILES_DIR' - runfiles - else - ENV[$1] - end - end - end - exec(ruby_program, '--disable-gems', *rubyopt, main, *args) + rubyopt = expand_vars({rubyopt}) + ENV['RUBYOPT'] = Shellwords.join(expand_vars({rubyopt})) + + exec(program, *program_opts, main, *args) # TODO(yugui) Support windows end diff --git a/ruby/tests/BUILD.bazel b/ruby/tests/BUILD.bazel index 298b600..6ef7a78 100644 --- a/ruby/tests/BUILD.bazel +++ b/ruby/tests/BUILD.bazel @@ -252,6 +252,7 @@ container_image( base = "@ruby_base_container//image", entrypoint = ["/app/load_path_in_runfiles"], tars = [":load_path_in_runfiles_container_layer"], + tags = ["docker"], ) sh_test(