Cross-Platform Development

Packing your Ruby application into a single executable

Packing your Ruby application into a single executable

by Minqi Pan

In this talk presented by Minqi Pan at RubyConf 2017, the main focus is on packaging Ruby applications into a single executable for improved distribution and user experience. The video highlights a new open-source tool that simplifies Ruby application deployment by creating standalone executables for Windows, macOS, and Linux. This addresses common issues Ruby developers face when managing dependencies and installing environments across platforms, particularly emphasizing the challenges on Windows.

Key Points Discussed:

  • The Motivation for Development: Minqi shared a personal experience of installing the GitLab CI runner, noticing its ease of deployment via a single executable created with Go. This highlighted the inefficiencies in how Ruby applications are typically distributed.
  • Packaging Solution: The Ruby Packer was introduced to compile Ruby projects into a singular executable, removing the need for users to install Ruby or manage complex dependencies.
  • Deployment Features:
    • Executables created with the Ruby Packer are lightweight (e.g., a GUI application compiled to around 40 megabytes).
    • The tool offers auto-update capabilities, enabling executables to check for and download updates automatically upon running.
  • Technical Mechanism: The speaker explained that resources are stored in a virtual file system within the executable alongside the Ruby interpreter, allowing access to the Ruby standard library without external dependencies.
  • Examples and Scenarios: Minqi demonstrated how to use the tool for compiling Ruby applications and shared experiences with packaging Rails applications to ensure smooth deployment, addressing issues like handling temporary files during execution.
  • Future of Ruby Packaging: The intent is to transition Ruby from source code distribution to streamlined executable distribution, akin to other programming languages, making it much easier for developers and end-users alike.

Conclusions and Takeaways:

  • The Ruby Packer significantly simplifies the installation, update, and distribution of Ruby applications, potentially enhancing the Ruby developer experience.
  • The tool is openly available on GitHub, encouraging the Ruby community to adopt it for their projects.
  • Minqi expressed eagerness to see how developers leverage this tool in their Ruby applications, emphasizing its potential in transforming Ruby application deployment.
00:00:10.550 Good morning, RubyConf! I'm excited to be here. How is everyone doing today?
00:00:19.619 My name is Minqi Pan, and I came from Beijing, China. I'm a Ruby and C++ hacker and a collaborator with Nginx, which involves a lot of open-source development.
00:00:32.570 You can find my GitHub page with various links to my projects. Today, I will be talking about how to compile your Ruby application into a single executable.
00:00:49.770 So where does the story begin? The other day, I was installing the GitLab CI runner on a Windows machine for a C# project. I thought it would be hard to install Ruby on Windows, and I'd need to set up the Ruby environment and install various gems. However, it turned out that wasn't necessary at all.
00:01:03.180 They provided a single executable for easy download—just 46 megabytes. After downloading, I executed it, and it installed the service on my CI machine without issues.
00:01:10.229 Why is that? Because they didn't write the CI runner in Ruby, but in Go. Go has a nice feature that builds programs into a single binary that can be distributed easily. This brings me to a problem that Ruby faces with distribution.
00:01:16.409 Many Ruby applications require users to have the Ruby environment installed, manage gems, and follow steps that can be error-prone, especially on Windows. After the initial setup, users often forget steps and face issues, particularly with native extensions and version mismatches. Updating distributed programs is also cumbersome, requiring lengthy processes.
00:02:09.869 With this in mind, I've decided to address the Ruby packaging issue by developing a Ruby Packer to compile Ruby projects into a single executable file. This makes distribution straightforward—users won't need to install Ruby and manage dependencies manually.
00:02:27.730 For example, I compiled a GUI project into a single executable that weighs around 40 megabytes. Users can simply run it without needing to install anything; just a double-click on Windows. This improvement makes installations and updates significantly easier.
00:03:00.000 Let's look at a demonstration. The program I packed checks for updates when it runs. If it finds a new version, it can automatically download and replace itself. The download happens in a temporary directory, and once downloaded, it will move the new file into its original location.
00:03:13.580 The updating process is smooth; once packaged into a single executable, it makes things so much easier.
00:03:30.400 Now, let's demonstrate how this works. I have a recording of the update process in action, which I believe you will find interesting.
00:03:43.840 When the update occurs, it quickly replaces the existing file with the latest version while respecting existing processes.
00:04:00.500 So, how does this packing and updating work? When you compile your Ruby application, resources are stored in a virtual file system created in memory, alongside the Ruby interpreter. This allows for the inclusion of various components without needing extra installations.
00:04:42.280 We can use commands directly referencing files within this virtual system, which is how we can utilize the Ruby standard library within a packed executable. This feature is particularly useful when performing system operations.
00:05:03.420 To provide a practical example, I can show you how to compile projects or gems using this new tool, which works seamlessly across platforms—Windows, Linux, and macOS.
00:05:21.580 Let me walk you through some scenarios for using this tool. The first scenario involves using the tool to produce a single Ruby interpreter executable, resulting in a simple command that prints information to the console.
00:06:00.000 Currently, Ruby is distributed mainly as source code, but my goal is to facilitate the distribution of Ruby applications as single executables. Imagine if you could easily share a single file instead, much like how other languages handle executable distribution.
00:06:47.720 In addition, we made sure to embed the Ruby standard library directly into the executable, allowing access to standardified code without external dependencies.
00:07:03.510 Now, regarding Rails applications, we have taken steps to allow Rails projects to utilize this packaging tool as well. By specifying the right commands, you can compile Rails applications into standalone executables, enabling smoother deployment.
00:07:43.899 We also managed to handle the temporary files that a Rails app creates during execution by directing logs and caches to a designated temporary location instead of the packed executable.
00:08:17.640 In summary, we've created an effective solution for packaging Ruby applications that simplifies installation and updates while preserving application integrity. The Ruby Packer offers ease of use that I believe many in the Ruby community will greatly appreciate.
00:09:00.000 So if you're interested in trying out this tool, you can find the source code and additional resources on my GitHub page. The tool is open-source and aims to enhance the Ruby experience.
00:09:15.400 Thank you for your attention! I'm excited to see how you will apply this tool in your Ruby projects.