How to install gem via Makefile if it doesn't exist - ruby

I'm creating a Makefile for my project:
build:
sudo gem install sass
Any time I build it's asking me for my superuser password. If I remove sudo it will not install at all, but throw an error instead, as I don't have permissions to install a gem.
So I came up with an idea, that I want to check whether the gem already exists, and run installing command only when it doesn't.
So the question is how to perform this check inside Makefile.

From the command line you can see if a gem is installed with gem list <gemname>. This prints out a list of installed gems that match <gemname>:
$ gem list sass
*** LOCAL GEMS ***
sass (3.4.13, 3.4.1, 3.2.19)
sass-rails (5.0.1, 4.0.3)
The argument is actually a regex, so you can be more specific, checking e.g. only the Sass gem itself:
$ gem list \^sass\$
*** LOCAL GEMS ***
sass (3.4.13, 3.4.1, 3.2.19)
The -i flag to list makes it produce output more usable in scripts, printing true or false, and having a suitable exit status:
$ gem list \^sass\$ -i
true
$ echo $?
0
$ gem list \^notsass\$ -i
false
$ echo $?
1
You can combine this with Make’s conditionals, and the shell function (assuming GNU make) to check if a gem is installed from your makefile:
ifeq ($(shell gem list \^sass\$$ -i), false)
gem install sass
endif
(The extra $ is needed to prevent make trying to expand it as a variable.)

It's now traditional in the Ruby community to use Bundler to manage / install dependencies. This will install Gems without you having sudo privs, and also will keep different Ruby project's gems separate.
If you must install the gem raw, look into RVM or rbenv which both install Ruby and any future gems in your home directory. There' some logic you'd have to add to your Makefile to get it to use the new Ruby in your home folder (rbenv may make this easier than rvm, although Idon't know for sure)... but it's not hard.

One quick way to accomplish the task is writing an .rb script and execute it from a Makefile. The simplest script I came up with goes as follows:
#!/usr/bin/env ruby
if !Gem::Specification::find_all_by_name('sass').any?
exec("sudo gem install sass")
end
find_all_by_name is always returning an array and doesn't raise an error when it can't find anything (as find_by_name does).
Makefile:
default:
./install.rb
Make sure install.rb is executable:
chmod +x install.rb
Run it using make.

Related

Install a Ruby gem to an arbitrary prefix

I'd like to install a Ruby gem to an arbitrary prefix. For the sake of exposition, I'm trying to install github-markup; though, I suspect I'm encountering a general issue rather than anything particular to this package.
In the package's source distribution directory, I've done this:
$ gem install --install-dir $HOME/github-markup/lib/ruby/gems --bindir $HOME/github-markup/bin github-markup
And, of course, I've added $HOME/github-markup/bin to the PATH; and I've added $HOME/github-markup/lib/ruby/gems to RUBYLIB.
But, when I try to run the executable, this happens:
$ github-markup my.md
-bash: /usr/local/bin/github-markup: No such file or directory
Clearly I'm missing a piece of the puzzle.

Ruby gem names with appended ruby version

Ruby gem names are really throwing me off. For example if install a gem called jade, a wrapper script is placed at /usr/bin/jade1.9 on some systems and at /usr/bin/jade on others. I'm curious if anyone has a recommendation on how I can use jade in scripts without writing some hackish code that guesses the correct gem name. The naming also makes it difficult to write documentation for less savvy users. Is there a simple way of making gems install with same name on all systems?
To elaborate a bit:
gem install jade #jade is something I made up
ls /usr/bin/|grep "jade"
> jade1.9
When I want to execute:
jade --dosomething
I actually have to run
jade1.9 --dosomething
I've noticed certain gems such as rake are installed at both /usr/bin/rake and /usr/bin/rake1.9 with neither being a symlink and both files having the same md5sum.
I am trying to understand why gems get the ruby version appended on some systems and how I can make install without the trailing version number.
A list of some example of gems that install an executable:
ls /usr/bin/|grep "1.9"
amalgalite-pack1.9
bundle1.9
crate1.9
erb1.9
gem1.9
irb1.9
minitar1.9
rake1.9
rdoc1.9
ri1.9
rlock1.9
ruby1.9
rubyscript2exe1.9
testrb1.9

Gem not installing package

So I'm trying to install a package
$ sudo gem install compass
to be specific. It installs correctly and shows up when I do a list:
$ gem list
*** LOCAL GEMS ***
chunky_png (1.2.5)
compass (0.12.2)
fssm (0.2.9)
sass (3.1.20)
but for some reason when I try to run compass nothing happens. It says the command is not found. What am I doing wrong?
$ compass
bash: compass: command not found
I'm running Ubuntu if that helps.
Confirm that there is output for locate -r /compass.rb$, then echo $GEM_HOME. You should find that gem doesn't know about the directory that compass installed to. You can either move it from its previous location into the directory specified by GEM_HOME, or else append that directory to the variable in your ~/.bash_rc file. Much better, though, would be to use rvm for managing your gems (and Rubies), as it neatly avoids this sort of issue and also allows much finer control over the whole process.
This problem can be solved by follwing this:
http://markushedlund.com/dev-tech/ubuntu-compass-command-not-found
The problem is concerned about the global variable PATH that is not being updated correctly when installing gem compass
Run
echo "PATH=\$PATH:/var/lib/gems/1.8/bin:\$HOME/.gem/ruby/1.8/bin" >>
/etc/profile.d/rubygems1.8.sh
and re-login

Ruby 1.9.3 + Rails on Solaris 10 - libyaml is missing

I'm trying to install Ruby on Rails on Solaris 10 box. I managed to build Ruby 1.9.3 from source and I installed gems but when I run gem command every time I get this message:
# gem list
/usr/local/lib/ruby/1.9.1/yaml.rb:56:in `<top (required)>':
It seems your ruby installation is missing psych (for YAML output).
To eliminate this warning, please install libyaml and reinstall your ruby.
This is really anoying :)
So I tried to rebuild Ruby and here is what I noticed in the output of make.
configuring psych
libyaml is missing. Please install libyaml.
Failed to configure psych. It will not be installed.
I found the extconf.rb script that checks for that and I tried to run it manually:
# pwd
/root/pub/ruby-1.9.3-p194/ext/psych
#
# irb --simple-prompt
>> require 'mkmf'
=> true
>> find_header 'yaml.h'
checking for yaml.h... yes
=> true
>> find_library 'yaml', 'yaml_get_version'
checking for yaml_get_version() in -lyaml... yes
=> true
>> exit
Apparently extconf.rb could find libyaml but make could not. So I'm puzzled why make does not find it. Any thoughts?
There are a couple of walk-throughs online regarding the install of Rails on Solaris.
This is for Rails 3: https://www.machine-unix.com/2011/05/installing-rails3-on-solaris-10-910/
And this one talks about avoiding issues with incompatible libraries: http://www.nowastedmoves.com/2009/geekery/installing-ruby-on-rails-on-solaris-10-1008-2/
I've never tried this on Solaris, but hopefully this will be of help.
I had this problem with Mac OS, perhaps it helps: http://icodeapps.net/?p=8
You need to install libyaml.
If you're install libyaml from a pre-built package, you will likely need a separate package with development headers, usually "libyaml-dev" or similar.
Alternatively you can install libyaml from source:
Download the source package:
http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz. To build and install LibYAML, run:
$ ./configure
$ make
# make install
(Note the last line begins with a #, indicated a root shell, prepend sudo when running as a normal user.)
Then reconfigure and recompile Ruby after installing libyaml.

How do I run a Ruby Gem?

This might seem stupid, but I recently tried to install SASS and followed their instructions:
$ gem install sass
$ sass --watch [...]
So I followed along:
root#server:~# gem install sass
Successfully installed sass-3.1.15
1 gem installed
Installing ri documentation for sass-3.1.15...
Installing RDoc documentation for sass-3.1.15...
root#server:~# sass
bash: sass: command not found
Despite looking around like an idiot trying to find some simple way to run something like gem run sass or some other workaround to make it function, I am more or less at a loss.
It seems that Debian/Ubuntu drops ruby gems into /var/lib/gems/1.8/bin.
So the solution (at least for Ubuntu/Debian) is:
$ sudo -s
# echo 'PATH=/var/lib/gems/1.8/bin:$PATH' > /etc/profile.d/gemspath.sh
# chmod 0755 /etc/profile.d/gemspath.sh
...and then open a new shell session.
(This is fixed in Ubuntu 11.10.)
If you happen to have installed Ruby through rbenv, you'll need to execute the following command
rbenv rehash
On macOS I had to add the gem executable directory to the path.
Add these lines to your ~/.bashrc file, and reopen the terminal to refresh the env vars.
# gem
gembin=`(gem env | sed -n "s/.*EXECUTABLE DIRECTORY: \(.*\)/\1/p")`
export PATH=$gembin:$PATH
If you use macOS and you:
I don't know/care about Ruby.
I just want to run this program.
Why is this so complicated?
Then run:
~/.gem/ruby/*/bin/jekyll
where jekyll is the thing you just installed with gem install.
If you're trying to run a simple WEBrick server for your gem you can do the following after installation:
sass start

Resources