What is libv8 and Why its Installation Fails
Tags: ruby, rails, bundler, libv8
Published: 2020-06-14 05:38:09


### Background
When I cloned a project and tried to run `bundle install`, I receive the error
```
ERROR: Failed to build gem native extension.
...
fatal error: 'climits' file not found #include <climits>
```

The error is raised when `bundler` tries to require `libv8`, which is in turn required by `therubyracer`.   

If you are reading this article, I believe I can assume that you are having a similar problem. I am going to share my findings here.


### In this blog, we will try to answer the following questions:
1. [Why do we need `libv8`?](#why-do-we-need-libv8)
    - a. [How is it related to `therubyracer`?](#how-is-it-related-to-therubyracer)
2. [Why does installation through `bundle install` fails?](#why-does-installation-through-bundle-install-fails)
3. [How do we fix it?](#how-do-we-fix-it)


### Why do we need `libv8`?
Before we talk about `libv8`, let's first take a look what is [V8](https://v8.dev/)  
> V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++. It is used in Chrome and in Node.js, among others.

So, basically, V8 is the Javascript engine in Chrome. And `libv8` is the ruby interface for the V8 engine used by `therubyracer`.


#### How is it related to `therubyracer`?
The `therubyracer` gem [embeds the V8 Javascript Interpreter into ruby][github-therubyracer]. With it, we can call Javascript functions or use Javascript objects directly in ruby runtime.


### Why does installation through `bundle install` fails?
The installation failed as `therubyracer` gem calls the `libv8` gem, and it fails to build a native extension, i.e. `v8`. I am able to repeat the same bug with:   

```bash
$ 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/billykong/.rvm/gems/ruby-2.6.5/gems/libv8-3.16.14.19/ext/libv8
...
Compiling v8 for x64
Using python 2.7.16
Using compiler: c++ (clang version 11.0.0)
Unable to find a compiler officially supported by v8.
It is recommended to use GCC v4.4 or higher
Beginning compilation. This will take some time.
...
```
The error in your case may be different but still there is one interesting finding here. **The `therubyracer` gem installation script is trying to compile `v8` from source!** I am not saying it is impossible, but I got a feeling that the compilation is the cause of issues for many of us. Just the first few posts I found when I google "libv8 error":    

- [https://stackoverflow.com/questions/19673714/error-installing-libv8-error-failed-to-build-gem-native-extension](https://stackoverflow.com/questions/19673714/error-installing-libv8-error-failed-to-build-gem-native-extension)
- [https://gist.github.com/simonqian/f67c862d06c94fe315d0ba97b711571f](https://gist.github.com/simonqian/f67c862d06c94fe315d0ba97b711571f)
- [https://stackoverflow.com/questions/19577759/installing-libv8-gem-on-os-x-10-9?noredirect=1&lq=1](https://stackoverflow.com/questions/19577759/installing-libv8-gem-on-os-x-10-9?noredirect=1&lq=1)

Compiling something requires all the dependencies to be present. Since `v8` is written in C++ and probably many of us don't have a C++ development environment setup ready for use. Perhaps it is easier just to download a suitable binary of v8 instead of building it from source.


### How do we fix it?
```bash
# 1. Install v8 ourselves
$ brew install v8-315
# 2. Install libv8 using the v8 binary we just installed
$ gem install libv8 -v '3.16.14.19' -- --with-system-v8
# 3. Install therubyracer using the v8 binary we just installed
$ gem install therubyracer -- --with-v8-dir=/usr/local/opt/v8@315
# 4. Install the remaining dependencies
$ bundle install
```
Note: The `--` before the `--with-system-v8` and `--with-v8-dir=/usr/local/opt/v8@315` is necessary when we supply library paths for native extensions, i.e. using specified libraries/binaries instead of building them.


### Conclusion
`therubyracer` or some other gems may requires native extensions to function properly. While some tries to build the extension from source code, it often fails because the dependencies required by the native extensions are not readily installed. We may solve the issues by supplying our own binaries.  

Hope that you have find the information useful. If you find any error or mistake in the above content, please do feel free to leave a comment below.
  
This blog is also published in [billykong.github.io](https://billykong.github.io/ruby/2020/03/17/fixing-libv8-in-osx-catalina.html).

### Reference
1. [https://v8.dev/docs](https://v8.dev/docs) 
2. [https://github.com/rubyjs/libv8](https://github.com/rubyjs/li bv8)
3. [https://github.com/rubyjs/therubyracer](https://github.com/rubyjs/therubyracer)
4. [https://gist.github.com/fernandoaleman/868b64cd60ab2d51ab24e7bf384da1ca](https://gist.github.com/fernandoaleman/868b64cd60ab2d51ab24e7bf384da1ca)
5. [https://guides.rubygems.org/command-reference/](https://guides.rubygems.org/command-reference/)
6. [https://stackoverflow.com/questions/19673714/error-installing-libv8-error-failed-to-build-gem-native-extension](https://stackoverflow.com/questions/19673714/error-installing-libv8-error-failed-to-build-gem-native-extension)
7. [https://gist.github.com/simonqian/f67c862d06c94fe315d0ba97b711571f](https://gist.github.com/simonqian/f67c862d06c94fe315d0ba97b711571f)
8. [https://stackoverflow.com/questions/19577759/installing-libv8-gem-on-os-x-10-9?noredirect=1&lq=1](https://stackoverflow.com/questions/19577759/installing-libv8-gem-on-os-x-10-9?noredirect=1&lq=1)


[libv8-github]: https://github.com/rubyjs/libv8
[github-therubyracer]: https://github.com/rubyjs/therubyracer