As a follow-up to my previous post, you can even make a single executable file of your Ruby archive. It relies on the fact that zip files are pretty resilient to extra garbage data in the beginning. Let's say I have two files, lib/greetings.rb
and bin/hello.rb
. greetings.rb
defines a make_hello()
function that is used by hello.rb
. Here's hello.rb
:
require "lib/greetings" puts "Enter your name:" name = gets.strip puts "\n" + make_hello(name)
You can run it like this:
$ ruby bin/hello.rb Enter your name: Steve Hello, Steve! $
First, we make a zip file that includes all the required source files:
$ zip -r hello.zip bin lib adding: bin/ (stored 0%) adding: bin/hello.rb (deflated 11%) adding: lib/ (stored 0%) adding: lib/greetings.rb (deflated 7%) $ unzip -l hello.zip Archive: hello.zip Length Date Time Name -------- ---- ---- ---- 0 02-14-11 21:01 bin/ 98 02-14-11 21:01 bin/hello.rb 0 02-14-11 20:59 lib/ 46 02-14-11 20:59 lib/greetings.rb -------- ------- 144 4 files
Now we need a ruby header for the zip file, which we'll put into header.rb
:
#!/usr/bin/ruby -rubygems -x require "zip/ziprequire" $:.push $0 require "bin/hello.rb" __END__
It runs the ruby interpreter, which then loads zip/ziprequire
, adds itself (which will be the zip file) to the path, and then requires our main file, bin/hello.rb
. We now prepend this header to the zip file using cat header.rb hello.zip > hello_tmp.zip
. If you now try to run unzip -l
on this file, you'll get:
$ unzip -l hello_tmp.zip Archive: hello_tmp.zip warning [hello_tmp.zip]: 97 extra bytes at beginning or within zipfile (attempting to process anyway) Length Date Time Name -------- ---- ---- ---- 0 02-14-11 21:01 bin/ 98 02-14-11 21:01 bin/hello.rb 0 02-14-11 20:59 lib/ 46 02-14-11 20:59 lib/greetings.rb -------- ------- 144 4 files
We need to fix this zip file to make it valid. Thankfully zip
has an option for this:
$ zip --fix hello_tmp.zip --out hellox.zip Fix archive (-F) - assume mostly intact archive Zip entry offsets appear off by 97 bytes - correcting... copying: bin/ copying: bin/hello.rb copying: lib/ copying: lib/greetings.rb
We now have a valid zip archive in hellox.zip
, we just need to make it executable by running chmod +x hellox.zip
. Now your whole application is a single executable file that you can run:
$ ./hellox.zip Enter your name: Mike Hello, Mike!