Ruby Application - Packaging Question

Hi! I have a question about packaging a Ruby application.

Background
1. We're using Ruby on Windows and have created a gem out of the main functions
2. This plugs into an "application" system that uses this gem for all the common processing and the rest of the code is to set up things locally and use the gem's services
3. Now, we have a couple of Windows executables that we created from our C++ code which need to be called from the Ruby program. Currently, these are in '/bin' of the application system but actually these belong to the gem
4. The EXEs are built separately (different source project) and are updated only once every 1 ~ 2 years while the Ruby gem/ application is (at least currently) updated much more frequently.

Question
* What is a recommended way to package and deliver the EXE files?

For now, we can assume:
- It is Windows only and we are OK with that
- The executables can work with file paths and configurations and don't have any implicit relative path dependencies, etc.
- I know using shared libraries/ DLLs + Ruby bindings would be good but for now, that's quite a bit of change in our system

Thanks for any advice.

Best Regards,
Mohit.
2021-10-16 | 8:44 am.

Hi! I have a question about packaging a Ruby application.

Background
1. We're using Ruby on Windows and have created a gem out of the main
functions
2. This plugs into an "application" system that uses this gem for all
the common processing and the rest of the code is to set up things
locally and use the gem's services
3. Now, we have a couple of Windows executables that we created from our
C++ code which need to be called from the Ruby program. Currently, these
are in '/bin' of the application system but actually these belong to the
gem
4. The EXEs are built separately (different source project) and are
updated only once every 1 ~ 2 years while the Ruby gem/ application is
(at least currently) updated much more frequently.

Question
* What is a recommended way to package and deliver the EXE files?

The standard Gem::Specification supports packaging up binaries. If you
haven't tried it already, here's where I'd start:

- before packaging the gem, copy the binary executables into the project
`bin` directory
- add the files to Gem::Specification#files via
https://docs.ruby-lang.org/en/3.0.0/Gem/Specification.html#method-i-files
- add the files to Gem::Specification#executables via
https://docs.ruby-lang.org/en/3.0.0/Gem/Specification.html#method-i-executables

The result should be, after installation, that these executables are
installed in directories that are in the user's `PATH` environment variable.

If this doesn't work, please reply with more information about what you've
tried and what's not working for you!

-mike

···

On Fri, Oct 15, 2021 at 8:50 PM Mohit Sindhwani <mo_mail@onghu.com> wrote:

For now, we can assume:
- It is Windows only and we are OK with that
- The executables can work with file paths and configurations and don't
have any implicit relative path dependencies, etc.
- I know using shared libraries/ DLLs + Ruby bindings would be good but
for now, that's quite a bit of change in our system

Thanks for any advice.

Best Regards,
Mohit.
2021-10-16 | 8:44 am.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

Hi Mike,

Thank you for replying!

The standard Gem::Specification supports packaging up binaries. If you haven't tried it already, here's where I'd start:

- before packaging the gem, copy the binary executables into the project `bin` directory
- add the files to Gem::Specification#files via class Gem::Specification - RDoc Documentation
- add the files to Gem::Specification#executables via class Gem::Specification - RDoc Documentation

The result should be, after installation, that these executables are installed in directories that are in the user's `PATH` environment variable.

If this doesn't work, please reply with more information about what you've tried and what's not working for you!

For some reason, it didn't strike me to use that. I just mentally reached the wrong conclusion that when we say that bin is for executables from your gem, that these are executables that use your gem rather than the other way around.

Thanks for pointing me to this. I will take a look this weekend!

Best Regards,
Mohit.
2021-10-18 | 9:36 pm.

···

On 2021-10-18 12:41 am, Mike Dalessio wrote:

From what I know, you should actually put the executable logic in an `exe` directory and add a thin wrapper to a `bin` directory (for development purposes):

#!/usr/bin/env ruby
require 'bundler/setup'
load "#{__dir__}/../exe/executable_name"

