diff --git a/ruby/private/binary/BUILD.bazel b/ruby/private/binary/BUILD.bazel index e532aa5..b0e2bc3 100644 --- a/ruby/private/binary/BUILD.bazel +++ b/ruby/private/binary/BUILD.bazel @@ -2,7 +2,8 @@ package(default_visibility = ["//ruby/private:__pkg__"]) exports_files( [ - "binary_wrapper.tpl", + "binary_launcher.tpl", + "main_binary_wrapper.tpl", ], visibility = ["//visibility:public"], ) diff --git a/ruby/private/binary/binary.bzl b/ruby/private/binary/binary.bzl index 6dea6de..aaf1544 100644 --- a/ruby/private/binary/binary.bzl +++ b/ruby/private/binary/binary.bzl @@ -59,6 +59,9 @@ def rb_binary_macro(ctx, main, srcs): executable = ctx.actions.declare_file(ctx.attr.name) + launcher_name = ctx.attr.name + "-launcher" + launcher_executable = ctx.actions.declare_file(launcher_name) + deps = _transitive_deps( ctx, extra_files = [executable], @@ -73,12 +76,12 @@ def rb_binary_macro(ctx, main, srcs): rubyopt = reversed(deps.rubyopt.to_list()) ctx.actions.expand_template( - template = ctx.file._wrapper_template, - output = executable, + template = ctx.file._launcher_template, + output = launcher_executable, substitutions = { "{loadpaths}": repr(deps.incpaths.to_list()), + "{rule_name}": ctx.attr.name, "{rubyopt}": repr(rubyopt), - "{main}": repr(_to_manifest_path(ctx, main)), "{interpreter}": _to_manifest_path(ctx, interpreter), "{gem_path}": gem_path, "{bundle_path}": bundle_path, @@ -88,9 +91,20 @@ def rb_binary_macro(ctx, main, srcs): }, ) + ctx.actions.expand_template( + template = ctx.file._wrapper_template, + output = executable, + substitutions = { + "{launcher_name}": launcher_name, + "{main}": repr(_to_manifest_path(ctx, main)), + }, + ) + + runfiles = ctx.runfiles(files = [launcher_executable]) + runfiles = runfiles.merge(deps.default_files.merge(deps.data_files)) info = DefaultInfo( executable = executable, - runfiles = deps.default_files.merge(deps.data_files), + runfiles = runfiles, ) return [info] diff --git a/ruby/private/binary/binary_wrapper.tpl b/ruby/private/binary/binary_launcher.tpl similarity index 96% rename from ruby/private/binary/binary_wrapper.tpl rename to ruby/private/binary/binary_launcher.tpl index 21a7efc..4fbc59f 100644 --- a/ruby/private/binary/binary_wrapper.tpl +++ b/ruby/private/binary/binary_launcher.tpl @@ -21,7 +21,8 @@ require 'rbconfig' def find_runfiles - stub_filename = File.absolute_path($0) + stub_dirname = File.dirname(File.absolute_path($0)) + stub_filename = "#{stub_dirname}/{rule_name}" runfiles = "#{stub_filename}.runfiles" loop do case @@ -113,6 +114,8 @@ def setup_gem_path(runfiles) end def main(args) + raise "Must provide target to launch" if args.empty? + runfiles = find_runfiles runfiles_envkey, runfiles_envvalue = runfiles_envvar(runfiles) @@ -128,7 +131,7 @@ def main(args) ruby_program = find_rb_binary - main = {main} + main = args.shift main = File.join(runfiles, main) rubyopt = {rubyopt}.map do |opt| opt.gsub(/\${(.+?)}/o) do diff --git a/ruby/private/binary/main_binary_wrapper.tpl b/ruby/private/binary/main_binary_wrapper.tpl new file mode 100644 index 0000000..86debcf --- /dev/null +++ b/ruby/private/binary/main_binary_wrapper.tpl @@ -0,0 +1,23 @@ +#!/usr/bin/env ruby + +if __FILE__ == $0 + ## + # Find the launcher + ## + + curr_file = File.absolute_path(__FILE__) + curr_dir = File.dirname(curr_file) + + # Check if it is in this directory + if File.exists?("#{curr_dir}/{launcher_name}") + exec("#{curr_dir}/{launcher_name}", {main}, *ARGV) + end + + # Check if this file is a symlink to the runfiles directory... then it will be there + if File.symlink?(curr_file) && %r!(.*\.runfiles)/.*!o =~ File.readlink(curr_file) + runfiles_dir = File.dirname(File.readlink(curr_file)) + exec("#{runfiles_dir}/{launcher_name}", {main}, *ARGV) + end + + raise "Could not find launcher file! This is likely an issue with rules_ruby" +end diff --git a/ruby/private/constants.bzl b/ruby/private/constants.bzl index 493e17e..d394abd 100644 --- a/ruby/private/constants.bzl +++ b/ruby/private/constants.bzl @@ -30,7 +30,11 @@ RUBY_ATTRS = { ), "_wrapper_template": attr.label( allow_single_file = True, - default = "//ruby/private/binary:binary_wrapper.tpl", + default = "//ruby/private/binary:main_binary_wrapper.tpl", + ), + "_launcher_template": attr.label( + allow_single_file = True, + default = "//ruby/private/binary:binary_launcher.tpl", ), "_misc_deps": attr.label_list( allow_files = True,