如果 gem 不存在,如何通过 Makefile 安装

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

我正在为我的项目创建 Makefile

build:
    sudo gem install sass

每当我构建它时,它都会询问我的超级用户密码。如果我删除 sudo 它根本不会安装,而是抛出一个错误,因为我没有安装 gem.

的权限

所以我想出了一个主意,我想检查 gem 是否已经存在,只有当 运行 不存在时才安装命令。

所以问题是如何在 Makefile.

中执行此检查

现在 Ruby 社区中的传统做法是使用 Bundler 来管理/安装依赖项。这将在没有 sudo privs 的情况下安装 Gems,并且还会将不同的 Ruby 项目的 gem 分开。

如果您必须安装 gem raw,请查看 RVM or rbenv,它会在您的主目录中安装 Ruby 和任何未来的 gem。有一些逻辑你必须添加到你的 Makefile 才能让它使用你的主文件夹中的新 Ruby(rbenv 可能比 rvm 更容易,虽然我不确定)......但是不难。

完成任务的一种快速方法是编写 .rb 脚本并从 Makefile 执行它。我想出的最简单的脚本如下:

#!/usr/bin/env ruby
if !Gem::Specification::find_all_by_name('sass').any?
  exec("sudo gem install sass")
end

find_all_by_name 总是返回一个数组,当它找不到任何东西时不会引发错误(就像 find_by_name 那样)。

生成文件:

default:
    ./install.rb

确保 install.rb 可执行:

chmod +x install.rb

运行 它使用 make.

从命令行您可以查看 gem 是否与 gem list <gemname> 一起安装。这将打印出匹配 <gemname>:

的已安装 gem 列表
$ gem list sass

*** LOCAL GEMS ***

sass (3.4.13, 3.4.1, 3.2.19)
sass-rails (5.0.1, 4.0.3)

该参数实际上是一个正则表达式,因此您可以更具体一些,例如检查只有 Sass gem 本身:

$ gem list \^sass$

*** LOCAL GEMS ***

sass (3.4.13, 3.4.1, 3.2.19)

list-i 标志使它产生的输出在脚本中更有用,打印 truefalse,并具有合适的退出状态:

$ gem list \^sass$ -i
true
$ echo $?
0
$ gem list \^notsass$ -i
false
$ echo $?
1

您可以将其与 Make 的条件语句和 shell function(假设是 GNU make)结合使用来检查是否从您的 makefile:

安装了 gem
ifeq ($(shell gem list \^sass$$ -i), false)
    gem install sass
endif

(需要额外的 $ 以防止 make 尝试将其扩展为变量。)