From faed859058e59c6174825e59f59a9a2f19f02387 Mon Sep 17 00:00:00 2001 From: Alex Rodionov Date: Thu, 20 Feb 2025 10:46:45 -0800 Subject: [PATCH 1/4] fix: broken BCR presubmit command --- .bcr/presubmit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml index 48dcdc82..a7c79107 100644 --- a/.bcr/presubmit.yml +++ b/.bcr/presubmit.yml @@ -11,6 +11,6 @@ bcr_test_module: platform: ${{ platform }} bazel: ${{ bazel }} test_flags: - - "--test_tag_filters -bcr-presubmit-failure" + - "--test_tag_filters=-bcr-presubmit-failure" test_targets: - "//..." From b232ed7a254aa41b7c6b050e5048da3d9382e01e Mon Sep 17 00:00:00 2001 From: Alex Rodionov Date: Thu, 20 Feb 2025 10:47:34 -0800 Subject: [PATCH 2/4] fix: expose headers/jars on system ruby Fixes #208 --- .github/workflows/ci.yml | 11 +++++++-- ruby/private/download.bzl | 49 +++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93ea181a..2e281c0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: - if: matrix.ruby == 'system' uses: ruby/setup-ruby@v1 with: - ruby-version: "3.1.6" + ruby-version: 3.1.6 - run: bazel build ... - run: bazel run lib/gem:add-numbers 2 - run: bazel run lib/gem:print-version @@ -114,6 +114,9 @@ jobs: ruby: - 3.3.7 - jruby-9.4.12.0 + use-system-ruby: + - true + - false defaults: run: working-directory: examples/native_ext @@ -123,7 +126,11 @@ jobs: with: bazelrc: common --announce_rc --color=yes repository-cache: examples/native_ext/MODULE.bazel - - run: echo ${{ matrix.ruby }} > .ruby-version + - if: matrix.use-system-ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - run: echo ${{ matrix.use-system-ruby && 'system' || matrix.ruby }} > .ruby-version - run: bazel build ... - if: failure() && runner.debug == '1' uses: mxschmitt/action-tmate@v3 diff --git a/ruby/private/download.bzl b/ruby/private/download.bzl index 02be0975..4d266a3e 100644 --- a/ruby/private/download.bzl +++ b/ruby/private/download.bzl @@ -85,36 +85,34 @@ def _rb_download_impl(repository_ctx): else: fail("missing value for one of mandatory attributes 'version' or 'version_file'") + engine = "ruby" + env = {} + ruby_binary_name = "ruby" + gem_binary_name = "gem" if version.startswith("jruby"): _install_jruby(repository_ctx, version) - elif version == "system": - _symlink_system_ruby(repository_ctx) - elif repository_ctx.os.name.startswith("windows"): - _install_via_rubyinstaller(repository_ctx, version) - else: - _install_via_ruby_build(repository_ctx, version) - if version.startswith("jruby"): + engine = "jruby" ruby_binary_name = "jruby" gem_binary_name = "jgem" - else: - ruby_binary_name = "ruby" - gem_binary_name = "gem" - - env = {} - engine = "ruby" - if version.startswith("jruby"): - engine = "jruby" # JRuby might fail with "Errno::EACCES: Permission denied - NUL" on Windows: # https://github.com/jruby/jruby/issues/7182#issuecomment-1112953015 env.update({"JAVA_OPTS": "-Djdk.io.File.enableADS=true"}) elif version.startswith("truffleruby"): + _install_via_ruby_build(repository_ctx, version) + engine = "truffleruby" # TruffleRuby needs explicit locale # https://www.graalvm.org/dev/reference-manual/ruby/UTF8Locale/ env.update({"LANG": "en_US.UTF-8"}) + elif version == "system": + engine = _symlink_system_ruby(repository_ctx) + elif repository_ctx.os.name.startswith("windows"): + _install_via_rubyinstaller(repository_ctx, version) + else: + _install_via_ruby_build(repository_ctx, version) includes = [] if repository_ctx.path("dist/include").exists: @@ -262,11 +260,22 @@ def _symlink_system_ruby(repository_ctx): result = repository_ctx.execute(["ruby", "-e", "puts RbConfig.ruby"]) if result.return_code != 0: fail("Failed to determine the system Ruby path:\n%s\n%s" % (result.stdout, result.stderr)) - ruby_path = result.stdout.strip() - ruby_dir = repository_ctx.path(ruby_path).dirname - repository_ctx.symlink(ruby_dir, "dist/bin") - if repository_ctx.os.name.startswith("windows"): - repository_ctx.symlink(ruby_dir.dirname.get_child("lib"), "dist/lib") + + _symlink_system_ruby_dir("bindir", repository_ctx) + _symlink_system_ruby_dir("libdir", repository_ctx) + _symlink_system_ruby_dir("rubyhdrdir", repository_ctx) + + engine = repository_ctx.execute(["ruby", "-e", "puts RbConfig::CONFIG['RUBY_BASE_NAME']"]).stdout.strip() + return engine + +def _symlink_system_ruby_dir(dirname, repository_ctx): + prefix = repository_ctx.execute(["ruby", "-e", "puts RbConfig::CONFIG['prefix']"]).stdout.strip() + path = repository_ctx.execute(["ruby", "-e", "puts RbConfig::CONFIG['{dirname}']".format(dirname = dirname)]).stdout.strip() + src = repository_ctx.path(path) + dirname = path.removeprefix(prefix).removeprefix("/") + dst = repository_ctx.path("dist/{dirname}".format(dirname = dirname)) + if not dst.exists: + repository_ctx.symlink(src, dst) rb_download = repository_rule( implementation = _rb_download_impl, From 25daf0e1019f28887a42dc528beea69b27ed2383 Mon Sep 17 00:00:00 2001 From: Alex Rodionov Date: Thu, 20 Feb 2025 13:48:06 -0800 Subject: [PATCH 3/4] fix: allow .tool-versions in version_file --- ruby/private/download.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/private/download.bzl b/ruby/private/download.bzl index 4d266a3e..1a743bc1 100644 --- a/ruby/private/download.bzl +++ b/ruby/private/download.bzl @@ -284,7 +284,7 @@ rb_download = repository_rule( doc = "Ruby version to install.", ), "version_file": attr.label( - allow_single_file = [".ruby-version"], + allow_single_file = [".ruby-version", ".tool-versions"], doc = "File to read Ruby version from.", ), "msys2_packages": attr.string_list( From 5e43d14b3b38986db85b86b575562d062b2f8e81 Mon Sep 17 00:00:00 2001 From: Alex Rodionov Date: Fri, 21 Feb 2025 08:41:43 -0800 Subject: [PATCH 4/4] refactor: introduce helper for executing commands in repository --- ruby/private/download.bzl | 46 +++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/ruby/private/download.bzl b/ruby/private/download.bzl index 1a743bc1..22d74527 100644 --- a/ruby/private/download.bzl +++ b/ruby/private/download.bzl @@ -192,7 +192,7 @@ def _install_via_rubyinstaller(repository_ctx, version): ) repository_ctx.report_progress("Installing Ruby %s" % version) - result = repository_ctx.execute([ + _execute_command(repository_ctx, [ "./ruby-installer.exe", "/components=ruby,msys2", "/currentuser", @@ -201,30 +201,19 @@ def _install_via_rubyinstaller(repository_ctx, version): "/verysilent", ]) repository_ctx.delete("ruby-installer.exe") - if result.return_code != 0: - fail("%s\n%s" % (result.stdout, result.stderr)) - result = repository_ctx.execute(["./dist/bin/ridk.cmd", "install", "1", "3"]) - if result.return_code != 0: - fail("%s\n%s" % (result.stdout, result.stderr)) + _execute_command(repository_ctx, ["./dist/bin/ridk.cmd", "install", "1", "3"]) if len(repository_ctx.attr.msys2_packages) > 0: - mingw_package_prefix = None - result = repository_ctx.execute([ + mingw_package_prefix = _execute_command(repository_ctx, [ "./dist/bin/ruby.exe", "-rruby_installer", "-e", "puts RubyInstaller::Runtime::Msys2Installation.new.mingw_package_prefix", ]) - if result.return_code != 0: - fail("%s\n%s" % (result.stdout, result.stderr)) - else: - mingw_package_prefix = result.stdout.strip() packages = ["%s-%s" % (mingw_package_prefix, package) for package in repository_ctx.attr.msys2_packages] - result = repository_ctx.execute(["./dist/bin/ridk.cmd", "exec", "pacman", "--sync", "--noconfirm"] + packages) - if result.return_code != 0: - fail("%s\n%s" % (result.stdout, result.stderr)) + _execute_command(repository_ctx, ["./dist/bin/ridk.cmd", "exec", "pacman", "--sync", "--noconfirm"] + packages) # Ruby 3.0 compatibility binpath = repository_ctx.path("dist/bin") @@ -245,7 +234,8 @@ def _install_via_ruby_build(repository_ctx, version): ) repository_ctx.report_progress("Installing Ruby %s" % version) - result = repository_ctx.execute( + _execute_command( + repository_ctx, ["ruby-build/bin/ruby-build", "--verbose", version, "dist", "--", "--disable-install-doc"], timeout = 1200, quiet = not repository_ctx.os.environ.get("RUBY_RULES_DEBUG", default = False), @@ -253,30 +243,34 @@ def _install_via_ruby_build(repository_ctx, version): repository_ctx.delete("ruby-build") - if result.return_code != 0: - fail("%s\n%s" % (result.stdout, result.stderr)) - def _symlink_system_ruby(repository_ctx): - result = repository_ctx.execute(["ruby", "-e", "puts RbConfig.ruby"]) - if result.return_code != 0: - fail("Failed to determine the system Ruby path:\n%s\n%s" % (result.stdout, result.stderr)) - _symlink_system_ruby_dir("bindir", repository_ctx) _symlink_system_ruby_dir("libdir", repository_ctx) _symlink_system_ruby_dir("rubyhdrdir", repository_ctx) - engine = repository_ctx.execute(["ruby", "-e", "puts RbConfig::CONFIG['RUBY_BASE_NAME']"]).stdout.strip() + engine = _execute_command(repository_ctx, ["ruby", "-e", "puts RbConfig::CONFIG['RUBY_BASE_NAME']"]) return engine def _symlink_system_ruby_dir(dirname, repository_ctx): - prefix = repository_ctx.execute(["ruby", "-e", "puts RbConfig::CONFIG['prefix']"]).stdout.strip() - path = repository_ctx.execute(["ruby", "-e", "puts RbConfig::CONFIG['{dirname}']".format(dirname = dirname)]).stdout.strip() + prefix = _execute_command(repository_ctx, ["ruby", "-e", "puts RbConfig::CONFIG['prefix']"]) + path = _execute_command(repository_ctx, ["ruby", "-e", "puts RbConfig::CONFIG['{dirname}']".format(dirname = dirname)]) src = repository_ctx.path(path) dirname = path.removeprefix(prefix).removeprefix("/") dst = repository_ctx.path("dist/{dirname}".format(dirname = dirname)) if not dst.exists: repository_ctx.symlink(src, dst) +def _execute_command(repository_ctx, command, timeout = 600, quiet = False): + result = repository_ctx.execute(command, timeout = timeout, quiet = quiet) + if result.return_code != 0: + fail("Command '{command}' failed ({code} exit code):\n{stdout}\n{stderr}".format( + command = " ".join(command), + code = result.return_code, + stdout = result.stdout, + stderr = result.stderr, + )) + return result.stdout.strip() + rb_download = repository_rule( implementation = _rb_download_impl, attrs = {