如何添加 (pre/post)_install_hook 到 ruby 宝石

How to add a (pre/post)_install_hook to ruby gems

我想在安装前使用 gem install some-gem 之类的命令从 rubygems.org 安装 gem 时执行一些代码。

文档指出您可以使用如下所示的 http://docs.ruby-lang.org/en/2.2.0/Gem.html pre_install 挂钩:

# File lib/rubygems.rb, line 724
def self.pre_install(&hook)
  @pre_install_hooks << hook
end

文档进一步指出:

RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging RubyGems or implementing Ruby you can change RubyGems' defaults. For RubyGems packagers, provide lib/rubygems/defaults/operating_system.rb and override any defaults from lib/rubygems/defaults.rb. For Ruby implementers, provide lib/rubygems/defaults/#{RUBY_ENGINE}.rb and override any defaults from lib/rubygems/defaults.rb. If you need RubyGems to perform extra work on install or uninstall, your defaults override file can set pre and post install and uninstall hooks. See ::pre_install, ::pre_uninstall, ::post_install, ::post_uninstall.

这听起来正是我想要的。所以我创建了文件

然后我输入代码

Gem.pre_install { puts 'pre install hook called!' }

在所有列出的文件中。然后我将它们添加到 gemspec 中的 require_paths 中,如下所示:

s.require_paths = ["lib", "test", "rubygems"]

但是我在安装 gem 时在终端中没有看到任何输出。

我做错了什么?

目前的答案是 (2015-11-11) 不,您不能在安装时针对特定 gem 执行任意代码 。您问题中提到的钩子供 RubyGem 安装程序本身使用,而不是 gem 特定的。请参阅:How can I make a Ruby gem package copy files to arbitrary locations? 了解更多详细信息。

这些文件:

lib/rubygems/defaults/defaults.rb
lib/rubygems/defaults/operating_system.rb
rubygems/defaults.rb

不是从您的 gem 目录中调用的。它们位于 RubyGems 系统位置。

如果您希望在安装之前对每个 gem 执行相同的代码,那么您可以使用 pre_install 挂钩,方法是将代码放在 /usr/lib64/ruby/2.2.0/rubygems/defaults.rb 或您的Ruby 已安装在您的系统上。 operating_system.rb 文件也将从同一位置加载。

您可以向 gem 添加本机扩展。

gem规格:s.extensions << 'path/to/extconf.rb'

但是 gem install 命令想要在安装时执行 Makefile。

因此 extconf.rb 必须创建一个虚拟 Makefile:

dummy_make_content = "make:\n" \
                     "\t:\n" \
                     "install:\n" \
                     "\t:\n" \
                     "clean:\n" \
                     "\t:\n"
File.write('Makefile', dummy_make_content)

或者您可以要求 mkmf 包并使用预定义函数:

require 'mkmf'
create_makefile ''