问题描述
我找不到很多关于此的文档.如何打包 gem,以便在安装 gem 时编译 C 扩展?
I can't find many docs on this. How do I package a gem such that the C extension is compiled when the gem is installed?
我特别想这样做:
在 Linux 和 MacOSX 上我想在 gem install 上编译 C 扩展
on Linux and MacOSX i would like compile the C extension on gem install
在 Windows 上我想简单地安装一个预编译的 .so
on Windows I would like to simply install a precompiled .so
对此的任何帮助,尤其是示例源,都会非常有用:)
any help on this, in particular example source, would be very useful :)
推荐答案
Luis Lavena 创建了 rake-compiler
就是为了这个目的.
Luis Lavena has created rake-compiler
just for this purpose.
但是,您确定需要 C 扩展吗?关于 C 扩展的事情是每个 Ruby 实现都有自己的 C 扩展 API(而基于非 C 的扩展 API,如 XRuby、JRuby、Ruby.NET、IronRuby、HotRuby、MagLev、Red Sun 根本没有),这意味着您的 C 扩展仅适用于 one 实现.而且,由于 MRI only 实现了 Ruby 1.8 而 YARV only 实现了 Ruby 1.9,而我们目前正处于 1.8 和 1.9 之间的过渡阶段,很可能很多人会至少使用两种不同的实现.(我个人使用 5 个:MRI、YARV、JRuby、IronRuby 和 Rubinius.)
However, are you sure that you need a C extension? The thing about C extensions is that every Ruby implementation has their own C extension API (and non-C based ones like XRuby, JRuby, Ruby.NET, IronRuby, HotRuby, MagLev, Red Sun don't have one at all), which means that your C extension will only work on one implementation. And, since MRI only implements Ruby 1.8 and YARV only implements Ruby 1.9, and we are currently in a transition phase between 1.8 and 1.9, chances are that a lot of people will use at least two different implementations. (I personally use 5: MRI, YARV, JRuby, IronRuby and Rubinius.)
也许你最好使用 Ruby-FFI.Ruby-FFI 是 Ruby (duh) 的 FFI(外部函数接口),它允许您以可跨 Ruby 实现移植的方式绑定和映射纯 Ruby 中的 C 库.FFI API 最初由 Evan Phoenix 开发,作为 Rubinius,随后被 Charles Oliver Nutter 采用(由 Wayne Meissner 实现)用于 JRuby.Wayne 然后也写了 Ruby-FFI gem,其中包含 MRI 和 YARV 的 C 扩展.Laurent Sansonetti 为 MacRuby,Marc-André Cournoyer 的 tinyrb 也 支持 FFI(再次由 Wayne Meissner 编写)和 MagLev 的开发者也在努力.这意味着,如果您可以让您的库使用 FFI 而不是 C 扩展,您将自动支持 6 种 Ruby 实现,而不仅仅是一种.
Maybe you are better off using Ruby-FFI. Ruby-FFI is an FFI (Foreign Function Interface) for Ruby (duh), which allows you to bind to and map C libraries in pure Ruby in a manner that is portable across Ruby implementations. The FFI API was first developed by Evan Phoenix as the native extension API for Rubinius, it was then adopted by Charles Oliver Nutter (and implemented by Wayne Meissner) for JRuby. Wayne then also wrote the Ruby-FFI gem, which contains C extensions for MRI and YARV. Laurent Sansonetti implemented Ruby-FFI for MacRuby, Marc-André Cournoyer's tinyrb also supports FFI (again written by Wayne Meissner) and the MagLev developers are also working on it. Which means that if you can make your library work with FFI as opposed to a C extension, you will automatically support 6 Ruby implementations instead of just one.
使用 C 扩展而不是 FFI 扩展的唯一原因是,如果您真的确实想要一些特定于实现的行为.这方面的一个例子是 ParseTree 宝石,它深入到 MRI 的肠道并撕下- 解析树的内存表示.
The only reason to use a C extension as opposed to an FFI extension would be, if you really do want some implementation specific behavior. One example of this would be the ParseTree gem, which reaches deep into the intestines of MRI and rips out the in-memory representation of the parse tree.
最后但同样重要的是,看看 Nice-FFI 项目由 John Croisant,旨在使用 Ruby-FFI 更好.
Last but not least, take a look at the Nice-FFI project by John Croisant, which aims to make using Ruby-FFI even nicer.
这篇关于如何在 Ruby Gem 中封装 Ruby C 扩展?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!