0

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.

Karol
  • 7,803
  • 9
  • 49
  • 67
  • How would you perform that check *outside* of a makefile? – Etan Reisner May 27 '15 at 23:06
  • @EtanReisner If I know how to do it, I wouldn't have a problem with a `Makefile`. The example checks are here but don't help me much: http://stackoverflow.com/questions/1032114/check-for-ruby-gem-availability I could probably write a `.rb` script to perform a check and output/return something, but I'm leaving it as a last resort. – Karol May 27 '15 at 23:24
  • My point is the "in a makefile" bit here isn't material to the question. If you can check outside of a makefile you can check inside one. So if your question is how to check then you should ask that (and leave out the makefile bit) and that question you linked to would seem to be have your answer already. So if that's not the question then what is the question? You can't magically do anything in a makefile that you can't do normally. So if you normally need a ruby script then you need one in a makefile too. – Etan Reisner May 27 '15 at 23:34
  • @EtanReisner yeah you're right - there was nothing I could do within `Makefile` itself, so I created a simple `ruby` script to cope with the problem. – Karol May 28 '15 at 09:32

3 Answers3

1

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.)

matt
  • 78,533
  • 8
  • 163
  • 197
0

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.

RyanWilcox
  • 13,890
  • 1
  • 36
  • 60
  • Yep, I need a raw `sass` gem. It's not a `ruby` application I'm developing. I came up with an idea and added my answer. – Karol May 28 '15 at 09:35
0

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.

Karol
  • 7,803
  • 9
  • 49
  • 67