This is at least what `bundle gem` does by default IIRC. Then later you point to `exe` files in `Gem::Specification#executables` and bundler will do its work cross platform after the Gem is installed.

···

On 10/18/21 15:38, Mohit Sindhwani wrote:

Hi Mike,

Thank you for replying!

On 2021-10-18 12:41 am, Mike Dalessio wrote:

The standard Gem::Specification supports packaging up binaries. If you haven't tried it already, here's where I'd start:

- before packaging the gem, copy the binary executables into the project `bin` directory
- add the files to Gem::Specification#files via class Gem::Specification - RDoc Documentation
- add the files to Gem::Specification#executables via class Gem::Specification - RDoc Documentation

The result should be, after installation, that these executables are installed in directories that are in the user's `PATH` environment variable.

If this doesn't work, please reply with more information about what you've tried and what's not working for you!

For some reason, it didn't strike me to use that. I just mentally reached the wrong conclusion that when we say that bin is for executables from your gem, that these are executables that use your gem rather than the other way around.

Thanks for pointing me to this. I will take a look this weekend!

s/bundler/gem/

···

On 10/18/21 15:44, hmdne wrote:

and bundler will do its work cross platform after the Gem is installed.

Hi! Thanks!

From what I know, you should actually put the executable logic in an `exe` directory and add a thin wrapper to a `bin` directory (for development purposes):

#!/usr/bin/env ruby
require 'bundler/setup'
load "#{__dir__}/../exe/executable_name"

This is at least what `bundle gem` does by default IIRC. Then later you point to `exe` files in `Gem::Specification#executables` and bundler will do its work cross platform after the Gem is installed.

In our case, the `exe` files are literally .exe file because they are Windows executables (created from our C++ code) that won't run anywhere other than Windows but are called from our Ruby scripts.

So, in some senses, maybe, it's more like a fat gem with the executable binaries included in - but only for Windows.

Best Regards,
Mohit.

···

On 2021-10-18 9:44 pm, hmdne wrote:

Other than the option already mentioned by others of including exe
files as ".executables = [file.exe]" in the gemspec, you could package
an entire Ruby app as a native executable distributed as a Mac DMG/PKG
file or Windows MSI/EXE file.

