>我正在开发一个 Makefile 来构建一个应用程序,其中前端和后端完全分离在两个不同的目录中,例如:
- myapp
|_be
|_fe
这是我的制作文件:
.ONESHELL:
all: frontend backend
frontend:
cd ./fe &&
npm install &&
./node_modules/webpack/bin/webpack.js
backend: clean
cd ./be &&
gem install bundler &&
bundle install
clean:
rm -f ./fe/public/bundle.js && rm -rf ./fe/public/resources
webpack:
cd ./fe &&
.node_modules/webpack/bin/webpack.js
test:
cd ./fe &&
npm test
run:
cd ./be &&
rackup config.ru
前端是一个 React 应用程序,当我键入make frontend
时,它正在正确构建。这里没有问题。
但后端是用 Ruby 编写的 Rack 应用程序。在构建过程中我需要输入它的目录(be
),确保捆绑器已安装并运行bundle install
。
碰巧make
创建自己的外壳来运行 Makefile 命令。并且这个外壳不会继承我正在工作的控制台外壳的环境变量。这对我来说是一个问题,因为我使用rvm
,rvm
使用一些环境变量来选择正确的宝石。我使用.ruby-gemset
和.ruby-version
为我的应用程序创建专用捆绑包,而不是使用默认 gemset。这是必要的,因为我有使用许多不同的 Ruby 版本的应用程序,不想关心这个。
这个特定的应用程序使用 JRuby 9.1.7.0,然后我的Gemfile
(be
目录中)有以下行:
ruby '2.3.1', :engine => 'jruby', :engine_version => '9.1.7.0'
我注意到了所有这些问题,因为我在键入make backend
时收到以下错误:
您的 Ruby 引擎是 ruby,但您的 Gemfile 指定了 jruby
据我所知rvm
(而且我非常了解),这意味着它正在尝试使用我的默认 Ruby 版本(设置为 Ruby 2.5.0)作为引擎,而不是正确的 JRuby 版本。
现在,这是我的问题:有没有办法强制 make 内壳使用与我正在使用的控制台外壳相同的配置?
这将解决问题,因为控制台外壳已由rvm
配置。我知道这是因为当我手动输入be
目录并在其中运行bundle install
时,一切都很好。
我使用.ONESHELL
指令迫使make
这样做,但似乎这不是我需要的。
建议?
编辑:make
文档说-e
标志可用于强制make
获取所有控制台外壳变量。我试过了,但没有用。
编辑:如果我这样做,这一切都有效
rvm use --default jruby-9.1.7.0
在做我make backend
之前.但是由于许多原因,这样做并不方便。此外,我真的相信这是一个更好的方法。make
太聪明了,不允许这样简单的事情。
我相信有2个问题:
1)当rvm
创建其环境变量时,它不会export
它们,因此它们对子shell不可见,并且
2)由于子 shell 不是作为登录 shell 启动的,它看不到和处理rvm
函数声明,因此无法执行rvm my-ruby-version
。
以下是几种解决方法:
在创建子外壳之前,请执行如下操作:
export RVM_VERSION=`rvm current`
启动子外壳时,请在登录模式下执行此操作:
zsh --login
或
bash --login
然后,rvm 应该是一个函数,这应该可以工作:
rvm $RVM_VERSION
首先,我在backend:
食谱中添加了两行,现在正在阅读
backend:
cd ./be &&
source $(HOME)/.rvm/scripts/rvm &&
rvm use jruby-9.1.7.0 &&
gem install bundler &&
bundle install
这个想法是设置正确的Ruby(JRuby 9.1.7.0),而不必在控制台上永久更改它。
碰巧这行不通,因为我没有选择我正在使用的外壳,而且似乎由于某种原因它没有/bin/bash
,source
不起作用。作为续集,rvm
也行不通,我会收到那条恼人的消息,说
RVM 不是一个函数
然后我添加了
SHELL = /bin/bash
就在.ONESHELL:
指令之后。
现在一切正常!