github
Advanced Search
  • Home
  • Pricing and Signup
  • Explore GitHub
  • Blog
  • Login

luislavena / rake-compiler

  • Admin
  • Watch Unwatch
  • Fork
  • Your Fork
  • Pull Request
  • Download Source
    • 94
    • 14
  • Source
  • Commits
  • Network (14)
  • Issues (6)
  • Downloads (10)
  • Wiki (3)
  • Graphs
  • Branch: master

click here to add a description

click here to add a homepage

  • Branches (2)
    • integration
    • master ✓
  • Tags (10)
    • v0.7.0
    • v0.6.0
    • v0.5.0
    • v0.4.1
    • v0.4.0
    • v0.3.1
    • v0.3.0
    • v0.2.1
    • v0.1.1
    • v0.1.0
Sending Request…
Enable Donations

Pledgie Donations

Once activated, we'll place the following badge in your repository's detail box:
Pledgie_example
This service is courtesy of Pledgie.

Provide a standard and simplified way to build and package Ruby C and Java extensions using Rake as glue. — Read more

  cancel

http://rake-compiler.rubyforge.org

  cancel
  • Private
  • Read-Only
  • HTTP Read-Only

This URL has Read+Write access

Updated history to reflect fork queue commits. 
luislavena (author)
Tue Dec 29 13:47:12 -0800 2009
commit  32d062d6ad1fdbebe7621a11e7a1e0d8723991bc
tree    b5c99de9d7c17fd3d35cbbfce7854bb3d0bbe294
parent  93bee08c161063ac294ef4756bbe1fb543917be7
rake-compiler /
name age
history
message
file .gitignore Sun Aug 23 13:12:27 -0700 2009 ignore vim swapfiles [flori]
file History.txt Tue Dec 29 13:47:12 -0800 2009 Updated history to reflect fork queue commits. [luislavena]
file LICENSE.txt Thu Nov 06 20:35:02 -0800 2008 Added RDoc tasks and updated gem specifications... [luislavena]
file README.rdoc Sun Dec 06 19:06:40 -0800 2009 Start adding documentation for Java to README ... [myabc]
file Rakefile Mon Dec 15 14:29:02 -0800 2008 Make tasks loading works with different OS. Al... [luislavena]
directory bin/ Fri Nov 28 04:42:58 -0800 2008 Renamed cross-ruby rake tasks. [luislavena]
file cucumber.yml Sun Dec 06 19:02:19 -0800 2009 Sync Java compilation scenarios Merged Java co... [myabc]
directory features/ Mon Dec 07 14:02:05 -0800 2009 Fix handling of jar command line arguments * P... [myabc]
directory lib/ Sun Dec 13 01:47:51 -0800 2009 Silence make program lookup [luislavena]
directory spec/ Tue Dec 29 13:44:21 -0800 2009 bugfix for issue 15 [luisparravicini]
directory tasks/ Tue Dec 29 13:44:32 -0800 2009 Update gem manifest. Closes GH-14 Include miss... [luislavena]
README.rdoc

rake-compiler

rake-compiler aims to help Gem developers deal with Ruby extensions, simplifying code and reducing duplication.

It followss *convention over configuration* and sets a standardized structure to build and package both C and Java extensions in your gems.

This is the result of experiences dealing with several Gems that required native extensions across platforms and different user configurations where details like portability and clarity of code were lacking.

An Overview

Let’s summarize what rake-compiler provides:

  • No custom rake tasks required. Less code duplication and errors.
  • Painlessly build extensions on different platforms (Linux, OSX and Windows).
  • Painlessly build extensions for different Ruby implementations (JRuby, Rubinius and MRI).
  • Allow multiple extensions be compiled inside the same gem.
  • Mimics RubyGems installation process, so helps as a test environment.
  • Simplify cross platform compilation of extensions (target Windows from Linux).

I’m sold! show me how to use it! (Installation)

Usage of rake-compiler is pretty much straight forward.

First, you need to install the gem:

  $ gem install rake-compiler

Now what? (Usage)

Now that you have the gem installed, let’s give your project some structure.

Structure

Let’s say we want to compile an extension called ‘hello_world’, so we should organize the code and folders that will help rake-compiler do its job:

    |-- ext
    |   `-- hello_world
    |       |-- extconf.rb
    |       |-- HelloWorldService.java
    |       `-- hello_world.c
    |-- lib
    `-- Rakefile

TIP: Having a consistent folder structure will help developers and newcomers to find code and also contribute back to your project more easily.

Adding the code

So now it’s time to introduce the code to compile our extension:

    # File: Rakefile

    require 'rake/extensiontask'

    Rake::ExtensionTask.new('hello_world')

Ok, that’s it. No other line of code.

If we wanted to do the same for a JRuby extension (written in Java):

    # File: Rakefile

    require 'rake/javaextensiontask'

    Rake::JavaExtensionTask.new('hello_world')

Compile process

Those two lines of code automatically added the needed rake tasks to build the hello_world extension. Running Rake on 1.8.x/1.9 (MRI):

  $ rake -T
  (in /home/user/my_extension)
  rake compile                # Compile the extension(s)
  rake compile:hello_world    # Compile just the hello_world extension

Simply calling compile:

  $ rake compile

Will do all the compile process for us, putting the result extension inside lib directory.

NOTE: Please be aware that building C extensions requires the proper development environment for your Platform, which includes libraries, headers and build tools. Check your distro / vendor documentation on how to install it.

NOTE: Building Java extensions requires the javac, part of the Java Development Kit (JDK). This should be included by default on Mac OS X, and downloadable from java.sun.com for other operating systems.

Generate native gems

A common usage scenario of rake-compiler is generate native gems that bundles your extensions.

This got over-simplified with Rake::ExtensionTask:

    # somewhere in your Rakefile, define your gem spec
    spec = Gem::Specification.new do |s|
      s.name = "my_gem"
      s.platform = Gem::Platform::RUBY
      s.extensions = FileList["ext/**/extconf.rb"]
    end

    # add your default gem packing task
    Rake::GemPackageTask.new(spec) do |pkg|
    end

    # feed your ExtensionTask with your spec
    Rake::ExtensionTask.new('hello_world', spec)

Now, as usual, you can build your pure-ruby gem (standard output):

  $ rake gem
  (in /projects/oss/my_gem.git)
  mkdir -p pkg
    Successfully built RubyGem
    Name: my_gem
    Version: 0.1.0
    File: my_gem-0.1.0.gem
  mv my_gem-0.1.0.gem pkg/my_gem-0.1.0.gem

Plus, you have the functionality to build native versions of the gem:

  # rake native gem
  (... compilation output ...)
  mkdir -p pkg
    Successfully built RubyGem
    Name: my_gem
    Version: 0.1.0
    File: my_gem-0.1.0.gem
  mv my_gem-0.1.0.gem pkg/my_gem-0.1.0.gem
    Successfully built RubyGem
    Name: my_gem
    Version: 0.1.0
    File: my_gem-0.1.0-x86-mingw32.gem
  mv my_gem-0.1.0-x86-mingw32.gem pkg/my_gem-0.1.0-x86-mingw32.gem

You get two gems for the price of one.

And the same for JRuby extensions:

  # rake java gem
  (... compilation output ...)
  mkdir -p pkg
    Successfully built RubyGem
    Name: my_gem
    Version: 0.1.0
    File: my_gem-0.1.0.gem
  mv my_gem-0.1.0.gem pkg/my_gem-0.1.0.gem
    Successfully built RubyGem
    Name: my_gem
    Version: 0.1.0
    File: my_gem-0.1.0-java.gem
  mv my_gem-0.1.0-java.gem pkg/my_gem-0.1.0-java.gem

What about breaking the standards? (Customization)

In case you want to bend the convention established, rake-compiler let you personalize several settings for Rake::ExtensionTask:

    Rake::ExtensionTask.new do |ext|
      ext.name = 'hello_world'                # indicate the name of the extension.
      ext.ext_dir = 'ext/weird_world'         # search for 'hello_world' inside it.
      ext.lib_dir = 'lib/my_lib'              # put binaries into this folder.
      ext.config_script = 'custom_extconf.rb' # use instead of 'extconf.rb' default
      ext.tmp_dir = 'tmp'                     # temporary folder used during compilation.
      ext.source_pattern = "*.{c,cpp}"        # monitor file changes to allow simple rebuild.
      ext.config_options << '--with-foo'      # supply additional configure options to config script.
      ext.gem_spec = spec                     # optional indicate which gem specification
                                              # will be used to based on.
    end

Future is now: Cross compilation

rake-compiler provides now an standardized way to generate, from Linux or OSX both extensions and gem binaries for Windows!

It takes advantages from GCC host/target to build binaries (for target) on different OS (hosts).

How I enjoy this?

Besides having the development tool chain installed (GCC), you should install also mingw32 cross compilation package.

Installation depends will depend on your operating system/distribution. On Ubuntu and Debian machines, a simple apt-get install mingw32 will be enough.

On OSX, mingw32 is available via MacPorts: port install i386-mingw32-gcc (ensure you update your ports tree before hand as mingw32 has been been broken).

I have my tool-chain, now what?

You need to build Ruby for Windows.

Relax, no need to freak out! Let rake-compiler do it for you:

  rake-compiler cross-ruby

And you’re done. It will automatically download, configure and compile latest stable version of Ruby for Windows, and place it into ~/.rake-compiler

If, instead, you want to build another version than the default one, please supply a VERSION:

  rake-compiler cross-ruby VERSION=1.8.6-p114

Let’s build some gems!

Now, you only need to use additional options in your extension definition:

    Rake::ExtensionTask.new('my_extension', gem_spec) do |ext|
      ext.cross_compile = true                # enable cross compilation (requires cross compile toolchain)
      ext.cross_platform = 'i386-mswin32'     # forces the Windows platform instead of the default one
                                              # configure options only for cross compile
      ext.cross_config_options << '--with-something'

      # perform alterations on the gemspec when cross compiling
      ext.cross_compiling do |gem_spec|
        gem_spec.post_install_message = "You installed the binary version of this gem!"
      end
    end

By default, cross compilation targets ‘i386-mingw32’ which is default GCC platform for Ruby.

To target gems for current Ruby official distribution, please force the platform to the one shown before.

Magician doing some tricks, don’t blink!

Compiles keeps being simple:

  rake cross compile

And now, build your gems for Windows is just 5 more letters:

  rake cross native gem

And you’re done, yeah.

Take it even further

You can specify against with version of Ruby you want to build the extension:

  rake cross compile RUBY_CC_VERSION=1.8.6

If you installed 1.9.1, you can do:

  rake cross compile RUBY_CC_VERSION=1.9.1

Even more, you can target multiple versions (ie. 1.8.6 and 1.9.1):

  rake cross compile RUBY_CC_VERSION=1.8.6:1.9.1

And more exiting, bundle both binaries in one "fat" Gem:

  rake cross native gem RUBY_CC_VERSION=1.8.6:1.9.1

That will place binaries for 1.8 and 1.9 versions of ruby inside lib_dir

  lib/1.8/my_extension.so
  lib/1.9/my_extension.so

Now is up to you to make your gem load the proper one ;-)

Future

rake-compiler is a work in progress and we will appreciate feedback during the development of it! (and contributions too!)

You can find more information about rake-compiler:

Blog: blog.mmediasys.com RubyForge: rubyforge.org/projects/rake-compiler GitHub: github.com/luislavena/rake-compiler

Disclaimer

If you have any trouble, don’t hesitate to contact the author. As always, I’m not going to say "Use at your own risk" because I don’t want this library to be risky.

If you trip on something, I’ll share the liability by repairing things as quickly as I can. Your responsibility is to report the inadequacies.

Blog | Support | Training | Contact | API | Status | Twitter | Help | Security
© 2010 GitHub Inc. All rights reserved. | Terms of Service | Privacy Policy
Powered by the Dedicated Servers and
Cloud Computing of Rackspace Hosting®
Dedicated Server