Project

General

Profile

Actions

Misc #17815

open

Snapcraft Ruby plugin

Added by paddor (Patrik Wenger) 6 months ago. Updated 6 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
[ruby-core:103518]

Description

I'm working on a Ruby build plugin for the Snapcraft v2 plugin AP, since the v1 Ruby plugin does not work on the Ubuntu core20 image. The v2 API only allows to influence the build step, which means there's no nice way for the plugin to set environment variables that apply during runtime. The problem is that the final paths to Ruby's stdlib are unknown during compile time.

I've got it to work by renaming the ruby executable to ruby.bare and creating a wrapper script ruby that sets the $RUBYLIB and $GEM_PATH env variables based on $SNAP before execing ruby.bare. I don't like that it requires a wrapper script though, since it would have to awkwardly determine the arch-specific stdlib directory to support any platform. The current wrapper script is this:

#!/bin/sh
export RUBYLIB="$SNAP/lib/ruby/snap:$SNAP/lib/ruby/snap/x86_64-linux:$RUBYLIB"
export GEM_PATH="$SNAP/lib/ruby/gems/snap:$GEM_PATH"

exec `dirname $0`/ruby.bare "$@"

What possible solutions are there? I could maybe fix the shebangs of Ruby executables like gem and bundle, but not ruby itself since it's binary. Also, I'm not sure if env variable expansion even works in shebang.
Can the configure script's --with-search-path be made to support env variable expansion during runtime? That still wouldn't solve the issue about the arch-specific directory.

Python apparently determines its load paths relative to the executable being run. Does Ruby support anything like that?

Any other ideas?
Current state: https://github.com/paddor/snapcraft-ruby-plugin-v2

Actions #1

Updated by paddor (Patrik Wenger) 6 months ago

  • Description updated (diff)

Updated by hsbt (Hiroshi SHIBATA) 6 months ago

Hello, I'm maintainer of ruby snap package at https://github.com/ruby/snap.ruby

I'm not sure what means "Ruby build plugin". Does it means https://snapcraft.io/docs/ruby-plugin?

Updated by paddor (Patrik Wenger) 6 months ago

hsbt (Hiroshi SHIBATA) wrote in #note-2:

Hello, I'm maintainer of ruby snap package at https://github.com/ruby/snap.ruby

I'm not sure what means "Ruby build plugin". Does it means https://snapcraft.io/docs/ruby-plugin?

Hi! Yes, but https://snapcraft.io/docs/ruby-plugin is a v1 plugin. It does not work on core20. I want to make ruby plugin based on the v2 plugin API so that I can package Ruby applications (actually server processes) and easily install them in production.

I just pushed the current state: https://github.com/paddor/snapcraft-ruby-plugin-v2

Actions #4

Updated by paddor (Patrik Wenger) 6 months ago

  • Description updated (diff)

Updated by mame (Yusuke Endoh) 6 months ago

Hello,

paddor (Patrik Wenger) wrote:

Python apparently determines its load paths relative to the executable being run. Does Ruby support anything like that?

I think ./configure --enable-load-relative is what you are looking for.

Updated by paddor (Patrik Wenger) 6 months ago

mame (Yusuke Endoh) wrote in #note-5:

I think ./configure --enable-load-relative is what you are looking for.

That is very useful, thank you. It populates $LOAD_PATH with the correct paths. But it doesn't apply to the env variable GEM_PATH:

$ test-my-ruby-plugin
/snap/test-my-ruby-plugin/x43/lib/ruby/snap/rubygems.rb:281:in `find_spec_for_exe': can't find gem hello-world (>= 0.a) with executable hello-world (Gem::GemNotFoundException)
        from /snap/test-my-ruby-plugin/x43/lib/ruby/snap/rubygems.rb:300:in `activate_bin_path'
        from /snap/test-my-ruby-plugin/x43/bin/hello-world:23:in `<main>'

Is there an equivalent for Rubygems?

Running gem env inside the snap tells me this:

$ test-my-ruby-plugin.gem-env
RubyGems Environment:
  - RUBYGEMS VERSION: 3.2.15
  - RUBY VERSION: 3.0.1 (2021-04-05 patchlevel 64) [x86_64-linux]
  - INSTALLATION DIRECTORY: /home/user/.gem/ruby/3.0.0
  - USER INSTALLATION DIRECTORY: /home/user/snap/test-my-ruby-plugin/x44/.local/share/gem/ruby/snap
  - RUBY EXECUTABLE: /snap/test-my-ruby-plugin/x44/bin/ruby
  - GIT EXECUTABLE:
  - EXECUTABLE DIRECTORY: /home/user/.gem/ruby/3.0.0/bin
  - SPEC CACHE DIRECTORY: /home/user/snap/test-my-ruby-plugin/x44/.local/share/gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: //etc
  - RUBYGEMS PLATFORMS:
     - ruby
     - x86_64-linux
  - GEM PATHS:
     - /home/user/.gem/ruby/3.0.0
     - /home/user/.rubies/ruby-3.0.0/lib/ruby/gems/3.0.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - /snap/test-my-ruby-plugin/x44/usr/sbin
     - /snap/test-my-ruby-plugin/x44/usr/bin
     - /snap/test-my-ruby-plugin/x44/sbin
     - /snap/test-my-ruby-plugin/x44/bin
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/sbin
     - /usr/bin
     - /sbin
     - /bin
     - /usr/games
     - /usr/local/games

Notice how GEM PATHS does not list any directory inside the snap.

Updated by paddor (Patrik Wenger) 6 months ago

Wow, I just figured out something. It's the env variable GEM_PATH from my system that leaks into the process being run (duh). For some reason I thought that snap processes were more isolated. If I env -i (ignore environment) first, it derives the correct GEM_PATH and the gem can be loaded:

$ env -i /snap/bin/test-my-ruby-plugin
this is executable hello-world
$ env -i /snap/bin/test-my-ruby-plugin.gem-env
RubyGems Environment:
  - RUBYGEMS VERSION: 3.2.15
  - RUBY VERSION: 3.0.1 (2021-04-05 patchlevel 64) [x86_64-linux]
  - INSTALLATION DIRECTORY: /snap/test-my-ruby-plugin/x44/lib/ruby/gems/snap
  - USER INSTALLATION DIRECTORY: /home/user/snap/test-my-ruby-plugin/x44/.local/share/gem/ruby/snap
  - RUBY EXECUTABLE: /snap/test-my-ruby-plugin/x44/bin/ruby
  - GIT EXECUTABLE:
  - EXECUTABLE DIRECTORY: /snap/test-my-ruby-plugin/x44/bin
  - SPEC CACHE DIRECTORY: /home/user/snap/test-my-ruby-plugin/x44/.local/share/gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: //etc
  - RUBYGEMS PLATFORMS:
     - ruby
     - x86_64-linux
  - GEM PATHS:
     - /snap/test-my-ruby-plugin/x44/lib/ruby/gems/snap
     - /home/user/snap/test-my-ruby-plugin/x44/.local/share/gem/ruby/snap
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - /snap/test-my-ruby-plugin/x44/usr/sbin
     - /snap/test-my-ruby-plugin/x44/usr/bin
     - /snap/test-my-ruby-plugin/x44/sbin
     - /snap/test-my-ruby-plugin/x44/bin
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/sbin
     - /usr/bin
     - /sbin
     - /bin
     - /usr/games
     - /usr/local/games

That's good because in production there won't be a GEM_PATH env var.

Actions

Also available in: Atom PDF