diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 00000000..2333bc3f --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,25 @@ +name: Tests + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test-suite: + name: "Test Suite" + + runs-on: ubuntu-latest + + strategy: + fail-fast: false # Don't cancel all jobs if one fails. + + steps: + - uses: actions/checkout@v3 + - name: Run Setup + run: cd ${{ github.workspace }} && bin/setup + - name: Run Bazel Tests + run: cd ${{ github.workspace }} && bin/test-suite diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..f7f24c15 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,33 @@ +# How to Contribute + +This repository is currently a WIP, forked from +[rules_ruby](https://github.com/bazelruby/rules_ruby) for use in building and +testing Ruby [Protobuf](https://github.com/protocolbuffers/protobuf). + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement (CLA). You (or your employer) retain the copyright to your +contribution; this simply gives us permission to use and redistribute your +contributions as part of the project. Head over to + to see your current agreements on file or +to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code Reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. + +## Community Guidelines + +This project follows +[Google's Open Source Community Guidelines](https://opensource.google/conduct/). diff --git a/Gemfile.lock b/Gemfile.lock index 92438240..a5bc485b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,7 +7,8 @@ GEM ast (~> 2.4.1) rainbow (3.0.0) regexp_parser (2.1.1) - rexml (3.2.5) + rexml (3.3.6) + strscan rubocop (0.93.1) parallel (~> 1.10) parser (>= 2.7.1.5) @@ -20,6 +21,7 @@ GEM rubocop-ast (1.11.0) parser (>= 3.0.1.1) ruby-progressbar (1.11.0) + strscan (3.1.0) unicode-display_width (1.8.0) PLATFORMS diff --git a/README.adoc b/README.adoc index 758e9bb0..1db3c555 100644 --- a/README.adoc +++ b/README.adoc @@ -92,17 +92,12 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") #——————————————————————————————————————————————————————————————————————— git_repository( - name = "bazelruby_rules_ruby", + name = "rules_ruby", remote = "https://github.com/bazelruby/rules_ruby.git", branch = "master" ) -load( - "@bazelruby_rules_ruby//ruby:deps.bzl", - "rules_ruby_dependencies", - "rules_ruby_select_sdk", -) - +load("@rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies") rules_ruby_dependencies() #——————————————————————————————————————————————————————————————————————— @@ -113,16 +108,14 @@ rules_ruby_dependencies() load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() -rules_ruby_select_sdk(version = "3.0.2") +load("@rules_ruby//ruby:deps.bzl", "register_toolchain") +register_toolchains("ruby-3.0") #——————————————————————————————————————————————————————————————————————— # Now, load the ruby_bundle rule & install gems specified in the Gemfile #——————————————————————————————————————————————————————————————————————— -load( - "@bazelruby_rules_ruby//ruby:defs.bzl", - "ruby_bundle", -) +load("@ruby-3.0//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "bundle", @@ -170,7 +163,7 @@ Add `ruby_library`, `ruby_binary`, `ruby_rspec` or `ruby_test` into your `BUILD. #——————————————————————————————————————————————————————————————————————— load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_binary", "ruby_library", "ruby_test", @@ -215,7 +208,7 @@ Use `ruby_gem` rule to package any number of ruby files or folders into a Ruby-G [source,python] ---- load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_gem", ) @@ -486,8 +479,7 @@ ruby_bundle( excludes = {}, srcs = [], vendor_cache = False, - ruby_sdk = "@org_ruby_lang_ruby_toolchain", - ruby_interpreter = "@org_ruby_lang_ruby_toolchain//:ruby", + ruby_interpreter = "@rules_ruby//ruby/runtime:interpreter", ) ---- @@ -555,7 +547,7 @@ List of glob patterns per gem to be excluded from the library. Keys are the name [source,python] ---- -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +load("@ruby-3.0//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "gems", @@ -572,7 +564,7 @@ your workspace. The name should match the name of the bundle. [source,python] ---- -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +load("@ruby-3.0//:bundle.bzl", "ruby_bundle") workspace( name = "my_wksp", diff --git a/WORKSPACE b/WORKSPACE index e08c5ee3..6a1b9517 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,6 +1,6 @@ -workspace(name = "bazelruby_rules_ruby") +workspace(name = "rules_ruby") -load("@//ruby:deps.bzl", "rules_ruby_dependencies", "rules_ruby_select_sdk") +load("@//ruby:deps.bzl", "rules_ruby_dependencies") rules_ruby_dependencies() @@ -12,15 +12,36 @@ load("@bazel_skylib//lib:versions.bzl", "versions") versions.check("3.4.1") -rules_ruby_select_sdk("3.0.2") +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") + +# Register the system ruby version with a custom name. +ruby_runtime( + name = "system_ruby_custom", + version = "system", +) + +register_toolchains("@system_ruby_custom//:toolchain") + +# Register a versioned ruby with a custom name. +ruby_runtime( + name = "ruby3", + version = "ruby-3.0", +) + +register_toolchains("@ruby3//:toolchain") + +# Register a versioned ruby with its default name. +ruby_runtime("jruby-9.4") + +register_toolchains("@jruby-9.4//:toolchain") local_repository( - name = "bazelruby_rules_ruby_ruby_tests_testdata_another_workspace", + name = "rules_ruby_ruby_tests_testdata_another_workspace", path = "ruby/tests/testdata/another_workspace", ) local_repository( - name = "bazelruby_rules_ruby_ruby_tests_testdata_bundle_includes_workspace", + name = "rules_ruby_ruby_tests_testdata_bundle_includes_workspace", path = "ruby/tests/testdata/bundle_includes_workspace", ) @@ -95,11 +116,11 @@ container_pull( repository = "library/ruby", ) -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +load("@system_ruby_custom//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "bundle", - bundler_version = "2.1.4", + bundler_version = "2.4.22", excludes = { "mini_portile": ["test/**/*"], }, diff --git a/bin/deps b/bin/deps index dfdbbccd..00ffdd40 100755 --- a/bin/deps +++ b/bin/deps @@ -10,8 +10,9 @@ # ————————————————————————————————————————————————————————————————————————————————————— +export BASHMATIC_OS="$(uname -s | tr '[:upper:]' '[:lower:]')" [[ -z ${BASHMATIC_HOME} ]] && export BASHMATIC_HOME="${HOME}/.bashmatic" -[[ -d ${BASHMATIC_HOME} ]] || bash -c "$(curl -fsSL https://bashmatic.re1.re); bashmatic-install -q" +[[ -d ${BASHMATIC_HOME} ]] || bash -c "$(curl -fsSL https://raw.githubusercontent.com/kigster/bashmatic/master/bin/bashmatic-install); bashmatic-install -v -f -b v2.7.2" # shellcheck disable=SC1090 source "${BASHMATIC_HOME}/init.sh" 1>/dev/null 2>&1 diff --git a/bin/setup b/bin/setup index c0799cad..8875e278 100755 --- a/bin/setup +++ b/bin/setup @@ -37,7 +37,7 @@ setup.rbenv() { local installed_version="$(ruby -e 'puts RUBY_VERSION' | tr -d '\n')" if [[ ${installed_version} == ${ruby_version} ]]; then info "RUBY already installed, current version: ${bldylw}${ruby_version}" - return 0 + info "Setting up rbenv anyway" fi fi diff --git a/bin/test-suite b/bin/test-suite index 63643f16..bb435415 100755 --- a/bin/test-suite +++ b/bin/test-suite @@ -32,11 +32,6 @@ export BashMatic__Expr=" [[ -f ${HOME}/.bashmatic/init.sh ]] && source ${HOME}/.bashmatic/init.sh; set -e " -export Bazel__BuildSteps=" - bazel ${BAZEL_OPTS} info; echo; echo - bazel ${BAZEL_OPTS} build ${BAZEL_BUILD_OPTS} -- //... ; echo; echo - bazel ${BAZEL_OPTS} test ${BAZEL_BUILD_OPTS} ${BAZEL_TEST_OPTS} -- //... ; echo; echo -" deps.start-clock run.set-all abort-on-error show-output-on @@ -160,11 +155,15 @@ test.buildifier() { # Builds and runs workspace inside examples/simple_script test.simple-script() { + # This workspace requires a version specification + local RUBY_VERSION="--@rules_ruby//ruby/runtime:version=ruby-3.0 " __test.exec simple-script " cd examples/simple_script - ${Bazel__BuildSteps} - echo run :bin; bazel ${BAZEL_OPTS} run ${BAZEL_BUILD_OPTS} :bin - echo run :rubocop; bazel ${BAZEL_OPTS} run ${BAZEL_BUILD_OPTS} :rubocop + bazel ${BAZEL_OPTS} info; echo; echo + bazel ${BAZEL_OPTS} build ${BAZEL_BASE_BUILD_OPTS} ${RUBY_VERSION} -- //... ; echo; echo + bazel ${BAZEL_OPTS} test ${BAZEL_BASE_BUILD_OPTS} ${BAZEL_TEST_OPTS} ${RUBY_VERSION} -- //... ; echo; echo + echo run :bin; bazel ${BAZEL_OPTS} run ${BAZEL_BASE_BUILD_OPTS} ${RUBY_VERSION} :bin + echo run :rubocop; bazel ${BAZEL_OPTS} run ${BAZEL_BASE_BUILD_OPTS} ${RUBY_VERSION} :rubocop " } @@ -172,12 +171,21 @@ test.simple-script() { test.example-gem() { __test.exec example-gem " cd examples/example_gem - echo bazel ${BAZEL_OPTS} build ...:all; bazel ${BAZEL_OPTS} build ...:all + echo bazel ${BAZEL_OPTS} build ...:all + bazel ${BAZEL_OPTS} build --@rules_ruby//ruby/runtime:version=ruby-3.0 ...:all " } test.workspace() { - __test.exec workspace "${Bazel__BuildSteps}" + __test.exec workspace " + bazel ${BAZEL_OPTS} info; echo; echo + bazel ${BAZEL_OPTS} build ${BAZEL_BUILD_OPTS} -- //... ; echo; echo + bazel ${BAZEL_OPTS} test ${BAZEL_BUILD_OPTS} ${BAZEL_TEST_OPTS} -- //... ; echo; echo + bazel ${BAZEL_OPTS} build ${BAZEL_BUILD_OPTS} --@rules_ruby//ruby/runtime:version=ruby-3.0 -- //... ; echo; echo + bazel ${BAZEL_OPTS} test ${BAZEL_BUILD_OPTS} --@rules_ruby//ruby/runtime:version=ruby-3.0 ${BAZEL_TEST_OPTS} -- //... ; echo; echo + bazel ${BAZEL_OPTS} build ${BAZEL_BUILD_OPTS} --@rules_ruby//ruby/runtime:version=jruby-9.4 -- //... ; echo; echo + bazel ${BAZEL_OPTS} test ${BAZEL_BUILD_OPTS} --@rules_ruby//ruby/runtime:version=jruby-9.4 ${BAZEL_TEST_OPTS} -- //... ; echo; echo + " } # Private diff --git a/examples/example_gem/BUILD.bazel b/examples/example_gem/BUILD.bazel index 55948ee0..9b7baf6c 100644 --- a/examples/example_gem/BUILD.bazel +++ b/examples/example_gem/BUILD.bazel @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_gem", ) diff --git a/examples/example_gem/WORKSPACE b/examples/example_gem/WORKSPACE index 0f096a77..150de3b2 100644 --- a/examples/example_gem/WORKSPACE +++ b/examples/example_gem/WORKSPACE @@ -1,21 +1,21 @@ -workspace(name = "bazelruby_rules_ruby_example_gem") +workspace(name = "rules_ruby_example_gem") # Importing rules_ruby from the parent directory for developing # rules_ruby itself... local_repository( - name = "bazelruby_rules_ruby", + name = "rules_ruby", path = "../..", ) -load( - "@bazelruby_rules_ruby//ruby:deps.bzl", - "rules_ruby_dependencies", - "rules_ruby_select_sdk", -) +load("@rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies") rules_ruby_dependencies() -rules_ruby_select_sdk("3.0.2") +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") + +ruby_runtime("ruby-3.0") + +register_toolchains("@ruby-3.0//:toolchain") load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") diff --git a/examples/example_gem/lib/BUILD b/examples/example_gem/lib/BUILD index 32394529..360c4c24 100644 --- a/examples/example_gem/lib/BUILD +++ b/examples/example_gem/lib/BUILD @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_library", ) diff --git a/examples/example_gem/lib/foo/BUILD b/examples/example_gem/lib/foo/BUILD index 9e6e2fe3..65ad9e78 100644 --- a/examples/example_gem/lib/foo/BUILD +++ b/examples/example_gem/lib/foo/BUILD @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_library", ) diff --git a/examples/simple_rails_api/BUILD b/examples/simple_rails_api/BUILD index c53e54b5..84815920 100644 --- a/examples/simple_rails_api/BUILD +++ b/examples/simple_rails_api/BUILD @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_binary", ) diff --git a/examples/simple_rails_api/Gemfile b/examples/simple_rails_api/Gemfile index 3fab5dae..385b769d 100644 --- a/examples/simple_rails_api/Gemfile +++ b/examples/simple_rails_api/Gemfile @@ -2,11 +2,11 @@ source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 6.0.2' +gem 'rails', '~> 6.1.7' # Use sqlite3 as the database for Active Record gem 'sqlite3', '~> 1.4' # Use Puma as the app server -gem 'puma', '~> 4.3' +gem 'puma', '~> 5.6' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder # gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production diff --git a/examples/simple_rails_api/Gemfile.lock b/examples/simple_rails_api/Gemfile.lock index 9da3cb42..4e78dc36 100644 --- a/examples/simple_rails_api/Gemfile.lock +++ b/examples/simple_rails_api/Gemfile.lock @@ -1,124 +1,143 @@ GEM remote: https://rubygems.org/ specs: - actioncable (6.0.4.1) - actionpack (= 6.0.4.1) + actioncable (6.1.7.8) + actionpack (= 6.1.7.8) + activesupport (= 6.1.7.8) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.1) - actionpack (= 6.0.4.1) - activejob (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) + actionmailbox (6.1.7.8) + actionpack (= 6.1.7.8) + activejob (= 6.1.7.8) + activerecord (= 6.1.7.8) + activestorage (= 6.1.7.8) + activesupport (= 6.1.7.8) mail (>= 2.7.1) - actionmailer (6.0.4.1) - actionpack (= 6.0.4.1) - actionview (= 6.0.4.1) - activejob (= 6.0.4.1) + actionmailer (6.1.7.8) + actionpack (= 6.1.7.8) + actionview (= 6.1.7.8) + activejob (= 6.1.7.8) + activesupport (= 6.1.7.8) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.4.1) - actionview (= 6.0.4.1) - activesupport (= 6.0.4.1) - rack (~> 2.0, >= 2.0.8) + actionpack (6.1.7.8) + actionview (= 6.1.7.8) + activesupport (= 6.1.7.8) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.1) - actionpack (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) + actiontext (6.1.7.8) + actionpack (= 6.1.7.8) + activerecord (= 6.1.7.8) + activestorage (= 6.1.7.8) + activesupport (= 6.1.7.8) nokogiri (>= 1.8.5) - actionview (6.0.4.1) - activesupport (= 6.0.4.1) + actionview (6.1.7.8) + activesupport (= 6.1.7.8) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.1) - activesupport (= 6.0.4.1) + activejob (6.1.7.8) + activesupport (= 6.1.7.8) globalid (>= 0.3.6) - activemodel (6.0.4.1) - activesupport (= 6.0.4.1) - activerecord (6.0.4.1) - activemodel (= 6.0.4.1) - activesupport (= 6.0.4.1) - activestorage (6.0.4.1) - actionpack (= 6.0.4.1) - activejob (= 6.0.4.1) - activerecord (= 6.0.4.1) - marcel (~> 1.0.0) - activesupport (6.0.4.1) + activemodel (6.1.7.8) + activesupport (= 6.1.7.8) + activerecord (6.1.7.8) + activemodel (= 6.1.7.8) + activesupport (= 6.1.7.8) + activestorage (6.1.7.8) + actionpack (= 6.1.7.8) + activejob (= 6.1.7.8) + activerecord (= 6.1.7.8) + activesupport (= 6.1.7.8) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (6.1.7.8) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) bootsnap (1.9.1) msgpack (~> 1.0) - builder (3.2.4) + builder (3.3.0) byebug (11.1.3) - concurrent-ruby (1.1.9) + concurrent-ruby (1.3.4) crass (1.0.6) - erubi (1.10.0) + date (3.3.4) + erubi (1.13.0) ffi (1.15.4) - globalid (0.5.2) - activesupport (>= 5.0) - i18n (1.8.10) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.6) concurrent-ruby (~> 1.0) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - loofah (2.12.0) + loofah (2.22.0) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.8.1) mini_mime (>= 0.1.1) - marcel (1.0.2) - method_source (1.0.0) - mini_mime (1.1.1) - mini_portile2 (2.8.0) - minitest (5.14.4) + net-imap + net-pop + net-smtp + marcel (1.0.4) + method_source (1.1.0) + mini_mime (1.1.5) + mini_portile2 (2.8.7) + minitest (5.25.1) msgpack (1.4.2) - nio4r (2.5.8) - nokogiri (1.13.4) - mini_portile2 (~> 2.8.0) + net-imap (0.4.16) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.0) + net-protocol + nio4r (2.7.3) + nokogiri (1.16.7) + mini_portile2 (~> 2.8.2) racc (~> 1.4) - puma (4.3.12) + puma (5.6.9) nio4r (~> 2.0) - racc (1.6.0) - rack (2.2.3) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (6.0.4.1) - actioncable (= 6.0.4.1) - actionmailbox (= 6.0.4.1) - actionmailer (= 6.0.4.1) - actionpack (= 6.0.4.1) - actiontext (= 6.0.4.1) - actionview (= 6.0.4.1) - activejob (= 6.0.4.1) - activemodel (= 6.0.4.1) - activerecord (= 6.0.4.1) - activestorage (= 6.0.4.1) - activesupport (= 6.0.4.1) - bundler (>= 1.3.0) - railties (= 6.0.4.1) + racc (1.8.1) + rack (2.2.9) + rack-test (2.1.0) + rack (>= 1.3) + rails (6.1.7.8) + actioncable (= 6.1.7.8) + actionmailbox (= 6.1.7.8) + actionmailer (= 6.1.7.8) + actionpack (= 6.1.7.8) + actiontext (= 6.1.7.8) + actionview (= 6.1.7.8) + activejob (= 6.1.7.8) + activemodel (= 6.1.7.8) + activerecord (= 6.1.7.8) + activestorage (= 6.1.7.8) + activesupport (= 6.1.7.8) + bundler (>= 1.15.0) + railties (= 6.1.7.8) sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.4.2) - loofah (~> 2.3) - railties (6.0.4.1) - actionpack (= 6.0.4.1) - activesupport (= 6.0.4.1) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (6.1.7.8) + actionpack (= 6.1.7.8) + activesupport (= 6.1.7.8) method_source - rake (>= 0.8.7) - thor (>= 0.20.3, < 2.0) - rake (13.0.6) + rake (>= 12.2) + thor (~> 1.0) + rake (13.2.1) rb-fsevent (0.11.0) rb-inotify (0.10.1) ffi (~> 1.0) @@ -126,22 +145,22 @@ GEM spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) - sprockets (4.0.2) + sprockets (4.2.1) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) sqlite3 (1.4.2) - thor (1.1.0) - thread_safe (0.3.6) - tzinfo (1.2.9) - thread_safe (~> 0.1) - websocket-driver (0.7.5) + thor (1.3.2) + timeout (0.4.1) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - zeitwerk (2.4.2) + zeitwerk (2.7.0) PLATFORMS ruby @@ -150,8 +169,8 @@ DEPENDENCIES bootsnap (>= 1.4.2) byebug listen (>= 3.0.5, < 3.2) - puma (~> 4.3) - rails (~> 6.0.2) + puma (~> 5.6) + rails (~> 6.1.7) spring spring-watcher-listen (~> 2.0.0) sqlite3 (~> 1.4) diff --git a/examples/simple_rails_api/WORKSPACE b/examples/simple_rails_api/WORKSPACE index 8585cfec..287c06b4 100644 --- a/examples/simple_rails_api/WORKSPACE +++ b/examples/simple_rails_api/WORKSPACE @@ -1,27 +1,27 @@ -workspace(name = "bazelruby_rules_ruby_example") +workspace(name = "rules_ruby_example") # Importing rules_ruby from the parent directory for developing # rules_ruby itself... local_repository( - name = "bazelruby_rules_ruby", + name = "rules_ruby", path = "../..", ) -load( - "@bazelruby_rules_ruby//ruby:deps.bzl", - "rules_ruby_dependencies", - "rules_ruby_select_sdk", -) +load("@rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies") rules_ruby_dependencies() -rules_ruby_select_sdk(version = "3.0.2") +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") + +ruby_runtime("ruby-3.0") + +register_toolchains("@ruby-3.0//:toolchain") load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +load("@workspace_ruby//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "bundle", diff --git a/examples/simple_script/BUILD.bazel b/examples/simple_script/BUILD.bazel index 3f81e7b9..678c6497 100644 --- a/examples/simple_script/BUILD.bazel +++ b/examples/simple_script/BUILD.bazel @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_binary", "ruby_rspec", "ruby_rubocop", diff --git a/examples/simple_script/Gemfile.lock b/examples/simple_script/Gemfile.lock index 002c1270..9c0f9eff 100644 --- a/examples/simple_script/Gemfile.lock +++ b/examples/simple_script/Gemfile.lock @@ -10,7 +10,8 @@ GEM ast (~> 2.4.1) rainbow (3.0.0) regexp_parser (2.1.1) - rexml (3.2.5) + rexml (3.3.3) + strscan rspec (3.7.0) rspec-core (~> 3.7.0) rspec-expectations (~> 3.7.0) @@ -39,6 +40,7 @@ GEM rubocop-ast (1.11.0) parser (>= 3.0.1.1) ruby-progressbar (1.11.0) + strscan (3.1.0) unicode-display_width (2.1.0) PLATFORMS diff --git a/examples/simple_script/WORKSPACE b/examples/simple_script/WORKSPACE index 4ad11d15..85346469 100644 --- a/examples/simple_script/WORKSPACE +++ b/examples/simple_script/WORKSPACE @@ -1,23 +1,23 @@ -workspace(name = "bazelruby_rules_ruby_example") +workspace(name = "rules_ruby_example") # Importing rules_ruby from the parent directory for developing # rules_ruby itself... local_repository( - name = "bazelruby_rules_ruby", + name = "rules_ruby", path = "../..", ) -load( - "@bazelruby_rules_ruby//ruby:deps.bzl", - "rules_ruby_dependencies", - "rules_ruby_select_sdk", -) +load("@rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies") rules_ruby_dependencies() -rules_ruby_select_sdk(version = "3.0.2") +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") + +ruby_runtime("ruby-3.0") + +register_toolchains("@ruby-3.0//:toolchain") -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +load("@ruby-3.0//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "bundle", diff --git a/examples/simple_script/lib/BUILD b/examples/simple_script/lib/BUILD index f125ff86..b212e7f6 100644 --- a/examples/simple_script/lib/BUILD +++ b/examples/simple_script/lib/BUILD @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_library", ) diff --git a/examples/simple_script_vendored/BUILD.bazel b/examples/simple_script_vendored/BUILD.bazel index 1fc2d136..43b72f7e 100644 --- a/examples/simple_script_vendored/BUILD.bazel +++ b/examples/simple_script_vendored/BUILD.bazel @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_binary", "ruby_rspec", "ruby_rubocop", diff --git a/examples/simple_script_vendored/Gemfile.lock b/examples/simple_script_vendored/Gemfile.lock index 315f6e68..bc9b5d3b 100644 --- a/examples/simple_script_vendored/Gemfile.lock +++ b/examples/simple_script_vendored/Gemfile.lock @@ -8,7 +8,8 @@ GEM ast (~> 2.4.1) rainbow (3.0.0) regexp_parser (2.1.1) - rexml (3.2.5) + rexml (3.3.6) + strscan rspec (3.7.0) rspec-core (~> 3.7.0) rspec-expectations (~> 3.7.0) @@ -37,6 +38,7 @@ GEM rubocop-ast (1.11.0) parser (>= 3.0.1.1) ruby-progressbar (1.11.0) + strscan (3.1.0) unicode-display_width (2.1.0) PLATFORMS diff --git a/examples/simple_script_vendored/WORKSPACE b/examples/simple_script_vendored/WORKSPACE index 3aff264d..93609238 100644 --- a/examples/simple_script_vendored/WORKSPACE +++ b/examples/simple_script_vendored/WORKSPACE @@ -1,26 +1,29 @@ workspace( - name = "bazelruby_rules_ruby_example", + name = "rules_ruby_example", managed_directories = {"@bundle": ["vendor"]}, ) # Importing rules_ruby from the parent directory for developing # rules_ruby itself... local_repository( - name = "bazelruby_rules_ruby", + name = "rules_ruby", path = "../..", ) -load( - "@bazelruby_rules_ruby//ruby:deps.bzl", - "rules_ruby_dependencies", - "rules_ruby_select_sdk", -) +load("@rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies") rules_ruby_dependencies() -rules_ruby_select_sdk(version = "2.7.1") +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") + +ruby_runtime( + name = "ruby-2.7", + version = "ruby-2.7.1", +) + +register_toolchains("@ruby-2.7//:toolchain") -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +load("@ruby-2.7.1//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "bundle", diff --git a/examples/simple_script_vendored/lib/BUILD b/examples/simple_script_vendored/lib/BUILD index f125ff86..b212e7f6 100644 --- a/examples/simple_script_vendored/lib/BUILD +++ b/examples/simple_script_vendored/lib/BUILD @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_library", ) diff --git a/examples/simple_script_vendored/vendor/cache/rexml-3.2.5.gem b/examples/simple_script_vendored/vendor/cache/rexml-3.2.5.gem deleted file mode 100644 index 5680fec4..00000000 Binary files a/examples/simple_script_vendored/vendor/cache/rexml-3.2.5.gem and /dev/null differ diff --git a/examples/simple_script_vendored/vendor/cache/rexml-3.3.6.gem b/examples/simple_script_vendored/vendor/cache/rexml-3.3.6.gem new file mode 100644 index 00000000..bf6b6fdb Binary files /dev/null and b/examples/simple_script_vendored/vendor/cache/rexml-3.3.6.gem differ diff --git a/examples/simple_script_vendored/vendor/cache/strscan-3.1.0.gem b/examples/simple_script_vendored/vendor/cache/strscan-3.1.0.gem new file mode 100644 index 00000000..e7bd7071 Binary files /dev/null and b/examples/simple_script_vendored/vendor/cache/strscan-3.1.0.gem differ diff --git a/ruby/defs.bzl b/ruby/defs.bzl index 1777d38d..924ac2a1 100644 --- a/ruby/defs.bzl +++ b/ruby/defs.bzl @@ -1,44 +1,49 @@ load( - "@bazelruby_rules_ruby//ruby/private:toolchain.bzl", + "@rules_ruby//ruby/private:toolchain.bzl", + _mock_toolchain = "mock_ruby_toolchain", _toolchain = "ruby_toolchain", ) load( - "@bazelruby_rules_ruby//ruby/private:library.bzl", + "@rules_ruby//ruby/private:library.bzl", _library = "ruby_library", ) load( - "@bazelruby_rules_ruby//ruby/private:binary.bzl", + "@rules_ruby//ruby/private:binary.bzl", _binary = "ruby_binary", _test = "ruby_test", ) load( - "@bazelruby_rules_ruby//ruby/private/bundle:def.bzl", - _bundle = "bundle_install", - _ruby_bundle = "ruby_bundle_install", + "@rules_ruby//ruby/private/bundle:def.bzl", + _bundle_install = "bundle_install", ) load( - "@bazelruby_rules_ruby//ruby/private:rspec.bzl", + "@rules_ruby//ruby/private:rspec.bzl", _rspec = "ruby_rspec", _rspec_test = "ruby_rspec_test", ) load( - "@bazelruby_rules_ruby//ruby/private/rubocop:def.bzl", + "@rules_ruby//ruby/private/rubocop:def.bzl", _rubocop = "rubocop", ) load( - "@bazelruby_rules_ruby//ruby/private/gemspec:def.bzl", + "@rules_ruby//ruby/private/gemspec:def.bzl", _gem = "gem", _gemspec = "gemspec", ) +load( + "@rules_ruby//ruby/private:sdk.bzl", + _register_ruby_runtime = "register_ruby_runtime", +) +ruby_mock_toolchain = _mock_toolchain ruby_toolchain = _toolchain ruby_library = _library ruby_binary = _binary ruby_test = _test ruby_rspec_test = _rspec_test ruby_rspec = _rspec -ruby_bundle = _ruby_bundle -ruby_bundle_install = _bundle +ruby_bundle_install = _bundle_install ruby_rubocop = _rubocop ruby_gemspec = _gemspec ruby_gem = _gem +ruby_runtime = _register_ruby_runtime diff --git a/ruby/deps.bzl b/ruby/deps.bzl index 3a7c45b7..90c53ace 100644 --- a/ruby/deps.bzl +++ b/ruby/deps.bzl @@ -1,12 +1,7 @@ # Repository rules load( - "@bazelruby_rules_ruby//ruby/private:dependencies.bzl", + "@rules_ruby//ruby/private:dependencies.bzl", _rules_ruby_dependencies = "rules_ruby_dependencies", ) -load( - "@bazelruby_rules_ruby//ruby/private:sdk.bzl", - _rules_ruby_select_sdk = "rules_ruby_select_sdk", -) rules_ruby_dependencies = _rules_ruby_dependencies -rules_ruby_select_sdk = _rules_ruby_select_sdk diff --git a/ruby/private/BUILD.bazel b/ruby/private/BUILD.bazel index 1c16e04c..98152bbb 100644 --- a/ruby/private/BUILD.bazel +++ b/ruby/private/BUILD.bazel @@ -1,6 +1,7 @@ exports_files( [ "binary_wrapper.tpl", + "binary_runner.tpl", ], visibility = ["//visibility:public"], ) diff --git a/ruby/private/binary.bzl b/ruby/private/binary.bzl index 4a38054d..480fe5e5 100644 --- a/ruby/private/binary.bzl +++ b/ruby/private/binary.bzl @@ -29,7 +29,9 @@ def _get_gem_path(incpaths): # to create a rule (eg, rubocop) that does exactly the same. def ruby_binary_macro(ctx, main, srcs): sdk = ctx.toolchains[TOOLCHAIN_TYPE_NAME].ruby_runtime - interpreter = sdk.interpreter[DefaultInfo].files_to_run.executable + interpreter_info = sdk.interpreter[DefaultInfo] + interpreter = interpreter_info.files_to_run.executable + interpreter_runfiles = interpreter_info.default_runfiles.merge(interpreter_info.data_runfiles) if not main: expected_name = "%s.rb" % ctx.attr.name @@ -45,10 +47,11 @@ def ruby_binary_macro(ctx, main, srcs): ) executable = ctx.actions.declare_file(ctx.attr.name) + wrapper = ctx.actions.declare_file(ctx.attr.name + "_wrapper") deps = _transitive_deps( ctx, - extra_files = [executable], + extra_files = [executable, wrapper, interpreter], extra_deps = ctx.attr._misc_deps, ) @@ -60,21 +63,34 @@ def ruby_binary_macro(ctx, main, srcs): ctx.actions.expand_template( template = ctx.file._wrapper_template, - output = executable, + output = wrapper, substitutions = { "{loadpaths}": repr(deps.incpaths.to_list()), "{rubyopt}": repr(rubyopt), "{main}": repr(_to_manifest_path(ctx, main)), - "{interpreter}": _to_manifest_path(ctx, interpreter), "{gem_path}": gem_path, "{should_gem_pristine}": str(len(gems_to_pristine) > 0).lower(), "{gems_to_pristine}": " ".join(gems_to_pristine), }, ) + ctx.actions.expand_template( + template = ctx.file._runner_template, + output = executable, + substitutions = { + "{main}": wrapper.short_path, + "{interpreter}": interpreter.short_path, + "{workspace_name}": ctx.label.workspace_name or ctx.workspace_name, + }, + is_executable = True, + ) + info = DefaultInfo( executable = executable, - runfiles = deps.default_files.merge(deps.data_files), + runfiles = deps.default_files + .merge(deps.data_files) + .merge(interpreter_runfiles) + .merge(ctx.runfiles(files = [wrapper])), ) return [info] diff --git a/ruby/private/binary_runner.tpl b/ruby/private/binary_runner.tpl new file mode 100644 index 00000000..dc5ae042 --- /dev/null +++ b/ruby/private/binary_runner.tpl @@ -0,0 +1,14 @@ +#!/bin/sh + +if [ -n "${RUNFILES_DIR+x}" ]; then + PATH_PREFIX=$RUNFILES_DIR/{workspace_name}/ +elif [ -s `dirname $0`/../../MANIFEST ]; then + PATH_PREFIX=`cd $(dirname $0); pwd`/ +elif [ -d $0.runfiles ]; then + PATH_PREFIX=`cd $0.runfiles; pwd`/{workspace_name}/ +else + echo "WARNING: it does not look to be at the .runfiles directory" >&2 + exit 1 +fi + +$PATH_PREFIX{interpreter} -I${PATH_PREFIX} ${PATH_PREFIX}{main} "$@" \ No newline at end of file diff --git a/ruby/private/binary_wrapper.tpl b/ruby/private/binary_wrapper.tpl index 09e04024..3b633621 100755 --- a/ruby/private/binary_wrapper.tpl +++ b/ruby/private/binary_wrapper.tpl @@ -1,5 +1,3 @@ -#!/usr/bin/env ruby - # Ruby-port of the Bazel's wrapper script for Python # Copyright 2017 The Bazel Authors. All rights reserved. diff --git a/ruby/private/bundle/create_bundle_build_file.rb b/ruby/private/bundle/create_bundle_build_file.rb index 52626cf2..dfa85960 100755 --- a/ruby/private/bundle/create_bundle_build_file.rb +++ b/ruby/private/bundle/create_bundle_build_file.rb @@ -68,7 +68,9 @@ # # Library path differs across implementations as `lib/ruby` on MRI and `lib/jruby` on JRuby. GEM_PATH = ->(ruby_version, gem_name, gem_version) do - Dir.glob("lib/#{RbConfig::CONFIG['RUBY_INSTALL_NAME']}/#{ruby_version}/gems/#{gem_name}-#{gem_version}*").first + glob = Dir.glob("lib/#{RbConfig::CONFIG['RUBY_BASE_NAME']}/#{ruby_version}/gems/#{gem_name}-#{gem_version}*").first + alt_glob = Dir.glob("lib/#{RbConfig::CONFIG['RUBY_BASE_NAME']}/#{ruby_version}/bundler/gems/#{gem_name}-*").first + glob || alt_glob end # For ordinary gems, this path is like 'lib/ruby/3.0.0/specifications/rspec-3.10.0.gemspec'. @@ -81,9 +83,13 @@ # # Library path differs across implementations as `lib/ruby` on MRI and `lib/jruby` on JRuby. SPEC_PATH = ->(ruby_version, gem_name, gem_version) do - Dir.glob("lib/#{RbConfig::CONFIG['RUBY_INSTALL_NAME']}/#{ruby_version}/specifications/#{gem_name}-#{gem_version}*.gemspec").first + glob = Dir.glob("lib/#{RbConfig::CONFIG['RUBY_BASE_NAME']}/#{ruby_version}/specifications/#{gem_name}-#{gem_version}*.gemspec").first + alt_glob = Dir.glob("lib/#{RbConfig::CONFIG['RUBY_BASE_NAME']}/#{ruby_version}/bundler/gems/#{gem_name}-*/**/*.gemspec").first + glob || alt_glob end +HERE = File.absolute_path '.' + require 'bundler' require 'json' require 'stringio' @@ -191,7 +197,18 @@ def initialize(workspace_name:, # This attribute returns 0 as the third minor version number, which happens to be # what Ruby uses in the PATH to gems, eg. ruby 2.6.5 would have a folder called # ruby/2.6.0/gems for all minor versions of 2.6.* - @ruby_version ||= (RUBY_VERSION.split('.')[0..1] << 0).join('.') + @ruby_version ||= begin + version_string = (RUBY_VERSION.split('.')[0..1] << 0).join('.') + if File.exist?("lib/#{RbConfig::CONFIG['RUBY_BASE_NAME']}/#{version_string}") + version_string + else + if File.exist?("lib/#{RbConfig::CONFIG['RUBY_BASE_NAME']}/#{version_string}+0") + version_string + "+0" + else + raise "Cannot find directory named #{version_string} within lib/#{RbConfig::CONFIG['RUBY_BASE_NAME']}" + end + end + end end def generate! @@ -261,7 +278,14 @@ def register_gem(spec, template_out, bundle_lib_paths, bundle_binaries) # Usually, registering the directory paths listed in the `require_paths` of gemspecs is sufficient, but # some gems also require additional paths to be included in the load paths. require_paths += include_array(spec.name) - gem_lib_paths = require_paths.map { |require_path| File.join(gem_path, require_path) } + gem_lib_paths = require_paths.map do |require_path| + # Gems with native extensions (like ffi) will sometimes have elements of + # require_paths that are absolute rather than gem-path relative paths. + # It is incorrect to prepend those paths with the gem_path and Bazel will + # only allow relative paths as inputs to its glob() function. + pathname = Pathname.new(require_path) + pathname.absolute? ? pathname.relative_path_from(HERE).to_s : File.join(gem_path, require_path) + end bundle_lib_paths.push(*gem_lib_paths) # paths to search for executables diff --git a/ruby/private/bundle/def.bzl b/ruby/private/bundle/def.bzl index e368bd4c..c289d0ae 100644 --- a/ruby/private/bundle/def.bzl +++ b/ruby/private/bundle/def.bzl @@ -44,7 +44,7 @@ def run_bundler(runtime_ctx, bundler_arguments, previous_result): # $ bundle config --local | --global config-option config-value # # @config_category can be either 'local' or 'global' -def set_bundler_config(runtime_ctx, previous_result, config_category = "local"): +def set_bundler_config(runtime_ctx, previous_result, has_lock = True, config_category = "local"): # Bundler is deprecating various flags in favor of the configuration. # HOWEVER — for reasons I can't explain, Bazel runs "bundle install" *prior* # to setting these flags. So the flags are then useless until we can force the @@ -53,11 +53,11 @@ def set_bundler_config(runtime_ctx, previous_result, config_category = "local"): # # Set local configuration options for bundler bundler_config = { - "deployment": "true", + "deployment": "true" if has_lock else "false", "standalone": "true", "force": "false", "redownload": "false", - "frozen": "true", + "frozen": "true" if has_lock else "false", "path": BUNDLE_PATH, "jobs": "20", "shebang": runtime_ctx.interpreter, @@ -117,11 +117,12 @@ def bundle_install(runtime_ctx, previous_result): cwd = runtime_ctx.ctx.path(".") bundler_args = [ "install", - "--binstubs={}".format(cwd.get_child(BUNDLE_BIN_PATH)), - "--path={}".format(cwd.get_child(BUNDLE_PATH)), + "-V", "--standalone", "--gemfile={}".format(runtime_ctx.ctx.attr.gemfile.name), + "--jobs=10", # run a few jobs to ensure no gem install is blocking another ] + if runtime_ctx.ctx.attr.gemfile_lock: bundler_args += ["--deployment", "--frozen"] @@ -133,8 +134,18 @@ def bundle_install(runtime_ctx, previous_result): if result.return_code: fail("bundle install failed: %s%s" % (result.stdout, result.stderr)) - else: - return result + + # Creates a directory and place any executables from the gem there. + result = run_bundler(runtime_ctx, [ + "binstubs", + "--all", + "--path", + "{}".format(BUNDLE_BIN_PATH), + ], previous_result) + if result.return_code: + fail("bundle binstubs failed: %s%s" % (result.stdout, result.stderr)) + + return result def generate_bundle_build_file(runtime_ctx, previous_result): if runtime_ctx.ctx.attr.gemfile_lock: @@ -162,7 +173,7 @@ def generate_bundle_build_file(runtime_ctx, previous_result): if result.return_code: fail("build file generation failed: %s%s" % (result.stdout, result.stderr)) -def _ruby_bundle_impl(ctx): +def ruby_bundle_impl(ctx, ruby_interpreter): ctx.symlink(ctx.attr.gemfile, ctx.attr.gemfile.name) if ctx.attr.gemfile_lock: ctx.symlink(ctx.attr.gemfile_lock, ctx.attr.gemfile_lock.name) @@ -181,23 +192,29 @@ def _ruby_bundle_impl(ctx): # Setup this provider that we pass around between functions for convenience runtime_ctx = RubyRuntimeInfo( ctx = ctx, - interpreter = ctx.path(ctx.attr.ruby_interpreter), + interpreter = ruby_interpreter, environment = {"RUBYOPT": "--enable-gems"}, ) + result = run_bundler( + runtime_ctx, + ["clean"], + None, + ) + # 1. Install the right version of the Bundler Gem result = install_bundler(runtime_ctx, bundler_version) - # 2. Set Bundler config in the .bundle/config file + # 2. Generate a Gemfile.lock file if one isn't provided + if not runtime_ctx.ctx.attr.gemfile_lock: + result = set_bundler_config(runtime_ctx, result, has_lock = False) + result = bundle_install(runtime_ctx, result) + + # 3. Set Bundler config in the .bundle/config file result = set_bundler_config(runtime_ctx, result) - # 3. Run bundle install + # 4. Run bundle install result = bundle_install(runtime_ctx, result) - # 4. Generate the BUILD file for the bundle + # 5. Generate the BUILD file for the bundle generate_bundle_build_file(runtime_ctx, result) - -ruby_bundle_install = repository_rule( - implementation = _ruby_bundle_impl, - attrs = BUNDLE_ATTRS, -) diff --git a/ruby/private/constants.bzl b/ruby/private/constants.bzl index a76f8f3f..4bafff0a 100644 --- a/ruby/private/constants.bzl +++ b/ruby/private/constants.bzl @@ -1,7 +1,7 @@ # Ruby Constants load(":providers.bzl", "RubyLibraryInfo") -RULES_RUBY_WORKSPACE_NAME = "@bazelruby_rules_ruby" +RULES_RUBY_WORKSPACE_NAME = "@rules_ruby" TOOLCHAIN_TYPE_NAME = "%s//ruby:toolchain_type" % RULES_RUBY_WORKSPACE_NAME DEFAULT_BUNDLER_VERSION = "2.1.4" @@ -38,6 +38,10 @@ RUBY_ATTRS = { allow_single_file = True, default = "binary_wrapper.tpl", ), + "_runner_template": attr.label( + allow_single_file = True, + default = "binary_runner.tpl", + ), "_misc_deps": attr.label_list( allow_files = True, default = ["@bazel_tools//tools/bash/runfiles"], @@ -66,12 +70,6 @@ RSPEC_ATTRS.update(RUBY_ATTRS) RSPEC_ATTRS.update(_RSPEC_ATTRS) BUNDLE_ATTRS = { - "ruby_sdk": attr.string( - default = "@org_ruby_lang_ruby_toolchain", - ), - "ruby_interpreter": attr.label( - default = "@org_ruby_lang_ruby_toolchain//:ruby", - ), "gemfile": attr.label( allow_single_file = True, mandatory = True, @@ -154,3 +152,48 @@ GEMSPEC_ATTRS = { default = "%s//ruby/private/gemspec:readme_template.tpl" % RULES_RUBY_WORKSPACE_NAME, ), } + +# The full list of supported pinned version numbers. +SUPPORTED_VERSIONS = [ + "system", + "ruby-2.5.8", + "ruby-2.5.9", + "ruby-2.6.3", + "ruby-2.6.4", + "ruby-2.6.5", + "ruby-2.6.6", + "ruby-2.6.7", + "ruby-2.6.8", + "ruby-2.6.9", + "ruby-2.7.1", + "ruby-2.7.2", + "ruby-2.7.3", + "ruby-2.7.4", + "ruby-2.7.5", + "ruby-3.0.0", + "ruby-3.0.1", + "ruby-3.0.2", + "ruby-3.0.3", + "ruby-3.1.0", + "ruby-3.1.1", + "jruby-9.2.21.0", # Corresponded to 2.5.8 + "jruby-9.3.10.0", # Corresponds to 2.6.8 + "jruby-9.4.3.0", # Corresponds to 3.1.4 +] + +def get_supported_version(version): + """Transforms a user-friendly version identifier to a full version number.""" + + if version[0] >= "0" and version[1] <= "9": + version = "ruby-" + version + + supported_version = None + for v in sorted(SUPPORTED_VERSIONS, reverse = True): + if v.startswith(version): + supported_version = v + break + + if not supported_version: + fail("ruby_runtime: unsupported ruby version '%s' not in '%s'" % (version, SUPPORTED_VERSIONS)) + + return supported_version diff --git a/ruby/private/dependencies.bzl b/ruby/private/dependencies.bzl index 0a51d7a9..589a821e 100644 --- a/ruby/private/dependencies.bzl +++ b/ruby/private/dependencies.bzl @@ -3,6 +3,7 @@ Dependencies """ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load(":constants.bzl", "RULES_RUBY_WORKSPACE_NAME") def rules_ruby_dependencies(): if "bazel_skylib" not in native.existing_rules(): @@ -24,3 +25,17 @@ def rules_ruby_dependencies(): sha256 = "85e26971904cbb387688bd2a9e87c105f7cd7d986dc1b96bb1391924479c5ef6", strip_prefix = "rules_pkg-3e0cd514ad1cdd2d23ab3d427d34436f75060018/pkg", ) + + # Register placeholders for the system ruby. + native.bind( + name = "rules_ruby_system_jruby_implementation", + actual = "%s//:missing_jruby_implementation" % RULES_RUBY_WORKSPACE_NAME, + ) + native.bind( + name = "rules_ruby_system_ruby_implementation", + actual = "%s//:missing_ruby_implementation" % RULES_RUBY_WORKSPACE_NAME, + ) + native.bind( + name = "rules_ruby_system_no_implementation", + actual = "%s//:missing_no_implementation" % RULES_RUBY_WORKSPACE_NAME, + ) diff --git a/ruby/private/providers.bzl b/ruby/private/providers.bzl index 131f3355..624a5302 100644 --- a/ruby/private/providers.bzl +++ b/ruby/private/providers.bzl @@ -19,6 +19,18 @@ RubyRuntimeInfo = provider( ], ) +RubyRuntimeToolchainInfo = provider( + doc = "Information about a Ruby interpreter, related commands and libraries", + fields = { + "interpreter": "A label which points the Ruby interpreter", + "bundler": "A label which points bundler command", + "runtime": "A list of labels which points runtime libraries", + "jars": "A list of labels which points to ruby jars", + "headers": "A list of labels which points to the ruby headers", + "rubyopt": "A list of strings which should be passed to the interpreter as command line options", + }, +) + RubyGemInfo = provider( doc = "Carries info required to package a ruby gem", fields = [ diff --git a/ruby/private/rubocop/def.bzl b/ruby/private/rubocop/def.bzl index 03199063..28cb2404 100644 --- a/ruby/private/rubocop/def.bzl +++ b/ruby/private/rubocop/def.bzl @@ -1,4 +1,4 @@ -load("@bazelruby_rules_ruby//ruby/private:binary.bzl", "ruby_binary") +load("@rules_ruby//ruby/private:binary.bzl", "ruby_binary") # This wraps an rb_binary in a script that is executed from the workspace folder def rubocop(name, bin, deps): @@ -9,7 +9,7 @@ def rubocop(name, bin, deps): deps = deps, ) - runner = "@bazelruby_rules_ruby//ruby/private/rubocop:runner.sh.tpl" + runner = "@rules_ruby//ruby/private/rubocop:runner.sh.tpl" native.genrule( name = name, tools = [bin_name], diff --git a/ruby/private/runtime_alias.bzl b/ruby/private/runtime_alias.bzl new file mode 100644 index 00000000..8da00859 --- /dev/null +++ b/ruby/private/runtime_alias.bzl @@ -0,0 +1,98 @@ +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") +load("@rules_java//java:defs.bzl", "java_binary") +load(":constants.bzl", "TOOLCHAIN_TYPE_NAME") +load(":providers.bzl", "RubyRuntimeToolchainInfo") + +# These rules expose the runtime targets of whichever toolchain has been resolved. + +def _ruby_runtime_alias_impl(ctx): + ruby = ctx.toolchains[TOOLCHAIN_TYPE_NAME].ruby_runtime + return [ + DefaultInfo( + runfiles = ctx.runfiles(transitive_files = depset(ruby.runtime)), + files = depset(ruby.runtime), + ), + ruby, + ] + +ruby_runtime_alias = rule( + implementation = _ruby_runtime_alias_impl, + toolchains = [TOOLCHAIN_TYPE_NAME], +) + +def _ruby_jars_alias_impl(ctx): + runtime = ctx.attr.runtime[RubyRuntimeToolchainInfo] + target = runtime.jars + infos = [ + DefaultInfo( + files = target.files, + runfiles = ctx.runfiles(transitive_files = target.files), + ), + ] + for jar in infos[0].files.to_list(): + infos.append(JavaInfo(jar, jar)) + + return infos + +ruby_jars_alias = rule( + implementation = _ruby_jars_alias_impl, + attrs = { + "runtime": attr.label( + doc = "The runtime alias to use.", + mandatory = True, + ), + }, +) + +def _ruby_headers_alias_impl(ctx): + runtime = ctx.attr.runtime[RubyRuntimeToolchainInfo] + target = runtime.headers + return [ + ctx.attr.runtime[DefaultInfo], + target[CcInfo], + target[InstrumentedFilesInfo], + target[OutputGroupInfo], + ] + +ruby_headers_alias = rule( + implementation = _ruby_headers_alias_impl, + attrs = { + "runtime": attr.label( + doc = "The runtime alias to use.", + mandatory = True, + ), + }, +) + +def _ruby_interpreter_alias_impl(ctx): + runtime = ctx.attr.runtime[RubyRuntimeToolchainInfo] + target = runtime.interpreter + output = ctx.actions.declare_file("ruby_interpreter") + + ctx.actions.symlink( + output = output, + target_file = target[DefaultInfo].files_to_run.executable, + is_executable = True, + ) + runfiles = ctx.attr.runtime[DefaultInfo].default_runfiles.merge( + ctx.attr.runtime[DefaultInfo].data_runfiles, + ) + + return [ + DefaultInfo( + files = target.files, + runfiles = runfiles, + executable = output, + ), + ] + +ruby_interpreter_alias = rule( + implementation = _ruby_interpreter_alias_impl, + executable = True, + attrs = { + "runtime": attr.label( + doc = "The runtime alias to use.", + mandatory = True, + ), + }, +) diff --git a/ruby/private/sdk.bzl b/ruby/private/sdk.bzl index 71235754..da84961c 100644 --- a/ruby/private/sdk.bzl +++ b/ruby/private/sdk.bzl @@ -1,43 +1,61 @@ -load( - "@bazelruby_rules_ruby//ruby/private/toolchains:ruby_runtime.bzl", - _ruby_runtime = "ruby_runtime", -) - -def rules_ruby_select_sdk(version = "host"): - """Registers ruby toolchains in the WORKSPACE file.""" - - supported_versions = [ - "host", - "2.5.8", - "2.5.9", - "2.6.3", - "2.6.4", - "2.6.5", - "2.6.6", - "2.6.7", - "2.6.8", - "2.6.9", - "2.7.1", - "2.7.2", - "2.7.3", - "2.7.4", - "2.7.5", - "3.0.0", - "3.0.1", - "3.0.2", - "3.0.3", - "3.1.0", - "3.1.1", - ] - - if version in supported_versions: - _ruby_runtime( - name = "org_ruby_lang_ruby_toolchain", - version = version, - ) - else: - fail("rules_ruby_select_sdk: unsupported ruby version '%s' not in '%s'" % (version, supported_versions)) +load("@rules_ruby//ruby/private/toolchains:ruby_runtime.bzl", "ruby_runtime") +load(":constants.bzl", "RULES_RUBY_WORKSPACE_NAME", "get_supported_version") + +def register_ruby_runtime(name, version = None): + """Initializes a ruby toolchain at a specific version. + + A special version "system" or "system_ruby" will use whatever version of + ruby is installed on the host system. Besides that, this rules supports all + of versions in the SUPPORTED_VERSIONS list. The most recent matching + version will beselected. + + If the current system ruby doesn't match a given version, it will be + downloaded and built for use by the toolchain. Toolchain selection occurs + based on the //ruby/runtime:version flag setting. + + For example, `register_toolchains("ruby", "ruby-2.5")` will download and + build the latest supported version of Ruby 2.5. + By default, the system ruby will be used for all Bazel build and + tests. However, passing a flag such as: + --@rules_ruby//ruby/runtime:version="ruby-2.5" + will select the Ruby 2.5 installation. + + Optionally, a single string can be passed to this macro and it will use it + for both the name and version. + + Args: + name: the name of the generated Bazel repository + version: a version identifier (e.g. system, ruby-2.5, jruby-9.4) + """ + if not version: + version = name + if version == "system_ruby": + # Special handling to give the system ruby repo a friendly name. + version = "system" - native.register_toolchains( - "@org_ruby_lang_ruby_toolchain//:toolchain", + supported_version = get_supported_version(version) + if supported_version.startswith("ruby-"): + supported_version = supported_version[5:] + + ruby_runtime( + name = name, + version = supported_version, ) + + if supported_version == "system": + native.bind( + name = "rules_ruby_system_jruby_implementation", + actual = "@%s//:jruby_implementation" % name, + ) + native.bind( + name = "rules_ruby_system_ruby_implementation", + actual = "@%s//:ruby_implementation" % name, + ) + native.bind( + name = "rules_ruby_system_no_implementation", + actual = "@%s//:no_implementation" % name, + ) + native.bind( + name = "rules_ruby_system_interpreter", + actual = "@%s//:ruby" % name, + ) diff --git a/ruby/private/toolchain.bzl b/ruby/private/toolchain.bzl index cbaebd67..8af44df2 100644 --- a/ruby/private/toolchain.bzl +++ b/ruby/private/toolchain.bzl @@ -1,21 +1,14 @@ load(":constants.bzl", "RULES_RUBY_WORKSPACE_NAME") - -RubyRuntimeInfo = provider( - doc = "Information about a Ruby interpreter, related commands and libraries", - fields = { - "interpreter": "A label which points the Ruby interpreter", - "bundler": "A label which points bundler command", - "runtime": "A list of labels which points runtime libraries", - "rubyopt": "A list of strings which should be passed to the interpreter as command line options", - }, -) +load(":providers.bzl", "RubyRuntimeToolchainInfo") def _ruby_toolchain_impl(ctx): return [ platform_common.ToolchainInfo( - ruby_runtime = RubyRuntimeInfo( + ruby_runtime = RubyRuntimeToolchainInfo( interpreter = ctx.attr.interpreter, runtime = ctx.files.runtime, + jars = ctx.attr.jars, + headers = ctx.attr.headers, rubyopt = ctx.attr.rubyopt, ), ), @@ -35,6 +28,16 @@ _ruby_toolchain = rule( allow_files = True, cfg = "target", ), + "jars": attr.label( + mandatory = True, + allow_files = True, + cfg = "target", + ), + "headers": attr.label( + mandatory = True, + allow_files = True, + cfg = "target", + ), "rubyopt": attr.string_list( default = [], ), @@ -45,6 +48,8 @@ def ruby_toolchain( name, interpreter, runtime, + jars, + headers, rubyopt = [], rules_ruby_workspace = RULES_RUBY_WORKSPACE_NAME, **kwargs): @@ -53,6 +58,8 @@ def ruby_toolchain( name = impl_name, interpreter = interpreter, runtime = runtime, + jars = jars, + headers = headers, rubyopt = rubyopt, ) @@ -62,3 +69,29 @@ def ruby_toolchain( toolchain = ":%s" % impl_name, **kwargs ) + +def _mock_ruby_toolchain_impl(ctx): + return [ + platform_common.ToolchainInfo(), + ] + +_mock_ruby_toolchain = rule( + implementation = _mock_ruby_toolchain_impl, +) + +def mock_ruby_toolchain( + name, + rules_ruby_workspace = RULES_RUBY_WORKSPACE_NAME, + **kwargs): + impl_name = name + "_sdk" + _mock_ruby_toolchain( + name = impl_name, + ) + native.toolchain( + name = name, + toolchain_type = "%s//ruby:toolchain_type" % rules_ruby_workspace, + toolchain = ":%s" % impl_name, + exec_compatible_with = ["@platforms//:incompatible"], + target_compatible_with = ["@platforms//:incompatible"], + **kwargs + ) diff --git a/ruby/private/toolchains/BUILD b/ruby/private/toolchains/BUILD deleted file mode 100644 index 67efa96b..00000000 --- a/ruby/private/toolchains/BUILD +++ /dev/null @@ -1 +0,0 @@ -package(default_visibility = ["//ruby/private:__pkg__"]) diff --git a/ruby/private/toolchains/BUILD.bazel b/ruby/private/toolchains/BUILD.bazel new file mode 100644 index 00000000..282fec80 --- /dev/null +++ b/ruby/private/toolchains/BUILD.bazel @@ -0,0 +1,38 @@ +load("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") + +package(default_visibility = ["//ruby/private:__pkg__"]) + +# Placeholders for cases when no system ruby is requested +string_flag( + name = "internal_missing_ruby", + build_setting_default = "none", + values = [ + "none", + "ruby", + "jruby", + ], +) + +config_setting( + name = "missing_jruby_implementation", + flag_values = { + ":internal_ruby_implementation": "jruby", + }, +) + +config_setting( + name = "missing_ruby_implementation", + flag_values = { + ":internal_ruby_implementation": "ruby", + }, +) + +config_setting( + name = "missing_no_implementation", + flag_values = { + ":internal_ruby_implementation": "none", + }, +) + +# vim: set ft=bzl : diff --git a/ruby/private/toolchains/BUILD.runtime.tpl b/ruby/private/toolchains/BUILD.runtime.tpl index fbb3e64b..d4bb281b 100644 --- a/ruby/private/toolchains/BUILD.runtime.tpl +++ b/ruby/private/toolchains/BUILD.runtime.tpl @@ -1,49 +1,44 @@ -load( - "{rules_ruby_workspace}//ruby:defs.bzl", - "ruby_library", - "ruby_toolchain", -) +load("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") package(default_visibility = ["//visibility:public"]) -ruby_toolchain( - name = "toolchain", - interpreter = "//:ruby_bin", - rules_ruby_workspace = "{rules_ruby_workspace}", - runtime = "//:runtime", - # TODO(yugui) Extract platform info from RbConfig - # exec_compatible_with = [], - # target_compatible_with = [], -) +# Toolchain targets. These will be mocked out with stubs if no ruby version +# can be found. +{toolchain} -sh_binary( - name = "ruby_bin", - srcs = ["ruby"], - data = [":runtime"], +# Provide config settings to signal the ruby platform to downstream code. +# This should never be overridden, and is determined automatically during the +# creation of the toolchain. +string_flag( + name = "internal_ruby_implementation", + build_setting_default = "{implementation}", + values = [ + "none", + "ruby", + "jruby", + ], ) -cc_import( - name = "libruby", - hdrs = glob({hdrs}), - shared_library = {shared_library}, - static_library = {static_library}, +config_setting( + name = "jruby_implementation", + flag_values = { + ":internal_ruby_implementation": "jruby", + }, ) -cc_library( - name = "headers", - hdrs = glob({hdrs}), - includes = {includes}, +config_setting( + name = "ruby_implementation", + flag_values = { + ":internal_ruby_implementation": "ruby", + }, ) -filegroup( - name = "runtime", - srcs = glob( - include = ["**/*"], - exclude = [ - "BUILD.bazel", - "WORKSPACE", - ], - ), +config_setting( + name = "no_implementation", + flag_values = { + ":internal_ruby_implementation": "none", + }, ) # vim: set ft=bzl : diff --git a/ruby/private/toolchains/ruby_runtime.bzl b/ruby/private/toolchains/ruby_runtime.bzl index 5e533778..651366cd 100644 --- a/ruby/private/toolchains/ruby_runtime.bzl +++ b/ruby/private/toolchains/ruby_runtime.bzl @@ -1,19 +1,152 @@ load("//ruby/private:constants.bzl", "RULES_RUBY_WORKSPACE_NAME") load("//ruby/private/toolchains:repository_context.bzl", "ruby_repository_context") +_mock_toolchain = """ +load( + "{rules_ruby_workspace}//ruby:defs.bzl", + "ruby_mock_toolchain", +) + +ruby_mock_toolchain( + name = "toolchain", + rules_ruby_workspace = "{rules_ruby_workspace}", +) + +sh_binary( + name = "ruby_bin", + srcs = ["ruby"], + data = [":runtime"], +) + +cc_import( + name = "libruby", + hdrs = [], +) + +cc_library( + name = "headers", + hdrs = [], + includes = [], +) + +java_binary( + name = "dummy_jar", + srcs = ["Dummy.java"], +) + +filegroup( + name = "jars", + srcs = [":dummy_jar"], +) + +filegroup( + name = "runtime", + srcs = [], +) +""" + +_toolchain = """ +load( + "{rules_ruby_workspace}//ruby:defs.bzl", + "ruby_toolchain", +) + +ruby_toolchain( + name = "toolchain", + interpreter = "//:ruby_bin", + rules_ruby_workspace = "{rules_ruby_workspace}", + runtime = "//:runtime", + jars = "//:jars", + headers = "//:headers", + target_settings = [ + "{rules_ruby_workspace}//ruby/runtime:{setting}" + ], + # TODO(yugui) Extract platform info from RbConfig + # exec_compatible_with = [], + # target_compatible_with = [], +) + +sh_binary( + name = "ruby_bin", + srcs = ["ruby"], + data = [":runtime"], +) + +cc_import( + name = "libruby", + hdrs = glob({hdrs}, allow_empty = True), + shared_library = {shared_library}, + static_library = {static_library}, +) + +cc_library( + name = "headers", + hdrs = glob({hdrs}, allow_empty = True), + includes = {includes}, +) + +java_library( + name = "dummy_jar", + srcs = ["Dummy.java"], +) + +filegroup( + name = "jars", + srcs = {jars}, +) + +filegroup( + name = "runtime", + srcs = glob( + include = ["**/*"], + exclude = [ + "BUILD.bazel", + "WORKSPACE", + ], + ), +) +""" + +# Define a dummy java file for creating a no-op jar when JRuby isn't selected. +_dummy_jar = """ +public class Dummy { + public static void main(String[] args) {} +} +""" + +_bundle_bzl = """ +load("{rules_ruby_workspace}//ruby/private/bundle:def.bzl", "ruby_bundle_impl") +load("{rules_ruby_workspace}//ruby/private:constants.bzl", "BUNDLE_ATTRS") + +def _ruby_bundle_impl(ctx): + ruby_bundle_impl(ctx, "{interpreter}") + +ruby_bundle = repository_rule( + implementation = _ruby_bundle_impl, + attrs = BUNDLE_ATTRS, +) +""" + +_mock_bundle_bzl = """ +def ruby_bundle(**kwargs): + print("WARNING: no system ruby found for bundle") +""" + def _install_ruby_version(ctx, version): ctx.download_and_extract( - url = "https://github.com/rbenv/ruby-build/archive/refs/tags/v20220218.tar.gz", - sha256 = "35c82b13b7bc3713eee5615b0145c79fbbac32873f55f2ab796620d76970d8e3", - stripPrefix = "ruby-build-20220218", + url = "https://github.com/rbenv/ruby-build/archive/refs/tags/v20230710.tar.gz", + sha256 = "8c9cf458d461a9b6b63d44e4b5b246304168f665fd47adea1733ab6a7cd0f077", + stripPrefix = "ruby-build-20230710", ) install_path = "./build" - ctx.execute( + result = ctx.execute( ["./bin/ruby-build", "--verbose", version, install_path], quiet = False, timeout = 1600, # massive timeout because this does a lot and is a beast ) + if result.return_code: + fail("Ruby build failed: %s %s" % (result.stdout, result.stderr)) def _is_subpath(path, ancestors): """Determines if path is a subdirectory of one of the ancestors""" @@ -99,14 +232,27 @@ def _install_ruby(ctx, ruby): shared_library = _relativate(shared_library), ) -def host_ruby_is_correct_version(ctx, version): +def get_ruby_info(ctx, interpreter_path): + platform = ctx.execute([interpreter_path, "-e", "print RUBY_PLATFORM"]).stdout + if platform == "java": + ruby_impl = "jruby" + ruby_version = ctx.execute([interpreter_path, "-e", "print JRUBY_VERSION"]).stdout + else: + ruby_impl = "ruby" + ruby_version = ctx.execute([interpreter_path, "-e", "print RUBY_VERSION"]).stdout + + return ruby_impl, ruby_version + +def system_ruby_is_correct_version(ctx, version): interpreter_path = ctx.which("ruby") if not interpreter_path: print("Can't find ruby interpreter in the PATH") return False - ruby_version = ctx.execute(["ruby", "-e", "print RUBY_VERSION"]).stdout + ruby_impl, ruby_version = get_ruby_info(ctx, interpreter_path) + if ruby_impl == "jruby": + ruby_version = "jruby-" + ruby_version have_ruby_version = (version == ruby_version) @@ -118,39 +264,60 @@ def host_ruby_is_correct_version(ctx, version): def _ruby_runtime_impl(ctx): # If the current version of ruby is correct use that version = ctx.attr.version - if version == "host" or host_ruby_is_correct_version(ctx, version): + if version == "system" or system_ruby_is_correct_version(ctx, version): interpreter_path = ctx.which("ruby") else: _install_ruby_version(ctx, version) interpreter_path = ctx.path("./build/bin/ruby") + if not interpreter_path or not interpreter_path.exists: + fail("Installation of ruby version %s failed") - if not interpreter_path: - fail( - "Command 'ruby' not found. Set $PATH or specify interpreter_path", - "interpreter_path", - ) - - ruby = ruby_repository_context(ctx, interpreter_path) + ctx.file("Dummy.java", _dummy_jar) - installed = _install_ruby(ctx, ruby) + if interpreter_path and interpreter_path.exists: + ruby = ruby_repository_context(ctx, interpreter_path) + installed = _install_ruby(ctx, ruby) + ruby_impl, ruby_version = get_ruby_info(ctx, interpreter_path) + hdrs = ["%s/**/*.h" % path for path in installed.includedirs] + toolchain = _toolchain.format( + includes = repr(installed.includedirs), + hdrs = repr(["%s/**/*.h" % path for path in installed.includedirs]), + jars = "glob([\"**/lib/jruby.jar\"])" if ruby_impl == "jruby" else [":dummy_jar"], + static_library = repr(installed.static_library), + shared_library = repr(installed.shared_library), + rules_ruby_workspace = RULES_RUBY_WORKSPACE_NAME, + version = ruby_version, + setting = "config_system" if version == "system" else "config_%s-%s" % (ruby_impl, ruby_version), + ) + bundle_bzl = _bundle_bzl.format( + interpreter = ruby.interpreter_realpath, + rules_ruby_workspace = RULES_RUBY_WORKSPACE_NAME, + ) + else: + print("WARNING: no system ruby available, builds against system ruby will fail") + support = "none" + ruby_impl = "none" + toolchain = _mock_toolchain.format( + rules_ruby_workspace = RULES_RUBY_WORKSPACE_NAME, + ) + ctx.file("ruby", content = "", executable = True) + bundle_bzl = _mock_bundle_bzl ctx.template( "BUILD.bazel", ctx.attr._buildfile_template, substitutions = { - "{includes}": repr(installed.includedirs), - "{hdrs}": repr(["%s/**/*.h" % path for path in installed.includedirs]), - "{static_library}": repr(installed.static_library), - "{shared_library}": repr(installed.shared_library), - "{rules_ruby_workspace}": RULES_RUBY_WORKSPACE_NAME, + "{toolchain}": toolchain, + "{implementation}": ruby_impl, }, executable = False, ) + ctx.file("bundle.bzl", bundle_bzl) ruby_runtime = repository_rule( implementation = _ruby_runtime_impl, attrs = { - "version": attr.string(default = "host"), + "version": attr.string(default = "system"), "_buildfile_template": attr.label( default = "%s//ruby/private/toolchains:BUILD.runtime.tpl" % ( RULES_RUBY_WORKSPACE_NAME @@ -164,4 +331,9 @@ ruby_runtime = repository_rule( allow_single_file = True, ), }, + # Force a re-fetch when the Ruby version is changed through RVM. + # This will also force a re-download when PATH changes, which is + # unnecessary. To fix this, we may want to make system_ruby() + # a different repository rule from ruby_runtime(). + environ = ["PATH"], ) diff --git a/ruby/runtime/BUILD.bazel b/ruby/runtime/BUILD.bazel new file mode 100644 index 00000000..288e3d14 --- /dev/null +++ b/ruby/runtime/BUILD.bazel @@ -0,0 +1,139 @@ +load("@bazel_skylib//lib:selects.bzl", "selects") +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") +load("@rules_ruby//ruby/private:constants.bzl", "get_supported_version") +load( + ":version_support.bzl", + "ALL_JRUBY_MAJOR_MINOR_VERSIONS", + "ALL_RUBY_MAJOR_MINOR_VERSIONS", + "SUPPORTED_MAJOR_MINOR_VERSIONS", +) +load( + "@rules_ruby//ruby/private:runtime_alias.bzl", + _ruby_headers_alias = "ruby_headers_alias", + _ruby_interpreter_alias = "ruby_interpreter_alias", + _ruby_jars_alias = "ruby_jars_alias", + _ruby_runtime_alias = "ruby_runtime_alias", +) + +package(default_visibility = ["//visibility:public"]) + +toolchain_type(name = "toolchain_type") + +# Alias targets corresponding to whichever toolchain was resolved based on +# the selected version. + +_ruby_runtime_alias( + name = "runtime", +) + +_ruby_jars_alias( + name = "jars", + runtime = ":runtime", +) + +java_binary( + name = "jruby_binary", + main_class = "org.jruby.Main", + runtime_deps = [":jars"], +) + +_ruby_headers_alias( + name = "headers", + runtime = ":runtime", +) + +_ruby_interpreter_alias( + name = "interpreter", + runtime = ":runtime", +) + +# Supported ruby versions, which can be selected by flags. +# For example: --@rules_ruby//ruby/runtime:version=jruby-9.3 +string_flag( + name = "version", + build_setting_default = "auto", + values = [ + "auto", + "system", + ] + SUPPORTED_MAJOR_MINOR_VERSIONS, +) + +config_setting( + name = "config_auto", + flag_values = {"version": "auto"}, +) + +config_setting( + name = "internal_config_system", + flag_values = {"version": "system"}, +) + +[ + config_setting( + name = "internal_config_" + get_supported_version(version), + flag_values = {"version": version}, + ) + for version in SUPPORTED_MAJOR_MINOR_VERSIONS +] + +selects.config_setting_group( + name = "config_system", + match_any = [ + ":config_auto", + ":internal_config_system", + ], +) + +[ + selects.config_setting_group( + name = "config_" + get_supported_version(version), + match_any = [ + ":internal_config_" + get_supported_version(version), + ], + ) + for version in SUPPORTED_MAJOR_MINOR_VERSIONS +] + +[ + alias( + name = "config_" + version, + actual = ":config_" + get_supported_version(version), + ) + for version in SUPPORTED_MAJOR_MINOR_VERSIONS +] + +selects.config_setting_group( + name = "config_system_ruby", + match_all = [ + ":config_system", + "//external:rules_ruby_system_ruby_implementation", + ], +) + +selects.config_setting_group( + name = "config_ruby", + match_any = [":config_system_ruby"] + + [":config_%s" % v for v in ALL_RUBY_MAJOR_MINOR_VERSIONS], +) + +selects.config_setting_group( + name = "config_system_jruby", + match_all = [ + ":config_system", + "//external:rules_ruby_system_jruby_implementation", + ], +) + +selects.config_setting_group( + name = "config_jruby", + match_any = [":config_system_jruby"] + + [":config_%s" % v for v in ALL_JRUBY_MAJOR_MINOR_VERSIONS], +) + +selects.config_setting_group( + name = "config_system_none", + match_all = [ + ":config_system", + "//external:rules_ruby_system_no_implementation", + ], +) diff --git a/ruby/runtime/version_support.bzl b/ruby/runtime/version_support.bzl new file mode 100644 index 00000000..40dfa63d --- /dev/null +++ b/ruby/runtime/version_support.bzl @@ -0,0 +1,26 @@ +load("@bazel_skylib//lib:new_sets.bzl", "sets") +load( + "@rules_ruby//ruby/private:constants.bzl", + "SUPPORTED_VERSIONS", +) + +def _major_minor_versions(): + """Filters supported versions to unique major/minor pairs""" + versions = sets.make() + for s in SUPPORTED_VERSIONS: + if s.find(".") < 0: + continue + split = s.find(".", s.find(".") + 1) + sets.insert(versions, s[0:split]) + return sorted(sets.to_list(versions)) + +def _filter(versions, prefix): + filtered = [] + for v in versions: + if v.startswith(prefix): + filtered.append(v) + return filtered + +SUPPORTED_MAJOR_MINOR_VERSIONS = _major_minor_versions() +ALL_RUBY_MAJOR_MINOR_VERSIONS = _filter(SUPPORTED_MAJOR_MINOR_VERSIONS, "ruby-") +ALL_JRUBY_MAJOR_MINOR_VERSIONS = _filter(SUPPORTED_MAJOR_MINOR_VERSIONS, "jruby-") diff --git a/ruby/tests/BUILD.bazel b/ruby/tests/BUILD.bazel index b3e7290e..1ac2d437 100644 --- a/ruby/tests/BUILD.bazel +++ b/ruby/tests/BUILD.bazel @@ -65,7 +65,7 @@ sh_test( ], data = [ "args_check.rb", - "@org_ruby_lang_ruby_toolchain//:ruby_bin", + "@rules_ruby//ruby/runtime:interpreter", ], ) @@ -74,7 +74,7 @@ genrule( name = "generate_genrule_run_ruby_test", outs = ["genrules_run_ruby_test.sh"], cmd = " && ".join([ - ("$(location @org_ruby_lang_ruby_toolchain//:ruby_bin) " + + ("$(location @rules_ruby//ruby/runtime:interpreter) " + "$(location args_check.rb) foo bar baz"), "echo '#!/bin/sh -e' > $@", "echo true >> $@", @@ -83,8 +83,8 @@ genrule( output_to_bindir = 1, tools = [ "args_check.rb", - "@org_ruby_lang_ruby_toolchain//:ruby_bin", - "@org_ruby_lang_ruby_toolchain//:runtime", + "@rules_ruby//ruby/runtime", + "@rules_ruby//ruby/runtime:interpreter", ], ) @@ -120,7 +120,7 @@ ruby_binary( main = "load_path_in_runfiles_test.rb", deps = [ "//ruby/tests/testdata:g", - "@bazelruby_rules_ruby_ruby_tests_testdata_another_workspace//baz/qux:j", + "@rules_ruby_ruby_tests_testdata_another_workspace//baz/qux:j", ], ) @@ -137,7 +137,7 @@ ruby_test( main = "load_path_in_runfiles_test.rb", deps = [ "//ruby/tests/testdata:g", - "@bazelruby_rules_ruby_ruby_tests_testdata_another_workspace//baz/qux:j", + "@rules_ruby_ruby_tests_testdata_another_workspace//baz/qux:j", ], ) @@ -188,7 +188,7 @@ cc_binary( testonly = True, srcs = ["example_ext.c"], linkshared = True, - deps = ["@org_ruby_lang_ruby_toolchain//:headers"], + deps = ["@rules_ruby//ruby/runtime:headers"], ) cc_library( @@ -197,7 +197,7 @@ cc_library( srcs = ["example_ext.c"], linkstatic = True, tags = ["manual"], - deps = ["@org_ruby_lang_ruby_toolchain//:headers"], + deps = ["@rules_ruby//ruby/runtime:headers"], alwayslink = True, ) @@ -250,13 +250,13 @@ pkg_tar( include_runfiles = True, package_dir = "/app", remap_paths = { - "ruby": "load_path_in_runfiles.runfiles/bazelruby_rules_ruby/ruby", + "ruby": "load_path_in_runfiles.runfiles/rules_ruby/ruby", ".": "load_path_in_runfiles.runfiles/", }, strip_prefix = "dummy", symlinks = { - "/app/load_path_in_runfiles.runfiles/bazelruby_rules_ruby/external": "/app/load_path_in_runfiles.runfiles", - "/app/load_path_in_runfiles": "/app/load_path_in_runfiles.runfiles/bazelruby_rules_ruby/ruby/tests/load_path_in_runfiles", + "/app/load_path_in_runfiles.runfiles/rules_ruby/external": "/app/load_path_in_runfiles.runfiles", + "/app/load_path_in_runfiles": "/app/load_path_in_runfiles.runfiles/rules_ruby/ruby/tests/load_path_in_runfiles", }, ) diff --git a/ruby/tests/load_path_in_runfiles_test.rb b/ruby/tests/load_path_in_runfiles_test.rb index 95218273..1af9a4ea 100644 --- a/ruby/tests/load_path_in_runfiles_test.rb +++ b/ruby/tests/load_path_in_runfiles_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true require 'ruby/tests/testdata/foo/g' -require 'external/bazelruby_rules_ruby_ruby_tests_testdata_another_workspace/baz/qux/j' +require 'external/rules_ruby_ruby_tests_testdata_another_workspace/baz/qux/j' [g, j] diff --git a/ruby/tests/runtime_run_ruby_test.sh b/ruby/tests/runtime_run_ruby_test.sh index 6a3e270d..7de0ac8c 100755 --- a/ruby/tests/runtime_run_ruby_test.sh +++ b/ruby/tests/runtime_run_ruby_test.sh @@ -1,2 +1,2 @@ #!/bin/sh -e -external/org_ruby_lang_ruby_toolchain/ruby_bin $* +ruby/runtime/ruby_interpreter $* diff --git a/ruby/tests/testdata/another_workspace/WORKSPACE b/ruby/tests/testdata/another_workspace/WORKSPACE index 86ed1c1f..0f914eb0 100644 --- a/ruby/tests/testdata/another_workspace/WORKSPACE +++ b/ruby/tests/testdata/another_workspace/WORKSPACE @@ -1,5 +1,7 @@ -workspace(name = "bazelruby_rules_ruby_ruby_tests_testdata_another_workspace") +workspace(name = "rules_ruby_ruby_tests_testdata_another_workspace") -load("@bazelruby_rules_ruby//ruby:defs.bzl", "rules_ruby_select_sdk") +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") -rules_ruby_select_sdk() +ruby_runtime("system_ruby") + +register_toolchains("@system_ruby//:toolchain") diff --git a/ruby/tests/testdata/another_workspace/baz/qux/BUILD.bazel b/ruby/tests/testdata/another_workspace/baz/qux/BUILD.bazel index 89a2dfed..96d5c614 100644 --- a/ruby/tests/testdata/another_workspace/baz/qux/BUILD.bazel +++ b/ruby/tests/testdata/another_workspace/baz/qux/BUILD.bazel @@ -1,4 +1,4 @@ -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_library") +load("@rules_ruby//ruby:defs.bzl", "ruby_library") package(default_visibility = ["//visibility:public"]) diff --git a/ruby/tests/testdata/bundle_includes_workspace/BUILD.bazel b/ruby/tests/testdata/bundle_includes_workspace/BUILD.bazel index 01b33fa7..5663a68a 100644 --- a/ruby/tests/testdata/bundle_includes_workspace/BUILD.bazel +++ b/ruby/tests/testdata/bundle_includes_workspace/BUILD.bazel @@ -1,5 +1,5 @@ load( - "@bazelruby_rules_ruby//ruby:defs.bzl", + "@rules_ruby//ruby:defs.bzl", "ruby_binary", ) diff --git a/ruby/tests/testdata/bundle_includes_workspace/WORKSPACE b/ruby/tests/testdata/bundle_includes_workspace/WORKSPACE index 00a3bb41..25c14f53 100644 --- a/ruby/tests/testdata/bundle_includes_workspace/WORKSPACE +++ b/ruby/tests/testdata/bundle_includes_workspace/WORKSPACE @@ -1,21 +1,21 @@ -workspace(name = "bazelruby_rules_ruby_ruby_tests_testdata_bundle_includes_workspace") +workspace(name = "rules_ruby_ruby_tests_testdata_bundle_includes_workspace") local_repository( - name = "bazelruby_rules_ruby", + name = "rules_ruby", path = "../../../..", ) -load( - "@bazelruby_rules_ruby//ruby:deps.bzl", - "rules_ruby_dependencies", - "rules_ruby_select_sdk", -) +load("@rules_ruby//ruby:deps.bzl", "rules_ruby_dependencies") rules_ruby_dependencies() -rules_ruby_select_sdk(version = "3.0.2") +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") + +ruby_runtime("ruby-3.0") + +register_toolchains("@ruby-3.0//:toolchain") -load("@bazelruby_rules_ruby//ruby:defs.bzl", "ruby_bundle") +load("@ruby-3.0//:bundle.bzl", "ruby_bundle") ruby_bundle( name = "gems", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy