gem 在 Cygwin 中不起作用

gem 在 Cygwin 中不起作用

在新安装的 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.dllC:\Windows\System32from复制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")

要解决该问题,请尝试以下操作:

  1. devkit运行时需要extconf.rb如下:ruby -rdevkit extconf.rb,或者只需添加require "devkit"extconf.rb然后正常运行脚本。
  2. 运行devkitvars.batdevkit 中的脚本,PATH在编译之前配置工具链。

相关内容