【发布时间】:2013-06-28 16:17:42
【问题描述】:
我正在开发一个 gem,它目前是纯 Ruby,但我也一直在为其中一个特性开发一个更快的 C 变体。该功能在纯 Ruby 中可用,但有时速度较慢。缓慢只会影响一些潜在用户(取决于他们需要哪些功能,以及他们如何使用它们),因此如果 gem 无法在目标系统上编译,它可以优雅地回退到仅 Ruby 的功能是有意义的。
我想在单个 gem 中维护该功能的 Ruby 和 C 变体,并在安装 gem 时提供最佳(即最快)体验。这将使我能够从我的一个项目中支持最广泛的潜在用户。它还允许其他人的依赖 gem 和项目使用目标系统上的最佳可用依赖项,而不是为了兼容性而使用最低公分母版本。
我希望require 在运行时回退到出现在主lib/foo.rb 文件中,就像这样:
begin
require 'foo/foo_extended'
rescue LoadError
require 'foo/ext_bits_as_pure_ruby'
end
但是,我不知道如何让 gem 安装检查(或尝试失败)本机扩展支持,以便 gem 正确安装,无论它是否可以构建“foo_extended”。当我研究如何做到这一点时,我主要发现了几年前的讨论,例如http://permalink.gmane.org/gmane.comp.lang.ruby.gems.devel/1479 和 http://rubyforge.org/pipermail/rubygems-developers/2007-November/003220.html 暗示 Ruby gem 并不真正支持此功能。不过最近没有什么,所以我希望 SO 上的某个人有一些最新的知识?
我的理想解决方案是在尝试构建扩展之前检测目标 Ruby 不支持(或者在项目级别可能根本不想要)C 本机扩展。但是,如果不太脏,try/catch 机制也可以。
这可能吗,如果可以,怎么办?或者是我在搜索时发现的发布两个 gem 变体(例如 foo 和 foo_ruby)的建议,仍然是当前的最佳实践吗?
【问题讨论】:
-
@Stefan:在我链接的对话中,
json和json_pure的作者/维护者显然更喜欢它。除了发布 gem 的两个变体的额外工作外,依赖项目本身可能是其他东西的依赖项,最终不得不使用最低公分母,或者还必须提供两个变体来管理他们不编码的依赖项.我不会称其为“很好”,但如果这是最好的,那我也能做到 -
@Stefan:OP中体现的Neil的设计意图肯定是对的。他的问题很好也很重要,我自己对答案很感兴趣,请点赞。
-
这个我也很感兴趣,这个问题真的很重要。
标签: ruby gem ruby-c-extension