在新安装的 Windows 7 Professional 64 位上,我安装了 Cygwin (64) 及其一些软件包,包括 Ruby。我还使用 Ruby 安装程序安装了 Ruby,因为我可能需要它用于默认的 Windows shell 和 Cygwin。
现在,当我尝试执行gem
类似gem list
或的命令时gem install foo
,我收到一个奇怪的错误,我在网上搜索后的最后几个小时内都无法解决它。
$ 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
但是,使用 Windows 原生版本,从 Windows CMD 运行,没有任何问题。但是我不能使用 Cygwin 原生的 Windows Ruby 内容,因为这会出错,但这不是这里的问题。
使用 Process Monitor,我发现 Ruby 尝试打开C:\cygwin64\bin\kernel32.dll
但失败了,因为该文件不存在。我尝试将 fromkernel32.dll
和C:\Windows\System32
from复制C:\Windows\SysWOW64
到 Cygwinbin
文件夹中,但仍然出现相同的错误(除了它随后说无法加载 kernel32.dll),尽管进程监视器不再显示NAME NOT FOUND
错误。
这里发生了什么神奇的事情?我真的很想知道这里出了什么问题。我很感激任何帮助。
答案1
这似乎是 cygwin 2.5.2 发布的意外结果
https://www.cygwin.com/ml/cygwin/2016-06/msg00378.html
作为解决方法,将 cygwin 包降级到 2.5.1
答案2
解决此问题而不改变 rvm 构建过程的方法是:
ln -s /cygdrive/c/Windows/System32/kernel32.dll /usr/lib/kernel32
发生这种情况的原因是 ruby 正在寻找一个名为 的共享库kernel32
。Cygwin 2.5.1 及更早版本会自动将“.dll”扩展名添加到共享库加载中。但 cygwin 2.5.2 引入了一个补丁,要求提供完整的共享库文件名。在库搜索路径 ( /usr/lib
) 中添加符号链接,即使使用旧式名称加载,也可以找到该库。
答案3
我使用 rvm 安装了 ruby,因此更新的 Cygwin ruby 二进制文件没有太大帮助,而且我并不想降级我的 Cygwin 安装——我怎么知道何时可以安全地再次升级?
根据 Michael D 的回答中的信息,问题似乎出resolv.rb
在~\.rvm\rubies\ruby-<version>\lib\ruby\<version>\win32
(就我而言~\.rvm\rubies\ruby-2.1.7\lib\ruby\2.1.0\win32
)的文件中。
在这个文件的顶部附近,有一段代码
module Kernel32
extend Importer
dlload "kernel32"
end
只需将dlload "kernel32"
行更改为dlload "kernel32.dll"
似乎就可以解决这个问题。或者使用完整路径
dlload "c:/Windows/System32/kernel32.dll"
也有效,但扩展名似乎是关键部分(没有扩展名的完整路径也不起作用)。
这可能已在较新版本的 rvm 中修复,但我不想经历更新和重新安装的麻烦,所以这对我来说很管用。当然,这可能需要对所有已安装的 ruby 进行更改。
答案4
Ruby 包在加载本机库(至少是 kernel32.dll)时出现问题。问题来自对 的调用,该调用dns.getresource("_rubygems._tcp.#{host}", Resolv::DNS::Resource::IN::SRV)
可能会对 进行本机调用,kernel32.dll
因此会加载kernel32.dll
库。
如果您指定库的完整路径,它将正常工作。
kernel = Fiddle::Handle.new("c:/Windows/System32/kernel32.dll")
要解决该问题,请尝试以下操作:
devkit
运行时需要extconf.rb
如下:ruby -rdevkit extconf.rb
,或者只需添加require "devkit"
到extconf.rb
然后正常运行脚本。- 运行
devkitvars.bat
devkit 中的脚本,PATH
在编译之前配置工具链。