Skip to content

Commit 287cdef

Browse files
author
Graham Jenson
authored
Merge pull request #17 from bazelruby/refactor/runtime-compat
Make ruby_binary compatible with container
2 parents a210f9d + 04eeb22 commit 287cdef

File tree

15 files changed

+363
-116
lines changed

15 files changed

+363
-116
lines changed

.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ before_install:
3434
- bundle install
3535
install:
3636
- bazel $BAZEL_OPTS build $BAZEL_BUILD_OPTS --show_progress_rate_limit 0 -- //...
37-
- (cd examples && bazel $BAZEL_OPTS build $BAZEL_BUILD_OPTS --show_progress_rate_limit 0 -- //...)
37+
- (cd examples/simple_script && bazel $BAZEL_OPTS build $BAZEL_BUILD_OPTS --show_progress_rate_limit 0 -- //...)
3838
script:
3939
- bazel $BAZEL_OPTS test $BAZEL_BUILD_OPTS --show_progress_rate_limit 0 --test_output=streamed -- //...
40-
- (cd examples && bazel $BAZEL_OPTS test $BAZEL_BUILD_OPTS --show_progress_rate_limit 0 --test_output=streamed -- //...)
40+
- (cd examples/simple_script && bazel $BAZEL_OPTS test $BAZEL_BUILD_OPTS --show_progress_rate_limit 0 --test_output=streamed -- //...)
4141
# If this fails run `bazel run :buildifier`
4242
- bazel run :buildifier-check
4343
# If this fails run `bundle exec rubocop -a`
@@ -47,4 +47,4 @@ env:
4747
global:
4848
- PATH=$PATH:$HOME/local/bin
4949
- BAZEL_OPTS="--host_jvm_args=-Xmx500m --host_jvm_args=-Xms500m"
50-
- BAZEL_BUILD_OPTS="--curses=no --genrule_strategy=standalone --spawn_strategy=standalone --verbose_failures -j 20"
50+
- BAZEL_BUILD_OPTS="--curses=no --verbose_failures -j 20"

WORKSPACE

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,35 @@ gazelle_dependencies()
5454
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
5555

5656
protobuf_deps()
57+
58+
# rules_docker
59+
60+
http_archive(
61+
name = "io_bazel_rules_docker",
62+
sha256 = "14ac30773fdb393ddec90e158c9ec7ebb3f8a4fd533ec2abbfd8789ad81a284b",
63+
strip_prefix = "rules_docker-0.12.1",
64+
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.12.1/rules_docker-v0.12.1.tar.gz"],
65+
)
66+
67+
load(
68+
"@io_bazel_rules_docker//repositories:repositories.bzl",
69+
container_repositories = "repositories",
70+
)
71+
72+
container_repositories()
73+
74+
load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")
75+
76+
container_deps()
77+
78+
load(
79+
"@io_bazel_rules_docker//container:container.bzl",
80+
"container_pull",
81+
)
82+
83+
container_pull(
84+
name = "ruby_base_container",
85+
digest = "sha256:da560e130d6a4b75b099e932a98331ec3b2420b914d51a88edc4fe3c60aee9b1", # alpine linux/amd64
86+
registry = "docker.io",
87+
repository = "library/ruby",
88+
)

examples/simple_script/.rspec

Lines changed: 0 additions & 1 deletion
This file was deleted.

examples/simple_script/BUILD

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ ruby_binary(
1717
)
1818

1919
ruby_test(
20-
name = "default_test",
21-
srcs = ["script_spec.rb"],
22-
main = "script_spec.rb",
20+
name = "script_spec",
21+
srcs = [
22+
"script.rb",
23+
"spec/script_spec.rb",
24+
],
25+
main = "spec/script_spec.rb",
2326
rubyopt = ["-rrspec/autorun"], # require autorun because it is needed
2427
deps = [
2528
"//lib:foo",

examples/simple_script/script_spec.rb renamed to examples/simple_script/spec/script_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232

3333
require_relative '../script'
3434

35-
describe OSSRand do
36-
it begin
37-
expect(oss_rand).to be String
35+
describe 'oss_rand' do
36+
it 'generates a String' do
37+
expect(oss_rand).to be_a_kind_of String
3838
end
3939
end

ruby/private/BUILD.host_runtime.tpl

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ ruby_toolchain(
1010
name = "ruby_host",
1111
interpreter = "//:ruby_bin",
1212
bundler = "//:bundler",
13-
init_files = ["//:init_loadpath"],
1413
rubyopt = [
15-
"-I../org_ruby_lang_ruby_host/bundler/lib",
14+
"-I$(RUNFILES_DIR)/org_ruby_lang_ruby_host/bundler/lib",
1615
],
1716
runtime = "//:runtime",
17+
is_host = True,
1818
rules_ruby_workspace = "{rules_ruby_workspace}",
1919
# TODO(yugui) Extract platform info from RbConfig
2020
# exec_compatible_with = [],
@@ -27,12 +27,6 @@ sh_binary(
2727
data = [":runtime"],
2828
)
2929

30-
filegroup(
31-
name = "init_loadpath",
32-
srcs = ["init_loadpath.rb"],
33-
data = ["loadpath.lst"],
34-
)
35-
3630
cc_import(
3731
name = "libruby",
3832
hdrs = glob({hdrs}),
@@ -57,8 +51,6 @@ filegroup(
5751
srcs = glob(
5852
include = ["**/*"],
5953
exclude = [
60-
"init_loadpath.rb",
61-
"loadpath.lst",
6254
"BUILD.bazel",
6355
"WORKSPACE",
6456
],

ruby/private/binary.bzl

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ load(
55
_transitive_deps = "transitive_deps",
66
)
77

8+
def _to_manifest_path(ctx, file):
9+
if file.short_path.startswith("../"):
10+
return file.short_path[3:]
11+
else:
12+
return ("%s/%s" % (ctx.workspace_name, file.short_path))
13+
814
def _ruby_binary_impl(ctx):
915
sdk = ctx.toolchains[TOOLCHAIN_TYPE_NAME].ruby_runtime
1016
interpreter = sdk.interpreter[DefaultInfo].files_to_run.executable
11-
init_files = [f for t in sdk.init_files for f in t.files.to_list()]
12-
init_flags = " ".join(["-r${PATH_PREFIX}%s" % f.short_path for f in init_files])
1317

1418
main = ctx.file.main
1519
if not main:
@@ -20,30 +24,35 @@ def _ruby_binary_impl(ctx):
2024
break
2125
if not main:
2226
fail(
23-
("main must be present unless the name of the rule matches to one " +
24-
"of the srcs"),
27+
("main must be present unless the name of the rule matches to " +
28+
"one of the srcs"),
2529
"main",
2630
)
2731

32+
if sdk.is_host:
33+
interpreter_file_deps = []
34+
interpreter_trans_deps = []
35+
else:
36+
interpreter_file_deps = [interpreter]
37+
interpreter_trans_deps = [sdk.interpreter]
38+
2839
executable = ctx.actions.declare_file(ctx.attr.name)
2940
deps = _transitive_deps(
3041
ctx,
31-
extra_files = init_files + [interpreter, executable],
32-
extra_deps = sdk.init_files + [sdk.interpreter],
42+
extra_files = interpreter_file_deps + [executable],
43+
extra_deps = interpreter_trans_deps,
3344
)
3445

3546
rubyopt = reversed(deps.rubyopt.to_list())
36-
rubyopt += ["-I${PATH_PREFIX}%s" % inc for inc in deps.incpaths.to_list()]
3747

3848
ctx.actions.expand_template(
3949
template = ctx.file._wrapper_template,
4050
output = executable,
4151
substitutions = {
4252
"{interpreter}": interpreter.short_path,
43-
"{init_flags}": init_flags,
44-
"{rubyopt}": " ".join(rubyopt),
45-
"{main}": main.short_path,
46-
"{workspace_name}": ctx.label.workspace_name or ctx.workspace_name,
53+
"{loadpaths}": repr(deps.incpaths.to_list()),
54+
"{rubyopt}": repr(rubyopt),
55+
"{main}": repr(_to_manifest_path(ctx, main)),
4756
},
4857
is_executable = True,
4958
)

ruby/private/binary_wrapper.tpl

Lines changed: 126 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,126 @@
1-
#!/bin/sh
2-
3-
if [ -n "${RUNFILES_DIR+x}" ]; then
4-
PATH_PREFIX=$RUNFILES_DIR/{workspace_name}/
5-
elif [ -s `dirname $0`/../../MANIFEST ]; then
6-
PATH_PREFIX=`cd $(dirname $0); pwd`/
7-
elif [ -d $0.runfiles ]; then
8-
PATH_PREFIX=`cd $0.runfiles; pwd`/{workspace_name}/
9-
else
10-
echo "WARNING: it does not look to be at the .runfiles directory" >&2
11-
exit 1
12-
fi
13-
14-
$PATH_PREFIX{interpreter} --disable-gems {init_flags} {rubyopt} -I${PATH_PREFIX} {main} "$@"
1+
#!/usr/bin/env ruby
2+
3+
# Ruby-port of the Bazel's wrapper script for Python
4+
5+
# Copyright 2017 The Bazel Authors. All rights reserved.
6+
# Copyright 2019 BazelRuby Authors. All rights reserved.
7+
#
8+
# Licensed under the Apache License, Version 2.0 (the "License");
9+
# you may not use this file except in compliance with the License.
10+
# You may obtain a copy of the License at
11+
#
12+
# http://www.apache.org/licenses/LICENSE-2.0
13+
#
14+
# Unless required by applicable law or agreed to in writing, software
15+
# distributed under the License is distributed on an "AS IS" BASIS,
16+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
# See the License for the specific language governing permissions and
18+
# limitations under the License.
19+
#
20+
21+
require 'rbconfig'
22+
23+
def find_runfiles
24+
stub_filename = File.absolute_path($0)
25+
runfiles = "#{stub_filename}.runfiles"
26+
loop do
27+
case
28+
when File.directory?(runfiles)
29+
return runfiles
30+
when %r!(.*\.runfiles)/.*!o =~ stub_filename
31+
return $1
32+
when File.symlink?(stub_filename)
33+
target = File.readlink(stub_filename)
34+
stub_filename = File.absolute_path(target, File.dirname(stub_filename))
35+
else
36+
break
37+
end
38+
end
39+
raise "Cannot find .runfiles directory for #{$0}"
40+
end
41+
42+
def create_loadpath_entries(custom, runfiles)
43+
[runfiles] + custom.map {|path| File.join(runfiles, path) }
44+
end
45+
46+
def get_repository_imports(runfiles)
47+
Dir.children(runfiles).map {|d|
48+
File.join(runfiles, d)
49+
}.select {|d|
50+
File.directory? d
51+
}
52+
end
53+
54+
# Finds the runfiles manifest or the runfiles directory.
55+
def runfiles_envvar(runfiles)
56+
# If this binary is the data-dependency of another one, the other sets
57+
# RUNFILES_MANIFEST_FILE or RUNFILES_DIR for our sake.
58+
manifest = ENV['RUNFILES_MANIFEST_FILE']
59+
if manifest
60+
return ['RUNFILES_MANIFEST_FILE', manifest]
61+
end
62+
63+
dir = ENV['RUNFILES_DIR']
64+
if dir
65+
return ['RUNFILES_DIR', dir]
66+
end
67+
68+
# Look for the runfiles "output" manifest, argv[0] + ".runfiles_manifest"
69+
manifest = runfiles + '_manifest'
70+
if File.exists?(manifest)
71+
return ['RUNFILES_MANIFEST_FILE', manifest]
72+
end
73+
74+
# Look for the runfiles "input" manifest, argv[0] + ".runfiles/MANIFEST"
75+
manifest = File.join(runfiles, 'MANIFEST')
76+
if File.exists?(manifest)
77+
return ['RUNFILES_DIR', manifest]
78+
end
79+
80+
# If running in a sandbox and no environment variables are set, then
81+
# Look for the runfiles next to the binary.
82+
if runfiles.end_with?('.runfiles') and File.directory?(runfiles)
83+
return ['RUNFILES_DIR', runfiles]
84+
end
85+
end
86+
87+
def find_ruby_binary
88+
File.join(
89+
RbConfig::CONFIG['bindir'],
90+
RbConfig::CONFIG['ruby_install_name'],
91+
)
92+
end
93+
94+
def main(args)
95+
custom_loadpaths = {loadpaths}
96+
runfiles = find_runfiles
97+
98+
loadpaths = create_loadpath_entries(custom_loadpaths, runfiles)
99+
loadpaths += get_repository_imports(runfiles)
100+
loadpaths += ENV['RUBYLIB'].split(':') if ENV.key?('RUBYLIB')
101+
ENV['RUBYLIB'] = loadpaths.join(':')
102+
103+
runfiles_envkey, runfiles_envvalue = runfiles_envvar(runfiles)
104+
ENV[runfiles_envkey] = runfiles_envvalue if runfiles_envkey
105+
106+
ruby_program = find_ruby_binary
107+
108+
main = {main}
109+
main = File.join(runfiles, main)
110+
rubyopt = {rubyopt}.map do |opt|
111+
opt.gsub(/\${(.+?)}/o) do
112+
case $1
113+
when 'RUNFILES_DIR'
114+
runfiles
115+
else
116+
ENV[$1]
117+
end
118+
end
119+
end
120+
exec(ruby_program, '--disable-gems', *rubyopt, main, *args)
121+
# TODO(yugui) Support windows
122+
end
123+
124+
if __FILE__ == $0
125+
main(ARGV)
126+
end

ruby/private/bundle/create_bundle_build_file.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
exclude = {exclude},
3131
),
3232
deps = [":bundler_setup"],
33-
rubyopt = ["-r../{repo_name}/lib/bundler/setup.rb"],
33+
rubyopt = ["-r${RUNFILES_DIR}/{repo_name}/lib/bundler/setup.rb"],
3434
)
3535
3636
# PULL EACH GEM INDIVIDUALLY
@@ -48,7 +48,7 @@
4848
exclude = {exclude},
4949
),
5050
deps = {deps},
51-
rubyopt = ["-r../{repo_name}/lib/bundler/setup.rb"],
51+
rubyopt = ["-r${RUNFILES_DIR}/{repo_name}/lib/bundler/setup.rb"],
5252
)
5353
5454
'
@@ -57,7 +57,7 @@
5757
ruby_library(
5858
name = "all",
5959
deps = {deps},
60-
rubyopt = ["-r../{repo_name}/lib/bundler/setup.rb"],
60+
rubyopt = ["-r${RUNFILES_DIR}/{repo_name}/lib/bundler/setup.rb"],
6161
)
6262
'
6363
require "bundler"

0 commit comments

Comments
 (0)