4

On a freshly installed Windows 7 Professional 64 Bit I installed Cygwin (64) and some of its packages, including Ruby. I have also installed Ruby using the Ruby installer, because I'll likely need it for both the default Windows shells and Cygwin.

Now when I try to execute a gem command like gem list or gem install foo, I get a weird error I failed to solve within the last few hours of searching the internet.

$ which ruby
/usr/bin/ruby

$ which gem
/usr/bin/gem

$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-cygwin]

$ gem -v
2.4.8

$ gem list
ERROR:  Loading command: list (Fiddle::DLError)
        can't load kernel32
ERROR:  While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass

$ gem install sass
ERROR:  Loading command: install (Fiddle::DLError)
        can't load kernel32
ERROR:  While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass

However, with the native Windows version, from the Windows CMD, it works without any problems. I cannot however use native Windows Ruby stuff from Cygwin, because that gives me errors, but that's not the question here anyway.

With Process Monitor I figured out that Ruby tries to open C:\cygwin64\bin\kernel32.dll and fails, because that file is not there. I tried copying the kernel32.dll from C:\Windows\System32 and the one from C:\Windows\SysWOW64 into that Cygwin bin folder and still got the same error (apart from that it then said can't load kernel32.dll), although the Process Monitor didn't show a NAME NOT FOUND error anymore.

What magic is happening here? I'd really like to understand what's wrong here. I appreciate any help.

3

It seems a unexpected result of cygwin 2.5.2 release

https://www.cygwin.com/ml/cygwin/2016-06/msg00378.html

As workaround, downgrade cygwin package to 2.5.1

  • Problem solved cygwin.com/ml/cygwin-announce/2016-06/msg00054.html – matzeri Jun 28 '16 at 7:59
  • "Problem solved" That only fixes the problem when you install Ruby through the Cygwin installer, right? I'm getting this error while trying to install via RVM, so I guess my only option is to downgrade Cygwin. – Ajedi32 Jul 13 '16 at 16:58
  • If ruby is not installed with "Cygwin installer" than is not a a cygwin programs and I do not see why it should care about cygwin dll loader. – matzeri Jul 14 '16 at 6:11
  • RVM works by downloading and compiling Ruby from source. So if you're running it in a Cygwin environment, then the resulting binaries will be a "Cygwin program". Anyway, downgrading Cygwin to 2.5.1 did resolve my problem. – Ajedi32 Jul 14 '16 at 13:00
  • @Ajedi32, in case this is still a problem for you, I posted an answer for RVM installed rubies below. I didn't really want to downgrade my Cygwin version! – zelanix Aug 6 '16 at 8:06
6

A way to fix this without changing the rvm build process is:

ln -s /cygdrive/c/Windows/System32/kernel32.dll /usr/lib/kernel32

This happens because ruby is looking for a shared library named simply kernel32. Cygwin 2.5.1 and earlier automatically added the ".dll" extension to shared library loads. But cygwin 2.5.2 introduced a patch requiring full shared library filenames. Adding a symbolic link within the library search path (/usr/lib) allows the library to be found even when loaded with the old-style name.

  • 1
    +1 IMHO this solution is the neatest as there is no need to edit the resolv.rb. Worked with Cygwin 2.6.0 and rbenv – edwardsmatt Nov 24 '16 at 7:04
4

I installed ruby using rvm so the updated Cygwin ruby binaries weren't much help and I didn't really want to downgrade my Cygwin installation - how would I know when it was safe to upgrade again?

Following the information in Michael D's answer, the problem appears to be in the resolv.rb file located in ~\.rvm\rubies\ruby-<version>\lib\ruby\<version>\win32 (in my case ~\.rvm\rubies\ruby-2.1.7\lib\ruby\2.1.0\win32).

Somewhere near the top of this file, there is the code

module Kernel32
  extend Importer
  dlload "kernel32"
end

Simply changing the dlload "kernel32" line to dlload "kernel32.dll" seemed to fix it for me. Alternatively using the full path

dlload "c:/Windows/System32/kernel32.dll"

also worked, but it seems to be the extension that is the crucial bit (the full path without the extension also doesn't work).

This may have been fixed in a more recent version of rvm, but I didn't want to go through the hassle of updating and reinstalling, so this works for me. Or course this would likely need to be changed for all installed rubies.

  • The problem is solved since 28 June. I don't recommend using an rvm installation from Cygwin. I only had problems with that, at the latest when gems need to be compiled. And I don't see any problems with the Cygwin version (apart from this one, which has been fixed and could be workarounded easily). – Neon Aug 6 '16 at 7:24
  • 1
    @Neon, well I prefer to use rvm so that I can easily test different ruby versions and use gemsets so for me the problem was not solved, but each to their own. – zelanix Aug 6 '16 at 8:02
  • Also, cygwin doesn't provide the latest ruby versions. For example 2.3.1 is not available in the repos. Also, there are projects that use rvm specifically, to properly manage the ruby version which is used. – Timotei Oct 15 '16 at 10:36
2

The Ruby package has problem loading native libraries (at least kernel32.dll). The problem comes from a call to dns.getresource("_rubygems._tcp.#{host}", Resolv::DNS::Resource::IN::SRV) which probably make a native call to kernel32.dll hence loading the kernel32.dll library.

If you specify the full path to the library, it will work correctly.

kernel = Fiddle::Handle.new("c:/Windows/System32/kernel32.dll")

To solve the issue, try the following:

  1. Require devkit when running extconf.rb as follows: ruby -rdevkit extconf.rb , or just adding require "devkit" to extconf.rb then running the script normally.
  2. Run the devkitvars.bat script from the devkit to configure the PATH with the toolchain before compiling.
  • 1
    I don't quite get what you want me to do. I'm just using gem, no scripts from my side. So I'm not able to specify a full path and I don't know what's the extconf.rb is nor how or when to use it. I'm also not compiling anything. Please give some further instructions so I can test what you advised. – Neon Jun 27 '16 at 14:02
  • To know more about extconf.rb please refer here. To check the loading of kernel32.dll try to use this script. – Michael D Jun 27 '16 at 14:08
  • I am sorry, I seem to have attached the same link twice, here's the script I spoke about in the previous comment. – Michael D Jun 27 '16 at 20:21

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.