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!