rubyjs/therubyracer

Gem fails to build under Catalina

coding-bunny opened this issue · 17 comments

The ruby version itself doesn't seem to matter much as I'm running into this problem on several versions, the older the version the more guaranteed that it won't work however:

gem install therubyracer -v 0.12.3 -- --with-v8-include=/usr/local/Cellar/v8/7.8.279.23/libexec/include --with-v8-lib=/usr/local/Cellar/v8/7.8.279.23/libexec

Building native extensions.  This could take a while...
ERROR:  Error installing therubyracer:
        ERROR: Failed to build gem native extension.

        /Users/olivar/.rbenv/versions/1.9.3-p551/bin/ruby extconf.rb --with-v8-include=/usr/local/Cellar/v8/7.8.279.23/libexec/include --with-v8-lib=/usr/local/Cellar/v8/7.8.279.23/libexec
checking for main() in -lpthread... yes
checking for main() in -lobjc... yes
checking for v8.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/Users/olivar/.rbenv/versions/1.9.3-p551/bin/ruby
        --with-pthreadlib
        --without-pthreadlib
        --with-objclib
        --without-objclib
        --enable-debug
        --disable-debug
        --with-v8-dir
        --without-v8-dir
        --with-v8-include=${v8-dir}/include
        --with-v8-lib=${v8-dir}/
/Users/olivar/.rbenv/versions/1.9.3-p551/lib/ruby/gems/1.9.1/gems/libv8-3.16.14.19/ext/libv8/location.rb:50:in `configure': By using --with-system-v8, you have chosen to use the version  (Libv8::Location::System::NotFoundError)
of V8 found on your system and *not* the one that is bundled with 
the libv8 rubygem. 

However, your system version of v8 could not be located. 

Please make sure your system version of v8 that is compatible 
with 3.16.14.19 installed. You may need to use the 
--with-v8-dir option if it is installed in a non-standard location
        from /Users/olivar/.rbenv/versions/1.9.3-p551/lib/ruby/gems/1.9.1/gems/libv8-3.16.14.19/lib/libv8.rb:7:in `configure_makefile'
        from extconf.rb:32:in `<main>'


Gem files will remain installed in /Users/olivar/.rbenv/versions/1.9.3-p551/lib/ruby/gems/1.9.1/gems/therubyracer-0.12.3 for inspection.
Results logged to /Users/olivar/.rbenv/versions/1.9.3-p551/lib/ruby/gems/1.9.1/gems/therubyracer-0.12.3/ext/v8/gem_make.out

This is with paths specified for all libraries to either Homebrew or System ones on Catalina.
Neither seem to result in a successful build for the gem.

Same behavior here on Catalina, fresh V8 install. I got a ruby 2.1.2 app with therubyracer 0.12.3, tried several potential solutions, including:

$ gem install therubyracer -- --with-v8-dir=/usr/local/Cellar/v8/7.9.317.31/

My v8 install:

$ brew info v8
v8: stable 7.9.317.31 (bottled)
Google's JavaScript engine
https://github.com/v8/v8/wiki
/usr/local/Cellar/v8/7.9.317.31 (38 files, 38.9MB) *
  Poured from bottle on 2019-12-16 at 18:36:52
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/v8.rb
==> Dependencies
Build: ninja ✘
==> Requirements
Build: xcode ✔
==> Analytics
install: 4,439 (30 days), 11,006 (90 days), 37,352 (365 days)
install-on-request: 3,639 (30 days), 8,713 (90 days), 27,409 (365 days)
build-error: 0 (30 days)

But I always get Libv8::Location::System::NotFoundError (whether I simple do a gem install therubyracer with or without configuration options:

$ gem install therubyracer
Building native extensions. This could take a while...
ERROR:  Error installing therubyracer:
	ERROR: Failed to build gem native extension.

    current directory: /Users/user/.rvm/gems/ruby-2.1.2@project/gems/therubyracer-0.12.3/ext/v8
/Users/user/.rvm/rubies/ruby-2.1.2/bin/ruby -I /Users/user/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0 -r ./siteconf20191217-15965-121s81m.rb extconf.rb
checking for main() in -lpthread... yes
checking for main() in -lobjc... yes
checking for v8.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
	--with-opt-dir
	--with-opt-include
	--without-opt-include=${opt-dir}/include
	--with-opt-lib
	--without-opt-lib=${opt-dir}/lib
	--with-make-prog
	--without-make-prog
	--srcdir=.
	--curdir
	--ruby=/Users/user/.rvm/rubies/ruby-2.1.2/bin/ruby
	--with-pthreadlib
	--without-pthreadlib
	--with-objclib
	--without-objclib
	--enable-debug
	--disable-debug
	--with-v8-dir
	--without-v8-dir
	--with-v8-include
	--without-v8-include=${v8-dir}/include
	--with-v8-lib
	--without-v8-lib=${v8-dir}/lib
/Users/user/.rvm/gems/ruby-2.1.2@project/gems/libv8-3.16.14.19/ext/libv8/location.rb:50:in `configure': By using --with-system-v8, you have chosen to use the version  (Libv8::Location::System::NotFoundError)
of V8 found on your system and *not* the one that is bundled with
the libv8 rubygem.