I only know about packaging JRuby native applications well enough
since my open-source project Glimmer DSL for SWT
(GitHub - AndyObtiva/glimmer-dsl-swt: Glimmer DSL for SWT (JRuby Desktop Development Cross-Platform Native GUI Framework) - The Quickest Way From Zero To GUI - If You Liked Shoes, You'll Love Glimmer!) includes automated
packaging functionality
(https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md)
for DMG/PKG on Mac and MSI/EXE on Windows. If your code can run well
in JRuby and you do not need a quick startup time (JRuby takes 5-10
seconds to start), then that can be an option (for example, an app
that only needs to be started in the morning and left on all day would
be a good fit for this option).

That said, for standard CRuby packaging, OCRA is often recommended for
Windows (GitHub - larsch/ocra: One-Click Ruby Application Builder). In fact, it is mentioned on
my new open-source CRuby GUI project's page: Glimmer DSL for LibUI
(GitHub - AndyObtiva/glimmer-dsl-libui: Glimmer DSL for LibUI - Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library - The Quickest Way From Zero To GUI - If You Liked Shoes, You'll Love Glimmer! - No need to pre-install any prerequisites. Just install the gem and have platform-independent GUI that just works on Mac, Windows, and Linux.), but I am
no expert in it. Perhaps someone else experienced with it could talk
more about it.

···

On Mon, Oct 18, 2021 at 11:56 AM Mohit Sindhwani <mo_mail@onghu.com> wrote:

Hi! Thanks!

On 2021-10-18 9:44 pm, hmdne wrote:
> From what I know, you should actually put the executable logic in an
> `exe` directory and add a thin wrapper to a `bin` directory (for
> development purposes):
>
> #!/usr/bin/env ruby
> require 'bundler/setup'
> load "#{__dir__}/../exe/executable_name"
>
> This is at least what `bundle gem` does by default IIRC. Then later
> you point to `exe` files in `Gem::Specification#executables` and
> bundler will do its work cross platform after the Gem is installed.

In our case, the `exe` files are literally .exe file because they are
Windows executables (created from our C++ code) that won't run anywhere
other than Windows but are called from our Ruby scripts.

So, in some senses, maybe, it's more like a fat gem with the executable
binaries included in - but only for Windows.

Best Regards,
Mohit.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

--
Andy Maleh

LinkedIn: Andy Maleh - Lexop | LinkedIn
Blog: http://andymaleh.blogspot.com
GitHub: http://www.github.com/AndyObtiva
Phone: 438-835-5602

Hi Andy,

Thanks! First up, thanks for your awesome work on Glimmer! I try to do some writing about RubyOnWindows and that includes JRuby; in that, I have had the Glimmer site open in my browser for a few months because I really want to use it and write about how Ruby + JRuby + Rails + Glimmer offer very different options for developers to use.

Now, to what you wrote :slight_smile:

Other than the option already mentioned by others of including exe
files as ".executables = [file.exe]" in the gemspec, you could package
an entire Ruby app as a native executable distributed as a Mac DMG/PKG
file or Windows MSI/EXE file.

I only know about packaging JRuby native applications well enough
since my open-source project Glimmer DSL for SWT
(GitHub - AndyObtiva/glimmer-dsl-swt: Glimmer DSL for SWT (JRuby Desktop Development Cross-Platform Native GUI Framework) - The Quickest Way From Zero To GUI - If You Liked Shoes, You'll Love Glimmer!) includes automated
packaging functionality
(https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md)
for DMG/PKG on Mac and MSI/EXE on Windows.

I will read that link and see if it can help in our current problem.

If your code can run well
in JRuby and you do not need a quick startup time (JRuby takes 5-10
seconds to start), then that can be an option (for example, an app
that only needs to be started in the morning and left on all day would
be a good fit for this option).

I'm familiar with JRuby and in fact, I have a small post that talks about how to package a JRuby JAR based on Ruby code.

However, this application misses a few criteria:
-> we run the application on schedule every minute. The 3 ~ 5 seconds of JRuby startup are a problem till we migrate to a daemon mode for the application where it starts once, runs forever
-> specifically, we need a few Windows binaries to be included into the package
-> finally, we currently use a couple of native gems like Ox which we would need to replace.

That said, for standard CRuby packaging, OCRA is often recommended for
Windows (GitHub - larsch/ocra: One-Click Ruby Application Builder). In fact, it is mentioned on
my new open-source CRuby GUI project's page: Glimmer DSL for LibUI
(GitHub - AndyObtiva/glimmer-dsl-libui: Glimmer DSL for LibUI - Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library - The Quickest Way From Zero To GUI - If You Liked Shoes, You'll Love Glimmer! - No need to pre-install any prerequisites. Just install the gem and have platform-independent GUI that just works on Mac, Windows, and Linux.), but I am
no expert in it. Perhaps someone else experienced with it could talk
more about it.

I have experience with Ocra and it won't help in this case much since it handles the packaging of all the stuff into a single package, then unzips to temp and runs it - similar to JRuby's approach.

For me, the specific problem I was trying to solve is:
* I have some Windows EXE files that are called from our Ruby gem using system('myexe.exe input output')
* I'm seeking the best (Rubyist) way of delivering these with our gem (specifically to Windows users)

I imagine the options I have received will help with this problem and I might need to look up how to create fat gems since those can be specific to a platform and also include binaries.

I will report back.

Best Regards,
Mohit.

···

On 2021-10-19 11:43 am, Andy Maleh wrote: