← Blog

OCRAN: Turn Ruby Scripts into Executables for Windows, Linux and macOS

I maintain OCRAN, a Ruby gem that packages Ruby applications for distribution. It bundles your script, the Ruby interpreter, your gems and the native libraries they need into a self-contained artifact, so people can run your program without installing Ruby. Since version 1.4 it works on Windows, Linux and macOS.

OCRAN stands for “One-Click Ruby Application Next”. In this post I explain where it comes from, how to use it, and what changed recently.

From OCRA to OCRAN

OCRAN is a fork of OCRA, the One-Click Ruby Application builder that Lars Christensen started in 2009. For many years OCRA was the usual way to turn a Ruby script into a Windows .exe. Its last release, 1.3.11, came out in March 2020, and its changelog lists support for Ruby 2.2 to 2.7.

In 2023 I forked it to keep it working with current Ruby versions. The first OCRAN release, 1.3.12, supported Ruby up to 3.2. It has not been a one-person effort: shinokaro is a co-author in the gemspec, and a large share of the commits since the fork are theirs. Lars Christensen is still listed as an author as well, because the foundation is his work.

If you are still using OCRA, I wrote a short migration guide from OCRA to OCRAN. The command-line options are the same.

What OCRAN produces

OCRAN has four output formats:

On Windows you can also create a proper installer with Inno Setup (--innosetup).

Getting started

OCRAN requires Ruby 3.2 or newer.

gem install ocran
ocran script.rb

This runs script.rb, records which files and libraries it loads, and builds script.exe on Windows or script on Linux and macOS.

The other output formats:

ocran --output-dir myapp/ script.rb
ocran --output-zip myapp.zip script.rb
ocran --macosx-bundle --output MyApp --bundle-id com.example.myapp --icon icon.icns script.rb

You can add extra files, directories or glob patterns, and pass arguments to your script after --:

ocran script.rb assets/**/*.png
ocran script.rb -- --some-option=value

ocran --help lists all options.

How dependency detection works

OCRAN does not analyse your code statically. It runs your script during the build and includes everything that gets loaded through require and load. Code that is only loaded under certain conditions is included only if those conditions are met during the build run.

For programs that open a window or wait for input, you can check for the Ocran constant. It is only defined while OCRAN is building:

app = MyApp.new
app.main_loop unless defined?(Ocran)

If files from a gem are missing at runtime, try --gem-all=gemname first, then --gem-full=gemname. For Bundler projects, --gemfile Gemfile includes all gems listed in the Gemfile.

When the self-extracting executable runs, $0 points into the temporary directory, and the environment variable OCRAN_EXECUTABLE contains the full path of the executable itself. That is useful for finding files you ship next to it:

base_dir = File.dirname(ENV["OCRAN_EXECUTABLE"].to_s)

Things to keep in mind

What changed recently

The full list is in the changelog.

Feedback

If something does not work, please check the issues on GitHub first and open a new one if your problem is not there yet. Reports that include the Ruby version, the operating system and the exact ocran command help a lot.