pmq20 / ruby-packer

Packing your Ruby application into a single executable.
MIT License
1.56k stars 99 forks source link

Ruby apps with gem dependencies do not run #39

Open arjunmenon opened 6 years ago

arjunmenon commented 6 years ago

I tried to run an app having a gem dependency, green_shoes, a Ruby gtk2 gui library.

After it compiled the script and outputed a.out file, running produces this error

>$ ./a.out 
/__enclose_io_memfs__/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- green_shoes (LoadError)
    from /__enclose_io_memfs__/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /__enclose_io_memfs__/local/green.rb:1:in `<main>'

Now at first take what i can infer is it is using ruby 2.4 to package an app, but since on my system i got 2.3.3, it wont load. So how can we tell the packer to add those gems either from a local directory or fetch from rubygems.org or a custom version from github? Dependencies should be automatically added , right? Else it should have prompted unavailability or asked to provide dependency path, while packing.

yourivdlans commented 6 years ago

Would you happend to remember what arguments you used to compile the package?

From what I understand you should use the same Ruby version as the compiler does. Also, when compiling you should see the dependencies getting fetched from rubygems. So yes, it should do this automatically.

arjunmenon commented 6 years ago

I just did ./rubyc <name-of-file.rb> I can give it a try by installing ruby 2.4 in my system and re-run, but I have multiple gem dependencies and some of them are modified and sitting on my system. I can push them to a repo but the help argument does not specify how to call multiple gems as dependency and, that to, how to define a source.

yourivdlans commented 6 years ago

I'd suggest you use RVM or rbenv to be able to have multiple ruby versions installed. This way you don't have to worry about the ruby version installed on the system and you can have different projects with different ruby versions.

Personally I like rbenv.

arjunmenon commented 6 years ago

I got rbenv. Now to package an app I just want to know how to declare multiple gems as dependencies?

yourivdlans commented 6 years ago

I see, a Gemfile with your dependencies should be picked up by the compiler and be put in the package so it can be used by your program.

sk-jlewis commented 6 years ago

I'm also experiencing this problem.

test.rb

require 'faker'

puts "Hello #{Faker::Name.name}"

Dockerfile

FROM ruby:2.4.0

RUN apt-get update
RUN apt-get install -y squashfs-tools bison

RUN curl -L http://enclose.io/rubyc/rubyc-linux-x64.gz | gunzip > rubyc
RUN chmod +x rubyc && cp rubyc /usr/local/bin/

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Copy application files
COPY ./app/ ./

RUN rubyc test.rb
docker run -it rubyapp ./a.out
/__enclose_io_memfs__/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- faker (LoadError)
        from /__enclose_io_memfs__/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /__enclose_io_memfs__/local/test.rb:1:in `<main>'
iamsimakov commented 6 years ago

maybe add Gemfile and do bundle install ?(now I can not reproduce problem, but I will try do it tomorrow)

sk-jlewis commented 6 years ago

Hmm yea i had tried that as well :(

iamsimakov commented 6 years ago

hi, @sk-jlewis yes, the problem is still here. I tried to pack on my host machine, in docker, tried to install gems in the local path with a flag --path=vendor, tried to modify code of test.rb to set my gem path folder through Gem.use_paths(...), tried to require 'rubygems' before 'faker', but anywhere I see the same error: /__enclose_io_memfs__/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:inrequire': cannot load such file -- faker (LoadError)`

I found that rubyc install gems in vendor path in __enclose_io_memfs__ and even I tried to require an appropriate file from this folder: require 'vendor/ruby/2.4.0/gems/...'

And I see the error as above. It's like that GEM_PATH or GEM_HOME is not set. And I found that these two env vars set nil before the build. It's only my opinion based on reading sources. Maybe these vars set value anywhere after it.

maybe creators can say what happens(

cbeckr commented 6 years ago

I was able to resolve this with the following boilerplate at the top of the main file:

#!/usr/bin/env ruby
require 'rubygems'
require 'bundler/setup'
quadur commented 5 years ago

I'm struggling with the same problem on win10 my test.rb:

require 'rubygems'
require 'bundler/setup'
require 'faker'

puts "Hello #{Faker::Name.name}"

my Gemfile:

source "https://rubygems.org"
gem 'bundler'
gem 'faker'

Nothing I do seems to change gems recognized by rubyc -c test.rb. I've tried bundle installs, gem installs, the only thing that got me further was static requires to gem paths ie:

require 'C:\Ruby24-x64\lib\ruby\gems\2.4.0\gems\faker-1.9.1\lib\faker.rb'

But since I need eventmachine and serialruby gems I would have to require all of the requirements (and requirement requirements...) as well.

Does someone have a working solution/howto for gems on windows?

iamsimakov commented 5 years ago

@quadur hi, I use rubyc too. did you try to use docker for build your binary file? ex above https://github.com/pmq20/ruby-packer/issues/39#issuecomment-415494119

ngouy commented 4 years ago

Problem solved by restarting spring spring stop

E-Xor commented 4 years ago

I was able to make it work. I found several important steps to success:

pack/test.rb:

#!/usr/bin/env ruby

require 'rubygems'
require 'bundler/setup'
require 'colorize'

puts 'one'
puts 'two'.colorize(:red)

pack/Gemfile:

source 'https://rubygems.org'

gem 'colorize'

pack/Gemfile.lock, it was critical that BUNDLED WITH is 1.15.3, that's what rubyc wants.

GEM
  remote: https://rubygems.org/
  specs:
    colorize (0.8.1)

PLATFORMS
  ruby

DEPENDENCIES
  colorize

BUNDLED WITH
   1.15.3

Compiled like

./rubyc --tmpdir=/path/to/tmp --output=test.out --root=./pack ./pack/test.rb

Based on my understanding of the output of rubyc, it puts ruby (2.4.0) and gems, including bundler (1.15.3), in it's tmp directory and runs bundler with your Gemfile in that environment. It ignores rvm, gemset and what gems installed in there.