Introducing Aibika: Ruby executable packager on Windows built on Ocra
Why Aibika?
The Ocra (One-Click Ruby Application) tool used to be an excellent solution for distributing Ruby applications on the Windows platform.
With Ocra, you could create a self-extracting, self-running executable that contained the Ruby interpreter, application source code, and any additional Ruby libraries or dynamically-linked libraries (DLLs) needed.
However, Ocra has not been supported or updated since 2020. This has caused numerous issues with newer versions of Ruby, and its behavior is often considered suspicious by modern anti-virus software (resulting in the application being quarantined or deleted).
While our team is committed to creating a full-fledged Windows port of the Tebako packager, which provides a user-space mounted-disk experience with minimal intervention, we have decided to publish our enhanced fork of Ocra in the meantime.
What is Aibika?
Aibika is a direct descendant of Ocra and provides the same feature set and parameters.
The goal of Aibika is to modernize Ocra for the latest Ruby versions to run on the latest Windows systems.
We have adopted Aibika for Ruby 2.7 through 3.2 and tested it on Windows 2019 and 2022 in the GitHub Actions environment.
One of the main objectives of the Tebako project is to support development of Metanorma. Hence Aibika is now used to build the Metanorma single binary for Windows.
Migration did not require any changes other then replacement of calls to ocra to calls to aibika in the build scripts.
Ocra did not work with Ruby 3.x and placed restrictions on the version of rubygems that could be used. Aibika released these restrictions without any changes to the packaging script.
What does the name Aibika mean?
"Ocra" happens to be a wordplay on "okra", the plant name, so the name of the flower okra plant, "aibika" was adopted for the modern version.
The flower okra is named as it blooms flowers similar to the okra, and refers to the Abelmoschus manihot plant. Aibika refers to the Spanish name of the flower okra.
Aibika, called トロロアオイ (黄蜀葵, tororoaoi), is a key ingredient to the creation of Washi (和紙, Japanese paper).
Japanese paper is thin, durable and long-lasting because of its use of aibika. In the manufacturing of Japanese paper, mucus extracted from the root of aibika is used to uniformize the spread of fibers. Without this mucus in the solution, fibers will quickly get excluded from the solution, resulting in fibers not scattered evenly.
Using Aibika
General
Aibika supports multiple ways of creating a single executable for a Ruby program on Windows.
In this post we will described the most typical cases, but if your use case is more complex, please check out the README for other options.
Single file
If your Ruby application is a single file that references installed gems, this is how you package it.
Our sample application will check validity of a PNG file using the pngcheck gem.
require 'bundler'
require 'pngcheck'
exit if defined?(Aibika)
puts 'Enter PNG file name:'
fn = gets.chomp
status, info = PngCheck.analyze_file(fn)
puts "Status: #{status}, info: #{info}"
Notice that this application exits immediately after require
. In the case of
packaging, such context is signalled by the definition of Aibika
. This is a
good practice in our case because Aibika loads all application files.
If the execution continues, the application will wait for input, do processing and generate the output. Normally it can be avoided.
For correct packaging, Aibika shall be able to build a list of all application
files and dependencies either through require
, or by Gemfile or on the command
line.
With this source we can do packaging. Let’s assume that the file name is
sample.rb
, and that the bundler
, aibika
and pngcheck
gems are already
installed.
> aibika sample.rb
This command will produce the package application sample.exe
that can be used
as planned:
...
Finished building sample.exe (4434538 bytes)
D:\Projects\10.Projects\aibika demo>sample.exe
Enter PNG file name:
correct.png
Status: 0, info: OK: correct.png (172x178, 8-bit palette, non-interlaced, 92.4%).
D:\Projects\10.Projects\aibika demo>sample.exe
Enter PNG file name:
no.png
Status: 5, info: Failed to open no.png: No such file or directory
With Gemfile
We can also specify dependencies using Gemfile.
Our script will change to:
require 'pngcheck'
exit if defined?(Aibika)
puts 'Enter PNG file name:'
fn = gets.chomp
status, info = PngCheck.analyze_file(fn)
puts "Status: #{status}, info: #{info}"
Note that the indirect bundler dependency went into the Gemfile
:
source "https://rubygems.org"
gem "bundler"
gem "pngcheck", ">= 0.3.1"
and packaging command is:
> aibika --gemfile Gemfile sample.rb
Of course, this method works better in case of a complex application with dynamically loaded features.
Other options
Aibika provide numerous options to control packaging. If the simple approach described in this post does not work, please consider content detection options as explained in the Aibika README.