diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f36744e..981ac4b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -43,7 +43,7 @@ jobs: fail-fast: false matrix: os: [ubuntu] - ruby: ['2.6', '2.7', '3.0', '3.1', '3.2', 'ruby-head', 'debug', 'truffleruby'] + ruby: ['2.6', '2.7', '3.0', '3.1', '3.2', 'ruby-head', 'debug', 'truffleruby', 'truffleruby-head'] runs-on: ${{ matrix.os }}-latest steps: - uses: actions/checkout@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 543db62..dac8c5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased * Support YAML and JSON CompileCache on TruffleRuby. +* Support LoadPathCache on TruffleRuby. # 1.16.0 diff --git a/lib/bootsnap/load_path_cache.rb b/lib/bootsnap/load_path_cache.rb index 2279aa1..11f8a94 100644 --- a/lib/bootsnap/load_path_cache.rb +++ b/lib/bootsnap/load_path_cache.rb @@ -54,8 +54,17 @@ def unload! end def supported? - RUBY_ENGINE == "ruby" && - RUBY_PLATFORM =~ /darwin|linux|bsd|mswin|mingw|cygwin/ + if RUBY_PLATFORM.match?(/darwin|linux|bsd|mswin|mingw|cygwin/) + case RUBY_ENGINE + when "truffleruby" + # https://github.com/oracle/truffleruby/issues/3131 + RUBY_ENGINE_VERSION >= "23.1.0" + when "ruby" + true + else + false + end + end end end end diff --git a/lib/bootsnap/load_path_cache/cache.rb b/lib/bootsnap/load_path_cache/cache.rb index 32dc8b8..4d30c9e 100644 --- a/lib/bootsnap/load_path_cache/cache.rb +++ b/lib/bootsnap/load_path_cache/cache.rb @@ -24,8 +24,16 @@ def load_dir(dir) @mutex.synchronize { @dirs[dir] } end + TRUFFLERUBY_LIB_DIR_PREFIX = if RUBY_ENGINE == "truffleruby" + "#{File.join(RbConfig::CONFIG['libdir'], 'truffle')}#{File::SEPARATOR}" + end + # { 'enumerator' => nil, 'enumerator.so' => nil, ... } BUILTIN_FEATURES = $LOADED_FEATURES.each_with_object({}) do |feat, features| + if TRUFFLERUBY_LIB_DIR_PREFIX && feat.start_with?(TRUFFLERUBY_LIB_DIR_PREFIX) + feat = feat.byteslice(TRUFFLERUBY_LIB_DIR_PREFIX.bytesize..-1) + end + # Builtin features are of the form 'enumerator.so'. # All others include paths. next unless feat.size < 20 && !feat.include?("/") diff --git a/test/integration/kernel_test.rb b/test/integration/kernel_test.rb index e387ee4..2a17326 100644 --- a/test/integration/kernel_test.rb +++ b/test/integration/kernel_test.rb @@ -8,6 +8,8 @@ class KernelTest < Minitest::Test include TmpdirHelper def test_require_symlinked_file_twice + skip("https://github.com/oracle/truffleruby/issues/3138") if truffleruby? + setup_symlinked_files if RUBY_VERSION >= "3.1" # Fixed in https://github.com/ruby/ruby/commit/79a4484a072e9769b603e7b4fbdb15b1d7eccb15 (Ruby 3.1) @@ -41,6 +43,8 @@ def test_require_symlinked_file_twice_aliased end def test_require_relative_symlinked_file_twice + skip("https://github.com/oracle/truffleruby/issues/3138") if truffleruby? + setup_symlinked_files if RUBY_VERSION >= "3.1" # Fixed in https://github.com/ruby/ruby/commit/79a4484a072e9769b603e7b4fbdb15b1d7eccb15 (Ruby 3.1) @@ -83,6 +87,8 @@ def test_require_relative_and_then_require_symlinked_file end def test_require_deep_symlinked_file_twice + skip("https://github.com/oracle/truffleruby/issues/3138") if truffleruby? + setup_symlinked_files if RUBY_VERSION >= "3.1" # Fixed in https://github.com/ruby/ruby/commit/79a4484a072e9769b603e7b4fbdb15b1d7eccb15 (Ruby 3.1) @@ -116,6 +122,8 @@ def test_require_deep_symlinked_file_twice_aliased end def test_require_relative_deep_symlinked_file_twice + skip("https://github.com/oracle/truffleruby/issues/3138") if truffleruby? + setup_symlinked_files if RUBY_VERSION >= "3.1" # Fixed in https://github.com/ruby/ruby/commit/79a4484a072e9769b603e7b4fbdb15b1d7eccb15 (Ruby 3.1) @@ -211,5 +219,9 @@ def setup_symlinked_files RUBY File.symlink("real", "symlink") end + + def truffleruby? + RUBY_ENGINE == "truffleruby" + end end end diff --git a/test/load_path_cache/cache_test.rb b/test/load_path_cache/cache_test.rb index bb1e8ec..27c161d 100644 --- a/test/load_path_cache/cache_test.rb +++ b/test/load_path_cache/cache_test.rb @@ -35,16 +35,21 @@ def test_builtin_features assert_equal false, cache.find("thread") assert_equal false, cache.find("thread.rb") assert_equal false, cache.find("enumerator") - assert_equal false, cache.find("enumerator.so") - if RUBY_PLATFORM =~ /darwin/ - assert_equal false, cache.find("enumerator.bundle") + if truffleruby? + assert_equal false, cache.find("enumerator.rb") else - assert_same FALLBACK_SCAN, cache.find("enumerator.bundle") + assert_equal false, cache.find("enumerator.so") + if RUBY_PLATFORM =~ /darwin/ + assert_equal false, cache.find("enumerator.bundle") + else + assert_same FALLBACK_SCAN, cache.find("enumerator.bundle") + end end bundle = RUBY_PLATFORM =~ /darwin/ ? "bundle" : "so" + # These are not present in TruffleRuby but that means they will still return falsey. refute(cache.find("thread.#{bundle}")) refute(cache.find("enumerator.rb")) refute(cache.find("encdb.#{bundle}")) @@ -165,9 +170,15 @@ def test_path_encoding require path internal_path = $LOADED_FEATURES.last assert_equal(OS_ASCII_PATH_ENCODING, internal_path.encoding) - assert_equal(OS_ASCII_PATH_ENCODING, path.encoding) + # TruffleRuby object is a copy and the encoding resets to utf-8. + assert_equal(OS_ASCII_PATH_ENCODING, path.encoding) unless truffleruby? File.write(path, "") - assert_same path, internal_path + + if truffleruby? + assert_equal path, internal_path + else + assert_same path, internal_path + end utf8_path = cache.find("béé") assert_equal("#{@dir1}/béé.rb", utf8_path) @@ -176,9 +187,20 @@ def test_path_encoding assert_equal(Encoding::UTF_8, internal_utf8_path.encoding) assert_equal(Encoding::UTF_8, utf8_path.encoding) File.write(utf8_path, "") - assert_same utf8_path, internal_utf8_path + + if truffleruby? + assert_equal utf8_path, internal_utf8_path + else + assert_same utf8_path, internal_utf8_path + end end end + + private + + def truffleruby? + RUBY_ENGINE == "truffleruby" + end end end end