From f62f51c661e2647744b398c795391c35b56928a3 Mon Sep 17 00:00:00 2001 From: Yugui Sonoda Date: Wed, 11 Dec 2019 21:09:37 +0900 Subject: [PATCH 1/3] temp --- ruby/private/binary.bzl | 19 ++++++++++++++-- ruby/private/binary_wrapper.tpl | 39 ++++++++++++++++++++++----------- ruby/tests/BUILD.bazel | 1 + 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/ruby/private/binary.bzl b/ruby/private/binary.bzl index 3c8761a7..a354d733 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 765dd7a4..8df515e0 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 298b600a..6ef7a785 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( From 16d66e4c5da11189f1d8b9b11cd70d69565c76db Mon Sep 17 00:00:00 2001 From: Yuki Yugui Sonoda Date: Sun, 15 Dec 2019 20:32:37 +0900 Subject: [PATCH 2/3] temp --- ruby/private/binary_wrapper.tpl | 113 +------------------------- ruby/private/tools/runfiles.rb | 136 ++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 110 deletions(-) create mode 100644 ruby/private/tools/runfiles.rb diff --git a/ruby/private/binary_wrapper.tpl b/ruby/private/binary_wrapper.tpl index 8df515e0..bc7eecd7 100644 --- a/ruby/private/binary_wrapper.tpl +++ b/ruby/private/binary_wrapper.tpl @@ -23,119 +23,12 @@ # limitations under the License. # -require 'rbconfig' -require 'shellwords' - -def find_runfiles - stub_filename = File.absolute_path($0) - runfiles = "#{stub_filename}.runfiles" - loop do - case - when File.directory?(runfiles) - return runfiles - when %r!(.*\.runfiles)/.*!o =~ stub_filename - return $1 - when File.symlink?(stub_filename) - target = File.readlink(stub_filename) - stub_filename = File.absolute_path(target, File.dirname(stub_filename)) - else - break - end - end - raise "Cannot find .runfiles directory for #{$0}" -end - -def create_loadpath_entries(custom, runfiles) - [runfiles] + custom.map {|path| File.join(runfiles, path) } -end - -def get_repository_imports(runfiles) - Dir.children(runfiles).map {|d| - File.join(runfiles, d) - }.select {|d| - File.directory? d - } -end - -# Finds the runfiles manifest or the runfiles directory. -def runfiles_envvar(runfiles) - # If this binary is the data-dependency of another one, the other sets - # RUNFILES_MANIFEST_FILE or RUNFILES_DIR for our sake. - manifest = ENV['RUNFILES_MANIFEST_FILE'] - if manifest - return ['RUNFILES_MANIFEST_FILE', manifest] - end - - dir = ENV['RUNFILES_DIR'] - if dir - return ['RUNFILES_DIR', dir] - end - - # Look for the runfiles "output" manifest, argv[0] + ".runfiles_manifest" - manifest = runfiles + '_manifest' - if File.exists?(manifest) - return ['RUNFILES_MANIFEST_FILE', manifest] - end - - # Look for the runfiles "input" manifest, argv[0] + ".runfiles/MANIFEST" - manifest = File.join(runfiles, 'MANIFEST') - if File.exists?(manifest) - return ['RUNFILES_DIR', manifest] - end - - # If running in a sandbox and no environment variables are set, then - # Look for the runfiles next to the binary. - if runfiles.end_with?('.runfiles') and File.directory?(runfiles) - return ['RUNFILES_DIR', runfiles] - end -end - -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 - - loadpaths = create_loadpath_entries(custom_loadpaths, runfiles) - loadpaths += get_repository_imports(runfiles) - loadpaths += ENV['RUBYLIB'].split(':') if ENV.key?('RUBYLIB') - ENV['RUBYLIB'] = loadpaths.join(':') - - runfiles_envkey, runfiles_envvalue = runfiles_envvar(runfiles) - ENV[runfiles_envkey] = runfiles_envvalue if runfiles_envkey - - program_name = {program} - if program_name - program = File.join(runfiles, program_name) - else - program = find_ruby_program - end - program_opts = expand_vars({program_opts}) - + rubyopt = {rubyopt} main = {main} - main = File.join(runfiles, main) - rubyopt = expand_vars({rubyopt}) - ENV['RUBYOPT'] = Shellwords.join(expand_vars({rubyopt})) - exec(program, *program_opts, main, *args) + Runfiles.new(custom_loadpaths, rubyopt).exec(main, *args) # TODO(yugui) Support windows end @@ -159,4 +52,4 @@ end #shell { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e #shell # --- end runfiles.bash initialization v2 --- #shell -#shell exec "$(rlocation {interpreter})" ${BASH_SOURCE:-$0} "$@" +#shell exec "$(rlocation {interpreter})" -r"$(rlocation @bazelruby_ruby_rules//ruby/private/tools:runfiles.rb)" ${BASH_SOURCE:-$0} "$@" diff --git a/ruby/private/tools/runfiles.rb b/ruby/private/tools/runfiles.rb new file mode 100644 index 00000000..01e2da2c --- /dev/null +++ b/ruby/private/tools/runfiles.rb @@ -0,0 +1,136 @@ +require 'rbconfig' +require 'shellwords' + +# Based on the Bazel's binary wrapper script for Python + +# Copyright 2017 The Bazel Authors. All rights reserved. +# Copyright 2019 BazelRuby Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'rbconfig' +require 'shellwords' + +class Runfiles + def initialize(load_paths, rubyopt) + @runfiles = find_runfiles + @rubyopt = rubyopt + + loadpaths = create_loadpath_entries(load_paths, @runfiles) + loadpaths += get_repository_imports(@runfiles) + loadpaths += ENV['RUBYLIB'].split(':') if ENV.key?('RUBYLIB') + @loadpaths = loadpaths + end + + def exec(program, program_opts:, argv:) + runfiles_envkey, runfiles_envvalue = runfiles_envvar(runfiles) + ENV[runfiles_envkey] = runfiles_envvalue if runfiles_envkey + ENV['RUBYOPT'] = Shellwords.join(expand_vars(@rubyopt)) + ENV['RUBYLIB'] = @loadpaths.join(':') + + program_opts = expand_vars(program_opts || []) + exec(program, *program_opts, *argv) + end + + def exec_script(script, *argv) + ruby = find_ruby_program + script = File.join(@runfiles, script) + exec(ruby, argv: [script, *argv]) + end + + private + def find_runfiles + stub_filename = File.absolute_path($0) + runfiles = "#{stub_filename}.runfiles" + loop do + case + when File.directory?(runfiles) + return runfiles + when %r!(.*\.runfiles)/.*!o =~ stub_filename + return $1 + when File.symlink?(stub_filename) + target = File.readlink(stub_filename) + stub_filename = File.absolute_path(target, File.dirname(stub_filename)) + else + break + end + end + raise "Cannot find .runfiles directory for #{$0}" + end + + def create_loadpath_entries(custom, runfiles) + [runfiles] + custom.map {|path| File.join(runfiles, path) } + end + + def get_repository_imports(runfiles) + Dir.children(runfiles).map {|d| + File.join(runfiles, d) + }.select {|d| + File.directory? d + } + end + + # Finds the runfiles manifest or the runfiles directory. + def runfiles_envvar(runfiles) + # If this binary is the data-dependency of another one, the other sets + # RUNFILES_MANIFEST_FILE or RUNFILES_DIR for our sake. + manifest = ENV['RUNFILES_MANIFEST_FILE'] + if manifest + return ['RUNFILES_MANIFEST_FILE', manifest] + end + + dir = ENV['RUNFILES_DIR'] + if dir + return ['RUNFILES_DIR', dir] + end + + # Look for the runfiles "output" manifest, argv[0] + ".runfiles_manifest" + manifest = runfiles + '_manifest' + if File.exists?(manifest) + return ['RUNFILES_MANIFEST_FILE', manifest] + end + + # Look for the runfiles "input" manifest, argv[0] + ".runfiles/MANIFEST" + manifest = File.join(runfiles, 'MANIFEST') + if File.exists?(manifest) + return ['RUNFILES_DIR', manifest] + end + + # If running in a sandbox and no environment variables are set, then + # Look for the runfiles next to the binary. + if runfiles.end_with?('.runfiles') and File.directory?(runfiles) + return ['RUNFILES_DIR', runfiles] + end + end + + 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 +end From e150e795eeba1d42e23fa44c42e27eedc9563920 Mon Sep 17 00:00:00 2001 From: Yuki Yugui Sonoda Date: Sun, 15 Dec 2019 20:32:44 +0900 Subject: [PATCH 3/3] Revert "temp" This reverts commit 16d66e4c5da11189f1d8b9b11cd70d69565c76db. --- ruby/private/binary_wrapper.tpl | 113 +++++++++++++++++++++++++- ruby/private/tools/runfiles.rb | 136 -------------------------------- 2 files changed, 110 insertions(+), 139 deletions(-) delete mode 100644 ruby/private/tools/runfiles.rb diff --git a/ruby/private/binary_wrapper.tpl b/ruby/private/binary_wrapper.tpl index bc7eecd7..8df515e0 100644 --- a/ruby/private/binary_wrapper.tpl +++ b/ruby/private/binary_wrapper.tpl @@ -23,12 +23,119 @@ # limitations under the License. # +require 'rbconfig' +require 'shellwords' + +def find_runfiles + stub_filename = File.absolute_path($0) + runfiles = "#{stub_filename}.runfiles" + loop do + case + when File.directory?(runfiles) + return runfiles + when %r!(.*\.runfiles)/.*!o =~ stub_filename + return $1 + when File.symlink?(stub_filename) + target = File.readlink(stub_filename) + stub_filename = File.absolute_path(target, File.dirname(stub_filename)) + else + break + end + end + raise "Cannot find .runfiles directory for #{$0}" +end + +def create_loadpath_entries(custom, runfiles) + [runfiles] + custom.map {|path| File.join(runfiles, path) } +end + +def get_repository_imports(runfiles) + Dir.children(runfiles).map {|d| + File.join(runfiles, d) + }.select {|d| + File.directory? d + } +end + +# Finds the runfiles manifest or the runfiles directory. +def runfiles_envvar(runfiles) + # If this binary is the data-dependency of another one, the other sets + # RUNFILES_MANIFEST_FILE or RUNFILES_DIR for our sake. + manifest = ENV['RUNFILES_MANIFEST_FILE'] + if manifest + return ['RUNFILES_MANIFEST_FILE', manifest] + end + + dir = ENV['RUNFILES_DIR'] + if dir + return ['RUNFILES_DIR', dir] + end + + # Look for the runfiles "output" manifest, argv[0] + ".runfiles_manifest" + manifest = runfiles + '_manifest' + if File.exists?(manifest) + return ['RUNFILES_MANIFEST_FILE', manifest] + end + + # Look for the runfiles "input" manifest, argv[0] + ".runfiles/MANIFEST" + manifest = File.join(runfiles, 'MANIFEST') + if File.exists?(manifest) + return ['RUNFILES_DIR', manifest] + end + + # If running in a sandbox and no environment variables are set, then + # Look for the runfiles next to the binary. + if runfiles.end_with?('.runfiles') and File.directory?(runfiles) + return ['RUNFILES_DIR', runfiles] + end +end + +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} - rubyopt = {rubyopt} + runfiles = find_runfiles + + loadpaths = create_loadpath_entries(custom_loadpaths, runfiles) + loadpaths += get_repository_imports(runfiles) + loadpaths += ENV['RUBYLIB'].split(':') if ENV.key?('RUBYLIB') + ENV['RUBYLIB'] = loadpaths.join(':') + + runfiles_envkey, runfiles_envvalue = runfiles_envvar(runfiles) + ENV[runfiles_envkey] = runfiles_envvalue if runfiles_envkey + + 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 = expand_vars({rubyopt}) + ENV['RUBYOPT'] = Shellwords.join(expand_vars({rubyopt})) - Runfiles.new(custom_loadpaths, rubyopt).exec(main, *args) + exec(program, *program_opts, main, *args) # TODO(yugui) Support windows end @@ -52,4 +159,4 @@ end #shell { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e #shell # --- end runfiles.bash initialization v2 --- #shell -#shell exec "$(rlocation {interpreter})" -r"$(rlocation @bazelruby_ruby_rules//ruby/private/tools:runfiles.rb)" ${BASH_SOURCE:-$0} "$@" +#shell exec "$(rlocation {interpreter})" ${BASH_SOURCE:-$0} "$@" diff --git a/ruby/private/tools/runfiles.rb b/ruby/private/tools/runfiles.rb deleted file mode 100644 index 01e2da2c..00000000 --- a/ruby/private/tools/runfiles.rb +++ /dev/null @@ -1,136 +0,0 @@ -require 'rbconfig' -require 'shellwords' - -# Based on the Bazel's binary wrapper script for Python - -# Copyright 2017 The Bazel Authors. All rights reserved. -# Copyright 2019 BazelRuby Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -require 'rbconfig' -require 'shellwords' - -class Runfiles - def initialize(load_paths, rubyopt) - @runfiles = find_runfiles - @rubyopt = rubyopt - - loadpaths = create_loadpath_entries(load_paths, @runfiles) - loadpaths += get_repository_imports(@runfiles) - loadpaths += ENV['RUBYLIB'].split(':') if ENV.key?('RUBYLIB') - @loadpaths = loadpaths - end - - def exec(program, program_opts:, argv:) - runfiles_envkey, runfiles_envvalue = runfiles_envvar(runfiles) - ENV[runfiles_envkey] = runfiles_envvalue if runfiles_envkey - ENV['RUBYOPT'] = Shellwords.join(expand_vars(@rubyopt)) - ENV['RUBYLIB'] = @loadpaths.join(':') - - program_opts = expand_vars(program_opts || []) - exec(program, *program_opts, *argv) - end - - def exec_script(script, *argv) - ruby = find_ruby_program - script = File.join(@runfiles, script) - exec(ruby, argv: [script, *argv]) - end - - private - def find_runfiles - stub_filename = File.absolute_path($0) - runfiles = "#{stub_filename}.runfiles" - loop do - case - when File.directory?(runfiles) - return runfiles - when %r!(.*\.runfiles)/.*!o =~ stub_filename - return $1 - when File.symlink?(stub_filename) - target = File.readlink(stub_filename) - stub_filename = File.absolute_path(target, File.dirname(stub_filename)) - else - break - end - end - raise "Cannot find .runfiles directory for #{$0}" - end - - def create_loadpath_entries(custom, runfiles) - [runfiles] + custom.map {|path| File.join(runfiles, path) } - end - - def get_repository_imports(runfiles) - Dir.children(runfiles).map {|d| - File.join(runfiles, d) - }.select {|d| - File.directory? d - } - end - - # Finds the runfiles manifest or the runfiles directory. - def runfiles_envvar(runfiles) - # If this binary is the data-dependency of another one, the other sets - # RUNFILES_MANIFEST_FILE or RUNFILES_DIR for our sake. - manifest = ENV['RUNFILES_MANIFEST_FILE'] - if manifest - return ['RUNFILES_MANIFEST_FILE', manifest] - end - - dir = ENV['RUNFILES_DIR'] - if dir - return ['RUNFILES_DIR', dir] - end - - # Look for the runfiles "output" manifest, argv[0] + ".runfiles_manifest" - manifest = runfiles + '_manifest' - if File.exists?(manifest) - return ['RUNFILES_MANIFEST_FILE', manifest] - end - - # Look for the runfiles "input" manifest, argv[0] + ".runfiles/MANIFEST" - manifest = File.join(runfiles, 'MANIFEST') - if File.exists?(manifest) - return ['RUNFILES_DIR', manifest] - end - - # If running in a sandbox and no environment variables are set, then - # Look for the runfiles next to the binary. - if runfiles.end_with?('.runfiles') and File.directory?(runfiles) - return ['RUNFILES_DIR', runfiles] - end - end - - 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 -end