However, your system version of v8 could not be located.

Please make sure your system version of v8 that is compatible
with 3.16.14.19 installed. You may need to use the
--with-v8-dir option if it is installed in a non-standard location
	from /Users/user/.rvm/gems/ruby-2.1.2@project/gems/libv8-3.16.14.19/lib/libv8.rb:7:in `configure_makefile'
	from extconf.rb:32:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/user/.rvm/gems/ruby-2.1.2@project/extensions/x86_64-darwin-19/2.1.0/therubyracer-0.12.3/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/user/.rvm/gems/ruby-2.1.2@project/gems/therubyracer-0.12.3 for inspection.
Results logged to /Users/user/.rvm/gems/ruby-2.1.2@project/extensions/x86_64-darwin-19/2.1.0/therubyracer-0.12.3/gem_make.out

Same issue here. Just upgraded to Catalina and suddenly have issues. Ruby 2.3.1 app.

$ brew info v8
v8: stable 7.9.317.31 (bottled)
Google's JavaScript engine
https://github.com/v8/v8/wiki
/usr/local/Cellar/v8/7.9.317.31 (38 files, 38.9MB) *
  Poured from bottle on 2019-12-17 at 11:12:39
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/v8.rb
==> Dependencies
Build: ninja ✘
==> Requirements
Build: xcode ✔
==> Analytics
install: 4,439 (30 days), 11,006 (90 days), 37,352 (365 days)
install-on-request: 3,639 (30 days), 8,713 (90 days), 27,409 (365 days)
build-error: 0 (30 days)
$ gem install therubyracer -v '0.12.3' -- --with-v8-include=/usr/local/Cellar/v8/7.9.317.31/libexec/include --with-v8-lib=/usr/local/Cellar/v8/7.9.317.31/libexec
Building native extensions with: '--with-v8-include=/usr/local/Cellar/v8/7.9.317.31/libexec/include --with-v8-lib=/usr/local/Cellar/v8/7.9.317.31/libexec'
This could take a while...
ERROR:  Error installing therubyracer:
   ERROR: Failed to build gem native extension.

   current directory: /Users/scottdudley/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/therubyracer-0.12.3/ext/v8
/Users/scottdudley/.rbenv/versions/2.3.1/bin/ruby -r ./siteconf20191217-52344-fxjmd1.rb extconf.rb --with-v8-include=/usr/local/Cellar/v8/7.9.317.31/libexec/include --with-v8-lib=/usr/local/Cellar/v8/7.9.317.31/libexec
checking for main() in -lpthread... yes
checking for main() in -lobjc... yes
checking for v8.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
   --with-opt-dir
   --without-opt-dir
   --with-opt-include
   --without-opt-include=${opt-dir}/include
   --with-opt-lib
   --without-opt-lib=${opt-dir}/lib
   --with-make-prog
   --without-make-prog
   --srcdir=.
   --curdir
   --ruby=/Users/scottdudley/.rbenv/versions/2.3.1/bin/$(RUBY_BASE_NAME)
   --with-pthreadlib
   --without-pthreadlib
   --with-objclib
   --without-objclib
   --enable-debug
   --disable-debug
   --with-v8-dir
   --without-v8-dir
   --with-v8-include=${v8-dir}/include
   --with-v8-lib=${v8-dir}/lib
/Users/scottdudley/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/libv8-3.16.14.19/ext/libv8/location.rb:50:in `configure': By using --with-system-v8, you have chosen to use the version  (Libv8::Location::System::NotFoundError)
of V8 found on your system and *not* the one that is bundled with
the libv8 rubygem.

However, your system version of v8 could not be located.

