sassc-ruby icon indicating copy to clipboard operation
sassc-ruby copied to clipboard

Windows gems do not install on JRuby

Open headius opened this issue 4 years ago • 17 comments

I will preface this by saying that sassc-ruby works great on JRuby as long as you have build tools available!

Of course this is a problem for all Rubies running on Windows, since most users do not have build tools there. To fix this, you started releasing binary gems in 2.1+.

Unfortunately, the way that RubyGems selects binary gems means that they will not install on JRuby. In order for JRuby to have its own binary gems, we have always set our RUBY_PLATFORM to "java", and you will see those gems out there with a -java suffix. When RubyGems attempts to install sassc on JRuby on Windows, it does not see a -java suffix, so it falls back to the non-platform gem... and we're back where we started trying to build on Windows.

The fix is actually fairly simple: we need either the base gem release or a new -java gem release to include all the binaries for Windows and select the correct one at install or runtime. Since you already have the logic to pre-build the libsass binaries, this is just a packaging/release issue.

We are standing by to help make this happen.

Thank you very much for using FFI for this gem... it makes JRuby support almost automatic.

headius avatar Feb 17 '20 23:02 headius

This is the underlying problem in rails/rails#38492.

headius avatar Feb 17 '20 23:02 headius

the loading problem on Windows is already fixed by https://github.com/sass/sassc-ruby/pull/173 but the change wasn't released yet.

You still need a devkit, we can't ship precompiled binaries for Linux until we have a solution to this ticket https://github.com/sass/sassc-ruby/issues/141

ping @larskanis @glebm ?

ahorek avatar Feb 18 '20 15:02 ahorek

@ahorek I don't know about this loading issue. If I'm understanding correctly, this would be a problem if you're able to build the binary on Windows... it won't load because it's trying to use a ".jar" extension?

We are fine without precompiled binaries if the library can be built. Precompiled binaries will never work for JRuby if they're only distributed in the platform-specific gems, since RubyGems will never select those versions on JRuby (or on TruffleRuby, since they now force platform to always be "ruby").

headius avatar Feb 18 '20 18:02 headius

sassc 2.2.1 has prebuilt binaries on Windows, but not for JRuby on Windows.

it was built correctly, but it can't be loaded because it attempts to load the .so extension. The correct extension on Windows is ".dll".

dl_ext = (RbConfig::CONFIG['host_os'] =~ /darwin/ ? 'bundle' : 'so')

the second problem is about different C libraries like MUSL on Alpine Linux. Nokogiri has a similar issue https://github.com/sparklemotion/nokogiri/pull/1990 and I think it applies to JRuby as well.

this is the reason why sassc don't ship prebuild binaries on Linux anymore, see https://github.com/sass/sassc-ruby/pull/145 but this is the only blocker. Other than that it's just about a configuration to also build a java version.

ahorek avatar Feb 18 '20 18:02 ahorek

JRuby's version of nokogiri does not use any native libraries, so that issue does not apply to us.

It sounds like the Windows binary gems don't work for CRuby either.

headius avatar Feb 18 '20 19:02 headius

nokogiri has its own java library, but sassc use ffi + c library

ahorek avatar Feb 18 '20 19:02 ahorek

Is there a way to target Windows + JRuby only? Won't the -java suffix also match on non-Windows?

glebm avatar Feb 18 '20 23:02 glebm

Is there a way to make an automatic fall back to a compilation in a single gem (platform "java") or separate those platforms somehow? If so, we can ship at least Windows binaries.

ahorek avatar Feb 19 '20 20:02 ahorek

There's no way to target just JRuby + Windows because RubyGems only supports a single platform per gem. We've lobbied for adding more dimensions to this platform selection, but no work has been done toward that end. So yes, the -java gem will be selected on all platforms if that's the direction we go.

The options I see right now are:

  • Ship a -java gem that also includes prebuilt binaries for Windows. If it's installed on Windows, use the binaries; otherwise build them.
  • Ship the Windows binaries as part of the platformless gem and do the same thing as above. This avoids the need for separate binary gems for Windows but doesn't scale with many platforms.
  • Ship a single separate gem that contains binaries for all supported platforms, and have the platformless gem use that to pick a binary or build at install time.

Note also that TruffleRuby now forces its platform to always be "ruby" in terms of gems, so it won't pick up native binaries either. So the binary gems as they stand will only ever be installed when using CRuby.

headius avatar Feb 19 '20 23:02 headius

This issue still exists today, jruby (9.2.13.0) and Rails (6.0.3.4), on Windows 10

linojon avatar Nov 11 '20 19:11 linojon

I have some things to report which might help (anyway, I am seeking answers as well).

Setup:

  • CRuby 2.6.6 with DevKit
  • JRuby 9.2.18.0
  • SassC 2.4.0
  • Windows 10
  • pik is used to switch between Ruby versions

I was able to install sassc-2.4.0 into my JRuby installation by making sure that I enabled the DevKit before doing the installation. I posted this here: https://notepad.onghu.com/2021/ruby-tricks-009-jruby-sassc-installation-error/

However, I have a new problem.

When I start jirb and did require sassc it fails with an error:

       16: from org/jruby/RubyKernel.java:1189:in `catch'
       15: from org/jruby/RubyKernel.java:1189:in `catch'
       14: from org/jruby/RubyKernel.java:1442:in `loop'
       13: from org/jruby/RubyKernel.java:1048:in `eval'
       12: from (irb):1:in `evaluate'
       11: from C:/jruby-9.2.18.0/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:158:in `require'
       10: from org/jruby/RubyKernel.java:974:in `require'
        9: from C:/jruby-9.2.18.0/lib/ruby/gems/shared/gems/sassc-2.4.0/lib/sassc.rb:31:in `<main>'
        8: from org/jruby/RubyKernel.java:1002:in `require_relative'
        7: from org/jruby/RubyKernel.java:974:in `require'
        6: from C:/jruby-9.2.18.0/lib/ruby/gems/shared/gems/sassc-2.4.0/lib/sassc/native.rb:5:in `<main>'
        5: from C:/jruby-9.2.18.0/lib/ruby/gems/shared/gems/sassc-2.4.0/lib/sassc/native.rb:6:in `<module:SassC>'
        4: from C:/jruby-9.2.18.0/lib/ruby/gems/shared/gems/sassc-2.4.0/lib/sassc/native.rb:13:in `<module:Native>'
        3: from C:/jruby-9.2.18.0/lib/ruby/stdlib/ffi/library.rb:84:in `ffi_lib'
        2: from org/jruby/RubyArray.java:2588:in `map'
        1: from C:/jruby-9.2.18.0/lib/ruby/stdlib/ffi/library.rb:114:in `block in ffi_lib'
Could not open library 'C:/jruby-9.2.18.0/lib/ruby/gems/shared/gems/sassc-2.4.0/ext/libsass.dll' : The operation completed successfully.

I checked - the DLL file is actually at the correct place. So, that's not it.

Finally... I found that it works if the DevKit is still on the path. So, when I have this as my path, I have no problems.

PATH=C:\jruby-9.2.18.0\bin;C:\Ruby26-x64\msys64\mingw64\bin;C:\Ruby26-x64\msys64\usr\bin;___other_stuff

Hope this helps. Happy to help you check something if it helps. It feels like we are close :)

mohits avatar Jun 09 '21 15:06 mohits

@mohits Thanks for the follow-up! Perhaps it is linking to some library (e.g. libc bridge or something) in the devkit that is not always on your path? Glad to hear that it at least can work with devkit installed but it really should be able to use the pre-built dll.

headius avatar Jun 15 '21 19:06 headius

hi @headius - as @ahorek has identified in https://github.com/sass/sassc-ruby/pull/224 the issue is related to LINWINPTHREAD-1.DLL and related dependencies. Adding just C:\Ruby26-x64\msys64\mingw64\bin to the PATH works around it since the necessary files are on the path then. Once that pull request goes through, I expect that it would eventually work fine.

Good!

mohits avatar Jun 16 '21 17:06 mohits

@mohits devkit is still necessary for the installation, this wasn't fixed, but after the installation, you'll be able to use sassc without a devkit available.

btw you don't have to adjust paths manually, just run ridk enable it should do the trick.

ahorek avatar Jun 16 '21 18:06 ahorek

Hi @ahorek - thanks! I have to adjust paths (a bit) because I use pik which takes the Ruby that you're not using off the path. That sadly means that ridk enable does not work since it uses Ruby itself. But I will clean up the instructions anyway to indicate:

  • Need devkit for installation
  • Don't need devkit on path for running it

Thanks for keeping Windows and JRuby support as a priority. I'm trying to maintain notes for problems people face with RubyOnWindows and JRuby and I appreciate you helping to ssolve these problems on Windows & JRuby.

mohits avatar Jun 17 '21 01:06 mohits

So checking on status here... with #224 the devkit is no longer required at runtime, but is still required to install (naturally).

The other path we need to explore is how to structure the gems so that the prebuilt Windows binaries could be downloaded and installed for JRuby users. RubyGems will not select platform gems since our platform is java but if a java gem were pushed it could work like this:

  • Includes the win32 prebuilt dlls
  • Modify the ext build to start with Rake, since rake will be available everywhere but make might not be (without devkit)
  • On non-Windows, build normally
  • On Windows, just use the existing dlls. The rake ext build would be a no-op.

That would eliminate the need for JRuby users on Windows to have devkit installed.

headius avatar Jun 30 '21 16:06 headius

Modify the ext build to start with Rake

It may already be this way... I just remember this being an issue with e.g. io-console since even a dummy Makefile would force make to be installed.

headius avatar Jun 30 '21 16:06 headius