-
-
Save SteveBenner/de51738222e92d606487 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby | |
# | |
# Mac fix 1 - Install the Nokogiri gem on Mac OS 10.9 Mavericks | |
# | |
# Usage: to configure and install using Bundler, pass in 'bundle' as an argument to the script. | |
# | |
# Nokogiri works at a very low level, so it has many issues on various platforms. | |
# As a result, the command `install gem nokogiri` often will fail. This fix is for | |
# errors involving 'libiconv', such as the following one I encountered: | |
# | |
# > libiconv is missing. please visit http://nokogiri.org/tutorials/installing_nokogiri.html | |
# > for help with installing dependencies. | |
# > ----- | |
# > *** 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. | |
# | |
# This script is basically just carrying out the install process illustrated on the | |
# Nokogiri website, specifically for OS X 10.9. Other systems are not covered. | |
# More information can be found at: http://nokogiri.org/tutorials/installing_nokogiri.html | |
# | |
# Some additional resources I came across while troubleshooting this issue: | |
# - http://stackoverflow.com/questions/5528839/why-does-installing-nokogiri-on-mac-os-fail-with-libiconv-is-missing | |
# - http://stackoverflow.com/questions/23401174/nokogiri-gem-fails-to-install-in-os-x-mavericks | |
# - http://stackoverflow.com/questions/19643153/error-to-install-nokogiri-on-osx-10-9-maverick | |
# - http://jasdeep.ca/2013/10/installing-nokogiri-fails-os-x-mavericks/ | |
# | |
# NOTE: | |
# There are many factors involved in Nokogiri's installation. This script was tested | |
# on a system with the following characteristics and installations: | |
# | |
# - Mac OS X 10.9.4 | |
# - 'xcode-select' installed | |
# - Homebrew 0.9.5 | |
# - Ruby 2.1.2 | |
# - Nokogiri 1.6.3.1 | |
# There are three libraries required to compile Nokogiri's native extensions | |
libs = %w[libxml2 libxslt libiconv] | |
# Install and link them using Homebrew | |
`brew update` | |
%w[install link].each { |command| `brew #{command} #{libs.join(' ')}` } | |
# Use the latest versions of installed libraries from your Homebrew installation | |
paths = libs.inject({}) do |libs, lib| | |
# It's easy to find the library paths using the 'brew' executable, but keep in mind | |
# they are just symlinks; the real installation path may vary from system to system. | |
libs[lib.to_sym] = File.realpath `brew --prefix #{lib}`.chomp | |
libs | |
end | |
# If you have any Nokogiri gem files, they need to be removed obviously | |
`gem uninstall nokogiri` | |
# Install Nokogiri gem using either RubyGems or Bundler (defaults to RubyGems) | |
flags = [ | |
'--', | |
"--with-xml2-dir=#{paths[:libxml2]}", | |
"--with-xslt-dir=#{paths[:libxslt]}", | |
"--with-iconv-dir=#{paths[:libxml2]}", | |
"--with-xml2-config=#{paths[:libxml2]}/bin/xml2-config", | |
"--with-xslt-config=#{paths[:libxslt]}/bin/xslt-config" | |
] | |
if ARGV[0] == 'bundle' | |
`bundle config build.nokogiri #{flags.drop(1).join(' ')}` | |
print `bundle exec install nokogiri` | |
else | |
print `gem install nokogiri #{flags.join(' ')}` | |
end | |
puts | |
puts "Mac 'Nokogiri installation' fix applied successfully! Latest version at:"\ | |
"https://gist.github.com/SteveBenner/de51738222e92d606487" |
latest ruby 2.1.2 via rvm gives
add-air:code add$ ./macfix1-install-nokogiri.rb
./macfix1-install-nokogiri.rb:44:in `block in <main>': undefined method `shelljoin' for ["libxml2", "libxslt", "libiconv"]:Array (NoMethodError)
from ./macfix1-install-nokogiri.rb:44:in `each'
from ./macfix1-install-nokogiri.rb:44:in `<main>'
Ruby 2.0.0p451, same issue.
james$ ./macfix1-install-nokogiri.rb bundle
./macfix1-install-nokogiri.rb:44:in `block in <main>': undefined method `shelljoin' for ["libxml2", "libxslt", "libiconv"]:Array (NoMethodError)
from ./macfix1-install-nokogiri.rb:44:in `each'
from ./macfix1-install-nokogiri.rb:44:in `<main>'
So fork it, add the require, and send him a pull request. C'mon guys.
Haha, FAIL. I must have been up late writing this one; I know exactly what happened... I use the Shellwords
module quite a bit, so dropping Array#shelljoin
in there was just automatic for me. Before posting the script though, to polish it I went through and removed the dependency on shellwords
, because less dependencies == better code… And of course I forgot that one method. Glancing at the arguments, you’ll notice that it’s totally unnecessary—they don’t contain any special characters or anything—so I just swapped it for regular Array#join
.
Error: No available formula for libxml2libxsltlibiconv
Error: No such keg: /usr/local/Cellar/libxml2libxsltlibiconv
./macfix1-install-nokogiri.rb:50:in `block in <main>': undefined method `Pathname' for main:Object (NoMethodError)
from ./macfix1-install-nokogiri.rb:47:in `each'
from ./macfix1-install-nokogiri.rb:47:in `inject'
from ./macfix1-install-nokogiri.rb:47:in `<main>'
Thanks @newton108 for discovering two more errors. I do want people to run the script flawlessly of course, but it’s a rather informal script and testing it is low on my priority list for now. Any errors should be _extremely_ easy to fix, and in fact I did note in a comment that Pathname
was not required.
I got this error:
Error: No available formula for libiconv Apple distributes libiconv with OS X, you can find it in /usr/lib. Some build scripts fail to detect it correctly, please check existing formulae for solutions. Error: No such keg: /usr/local/Cellar/libxml2 ./macfix1-install-nokogiri.rb:50:in 'realpath': No such file or directory @ realpath_rec - /usr/local/Cellar/libxml2 (Errno::ENOENT) from ./macfix1-install-nokogiri.rb:50:in 'block in <main>' from ./macfix1-install-nokogiri.rb:47:in 'each' from ./macfix1-install-nokogiri.rb:47:in 'inject' from ./macfix1-install-nokogiri.rb:47:in '<main>'
When running brew link libxml2
manually got:
Warning: libxml2 is keg-only and must be linked with --force Note that doing so can interfere with building software.
This is Ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]
on OS X 10.9.5
Was able to get it working with this command: --use-system-libraries --with-xml2-config=/usr/local/opt/libxml2/bin/xml2-config
On new image of Yosemite (with no additional gcc from brew), nokogiri would not build.
It is likely only this command need be run: xcode-select --install
gem uninstall nokogiri
was recommended by other sources but probably not necessary.
The only action taken previous to above command was brew install libxml2
, however I imagine it was not necessary either. Nor part of the solution.
Thanks imme550! That helped me too. Only the file paths were different (I'm on 10.6.8 instead of 10.9):
gem install nokogiri -- --use-system-libraries --with-xml2-config=/usr/bin/xml2-config --with-xslt-config=/usr/bin/xslt-config
Thanks Steve Benner, this (mostly) worked for me. I had to add --use-system-libraries
and --with-xml2-include=/usr/local/opt/libxml2/include/libxml2
after the --
, and I skipped the brew link [library]
.
The full command was:
sudo gem install nokogiri -- --use-system-libraries --with-xslt-dir=/usr/local/opt/libxslt --with-iconv-dir=/usr/local/opt/libiconv --with-xml2-dir=/usr/local/opt/libxml2 --with-xml2-config=/usr/local/opt/libxml2/bin/xml2-config --with-xml2-include=/usr/local/opt/libxml2/include/libxml2 --with-xslt-config=/usr/local/opt/libxslt/bin/xslt-config
@krzysztofmajewski this was a working command for El Capitan. Thanks for that.
Thanks @krzysztofmajewski! Worked great for install Nokogiri 1.6.6.2 (just had to add the version number to the command nokogiri -v 1.6.6.2
You’ve really got to pick up your game, Apple! Installing one of the most essential gems in the Rubyverse has never been so complex and failure-prone as with the latest Mac OS releases… Luckily, we have amazing tools like Homebrew that come to our rescue. This script leverages the modern Homebrew ecosystem to fix Nokogiri installation issues in a few lines of Ruby—mostly a matter of pointing the gem installer at the modern libraries and tools provided by the open-source community, instead of Apple’s dated versions.
I hope this can be useful to others, as it has been to me. Contributions are welcomed!
Usage:
chmod u+x macfix1-install-nokogiri.rb
./Users/you/macfix1-install-nokogiri.rb
, or if the file is in your current working directory, you should use:./macfix1-install-nokogiri.rb
.ln -s <path-to-script> /usr/local/bin/install-nokogiri
to symbolically link it into my executables directory. Now I can just callinstall-nokogiri
in the shell, like any other command.Installing with Bundler
By default, the script installs Nokogiri with RubyGems. To configure and install with Bundler, simply pass
bundle
as an argument.