Please make sure your system version of v8 that is compatible
with 3.16.14.19 installed. You may need to use the
--with-v8-dir option if it is installed in a non-standard location
   from /Users/scottdudley/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/libv8-3.16.14.19/lib/libv8.rb:7:in `configure_makefile'
   from extconf.rb:32:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

 /Users/scottdudley/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-19/2.3.0-static/therubyracer-0.12.3/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Users/scottdudley/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/therubyracer-0.12.3 for inspection.
Results logged to /Users/scottdudley/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-19/2.3.0-static/therubyracer-0.12.3/gem_make.out

This is what made it work for me under Catalina under Ruby 1.9.3.
I assume this is going to work for all other versions as well:

brew install v8@3.15
bundle config build.libv8 --with-system-v8
bundle config build.therubyracer --with-v8-dir="$(brew --prefix "$LIBV8_VERSION")" --with-v8-include="$(brew --prefix "$LIBV8_VERSION")/include/" --with-v8-lib="$(brew --prefix "$LIBV8_VERSION")/lib/"
bundle install

Generated the following output:

Using stuffed_bunny 1.0.3
Using test-unit 3.2.7
Fetching therubyracer 0.12.3
Installing therubyracer 0.12.3 with native extensions
Fetching time_diff 0.3.0
Installing time_diff 0.3.0

I created a local configuration file for bundler for this project, but should work with the global config as well.

This is what made it work for me under Catalina under Ruby 1.9.3.
I assume this is going to work for all other versions as well:

brew install v8@3.15
bundle config build.libv8 --with-system-v8
bundle config build.therubyracer --with-v8-dir="$(brew --prefix "$LIBV8_VERSION")" --with-v8-include="$(brew --prefix "$LIBV8_VERSION")/include/" --with-v8-lib="$(brew --prefix "$LIBV8_VERSION")/lib/"
bundle install

Generated the following output:

Using stuffed_bunny 1.0.3
Using test-unit 3.2.7
Fetching therubyracer 0.12.3
Installing therubyracer 0.12.3 with native extensions
Fetching time_diff 0.3.0
Installing time_diff 0.3.0

I created a local configuration file for bundler for this project, but should work with the global config as well.

I tried your approach, uninstalling the latest V8 and installing @3.15, but no dice. Same exact error, using bundler config:

build.libv8
Set for the current user (/Users/xxx/.bundle/config): "--with-system-v8"

build.therubyracer
Set for the current user (/Users/xxx/.bundle/config): "--with-v8-dir=/usr/local/Cellar/v8/7.9.317.31 --with-v8-include=/usr/local/Cellar/v8/7.9.317.31/include/ --with-v8-lib=/usr/local/Cellar/v8/7.9.317.31/lib/"

This is what made it work for me under Catalina under Ruby 1.9.3.
I assume this is going to work for all other versions as well:

brew install v8@3.15
bundle config build.libv8 --with-system-v8
bundle config build.therubyracer --with-v8-dir="$(brew --prefix "$LIBV8_VERSION")" --with-v8-include="$(brew --prefix "$LIBV8_VERSION")/include/" --with-v8-lib="$(brew --prefix "$LIBV8_VERSION")/lib/"
bundle install

Generated the following output:

Using stuffed_bunny 1.0.3
Using test-unit 3.2.7
Fetching therubyracer 0.12.3
Installing therubyracer 0.12.3 with native extensions
Fetching time_diff 0.3.0
Installing time_diff 0.3.0

I created a local configuration file for bundler for this project, but should work with the global config as well.

I tried your approach, uninstalling the latest V8 and installing @3.15, but no dice. Same exact error, using bundler config:

build.libv8
Set for the current user (/Users/xxx/.bundle/config): "--with-system-v8"

build.therubyracer
Set for the current user (/Users/xxx/.bundle/config): "--with-v8-dir=/usr/local/Cellar/v8/7.9.317.31 --with-v8-include=/usr/local/Cellar/v8/7.9.317.31/include/ --with-v8-lib=/usr/local/Cellar/v8/7.9.317.31/lib/"

Similar idea but slightly different setup than @coding-bunny answer ended up working for me @bsbodden
https://gist.github.com/fernandoaleman/868b64cd60ab2d51ab24e7bf384da1ca

brew tap homebrew/versions
brew install v8-315

gem install libv8 -v '3.16.14.13' -- --with-system-v8
gem install therubyracer -- --with-v8-dir=/usr/local/opt/v8-315

bundle install

People looking for a quick fix to libv8 build might be interested in my comment under libv8#282.

That didn't work for me at all.
Only got it working with what I wrote above and setting the paths properly using scripts/bundler config when running the installation.

bundle config build.therubyracer --with-v8-dir="$(brew --prefix "$LIBV8_VERSION")" --with-v8-include="$(brew --prefix "$LIBV8_VERSION")/include/" --with-v8-lib="$(brew --prefix "$LIBV8_VERSION")/lib/"

noob programmer here.
Am I supposed to copy and paste this or is there a section of it that is a placeholder only?

bundle config build.therubyracer --with-v8-dir="$(brew --prefix "$LIBV8_VERSION")" --with-v8-include="$(brew --prefix "$LIBV8_VERSION")/include/" --with-v8-lib="$(brew --prefix "$LIBV8_VERSION")/lib/"

noob programmer here.
Am I supposed to copy and paste this or is there a section of it that is a placeholder only?

Assuming you have homebrew installed and the correct libraries, you can just copy & paste it.
The brew --prefix command returns the path to that library, so it will always construct the right path and save it for bundler to use it during gem configuration.

bundle config build.therubyracer --with-v8-dir="$(brew --prefix "$LIBV8_VERSION")" --with-v8-include="$(brew --prefix "$LIBV8_VERSION")/include/" --with-v8-lib="$(brew --prefix "$LIBV8_VERSION")/lib/"

noob programmer here.
Am I supposed to copy and paste this or is there a section of it that is a placeholder only?

Assuming you have homebrew installed and the correct libraries, you can just copy & paste it.
The brew --prefix command returns the path to that library, so it will always construct the right path and save it for bundler to use it during gem configuration.

thanks coding-bunny

Hey Guys, so here is how I fixed it. Uninstalled homebrew, ruby and all gems.

That didn't work for me at all.
Only got it working with what I wrote above and setting the paths properly using scripts/bundler config when running the installation.

Yeah, the solution I discovered relies on environment variables because libv8 gem is very limited in what it allows as arguments during install. Therefore it can’t rely on bundle config build.*. But Bundler doesn’t mess with environment variables so you can do something unusual like this in your shell:

env \
  CXX=clang++ \
  GYPFLAGS=-Dmac_deployment_target=10.9 \
bundle install

You can set bundle config build.libv8 --with-cxx=clang++, but you still have to explicitly set GYPFLAGS environment variable, so it’s even weirder.

I assume most people end up here because their local setup on macOS on Rails projects broke. Most of the people I know use some per-project environment variable setup anyway – using some .env manager, direnv or something like that. I personally prefer having development projects isolated from the rest of my system to some degree. Keeping around some obscure v8 version is less optimal for me than adding another envvar to my project setup. Moreover, that v8 from Homebrew is different version from the one The Ruby Racer relies on which made me nervous ever since I started relying on that fixed version formula from Homebrew months ago and which is why I dug deeper to see what’s going on. I know it works for some. At least people have options before someone finds time to fix this.

That's why I used bundle config build.libv8 --with-system-v8
And I don't have any of the environment variables set for libv8 on my Catalina machine.
The issue I see is that the "solution" is very platform specific.

I tried but got this error 👍

Fetching therubyracer 0.11.0
Installing therubyracer 0.11.0 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/vkuprin/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/therubyracer-0.11.0/ext/v8
/Users/vkuprin/.rbenv/versions/2.6.3/bin/ruby -I /Users/vkuprin/.rbenv/versions/2.6.3/lib/ruby/2.6.0 -r
./siteconf20200610-11249-1fptex4.rb extconf.rb --with-v8-dir\=/usr/local/opt/v8@3.15
checking for -lpthread... yes
checking for -lobjc... yes
checking for v8.h... yes
creating Makefile

current directory: /Users/vkuprin/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/therubyracer-0.11.0/ext/v8
make "DESTDIR=" clean

current directory: /Users/vkuprin/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/therubyracer-0.11.0/ext/v8
make "DESTDIR="
compiling accessor.cc
clang: warning: argument unused during compilation: '-rdynamic' [-Wunused-command-line-argument]
compiling array.cc
clang: warning: argument unused during compilation: '-rdynamic' [-Wunused-command-line-argument]
compiling backref.cc
clang: warning: argument unused during compilation: '-rdynamic' [-Wunused-command-line-argument]
backref.cc:35:50: warning: 'Wrap' is deprecated [-Wdeprecated-declarations]
    v8::Local<v8::Value> wrapper = v8::External::Wrap(this);
                                                 ^
/usr/local/opt/v8@3.15/include/v8.h:2012:3: note: 'Wrap' has been explicitly marked deprecated here
  V8_DEPRECATED(V8_INLINE(static Local<Value> Wrap(void* value)));
  ^
/usr/local/opt/v8@3.15/include/v8.h:88:62: note: expanded from macro 'V8_DEPRECATED'
#define V8_DEPRECATED(declarator) declarator __attribute__ ((deprecated))
                                                             ^
1 warning generated.
compiling constants.cc
clang: warning: argument unused during compilation: '-rdynamic' [-Wunused-command-line-argument]
compiling constraints.cc
clang: warning: argument unused during compilation: '-rdynamic' [-Wunused-command-line-argument]
compiling context.cc
clang: warning: argument unused during compilation: '-rdynamic' [-Wunused-command-line-argument]
context.cc:81:23: warning: 'SetData' is deprecated [-Wdeprecated-declarations]
  Void(Context(self)->SetData(String(data)));
                      ^
/usr/local/opt/v8@3.15/include/v8.h:3835:3: note: 'SetData' has been explicitly marked deprecated here
  V8_DEPRECATED(V8_INLINE(void SetData(Handle<Value> value)));
  ^
/usr/local/opt/v8@3.15/include/v8.h:88:62: note: expanded from macro 'V8_DEPRECATED'
#define V8_DEPRECATED(declarator) declarator __attribute__ ((deprecated))
                                                             ^
context.cc:81:31: error: no viable conversion from 'rr::String' to 'Handle<v8::Value>'
  Void(Context(self)->SetData(String(data)));
                              ^~~~~~~~~~~~
./rr.h:33:20: note: expanded from macro 'Void'
#define Void(expr) expr; return Qnil;
                   ^~~~
/usr/local/opt/v8@3.15/include/v8.h:190:26: note: candidate constructor (the implicit copy constructor) not viable: no known
conversion from 'rr::String' to 'const v8::Handle<v8::Value> &' for 1st argument
template <class T> class Handle {
                         ^
/usr/local/opt/v8@3.15/include/v8.h:212:32: note: candidate template ignored: could not match 'Handle<type-parameter-0-0>'
against 'rr::String'
  template <class S> V8_INLINE(Handle(Handle<S> that))
                               ^
./rr.h:186:11: note: candidate function
  virtual operator VALUE() const {
          ^
./rr.h:443:11: note: candidate function
  virtual operator v8::Handle<v8::String>() const;
          ^
/usr/local/opt/v8@3.15/include/v8.h:4830:37: note: passing argument to parameter 'data' here
void Context::SetData(Handle<Value> data) {
                                    ^
context.cc:85:31: warning: 'GetData' is deprecated [-Wdeprecated-declarations]
  return Value(Context(self)->GetData());
                              ^
/usr/local/opt/v8@3.15/include/v8.h:3829:3: note: 'GetData' has been explicitly marked deprecated here
  V8_DEPRECATED(V8_INLINE(Local<Value> GetData()));
  ^
/usr/local/opt/v8@3.15/include/v8.h:88:62: note: expanded from macro 'V8_DEPRECATED'
#define V8_DEPRECATED(declarator) declarator __attribute__ ((deprecated))
                                                             ^
2 warnings and 1 error generated.
make: *** [context.o] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/vkuprin/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/therubyracer-0.11.0 for
inspection.
Results logged to
/Users/vkuprin/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-19/2.6.0-static/therubyracer-0.11.0/gem_make.out

An error occurred while installing therubyracer (0.11.0), and Bundler cannot continue.
Make sure that `gem install therubyracer -v '0.11.0' --source 'https://rubygems.org/'` succeeds before bundling.

In Gemfile:
  therubyracer

I ran into this today, but noticed that websocket-driver failed to update too, saying it was missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun. Looks like my Mac command line tools got uninstalled with the Catalina update?

Running xcode-select --install fixed both issues for me 😄

Top Tip: Reload your shell (or restart your Mac) for the changes to take effect. I spent far too long trying these out without success before simply restarting and then it all just worked first time. Doh!

lloeki commented

Sorry but this gem is unmaintained, so I will close this issue.

We recommend going with mini_racer + libv8-node. If you feel the issue is still relevant to either of those, please open an issue over there!