gem install knife-solo で Error
Chef 実践入門を読み始めた。
Chef実践入門――コードによるインフラ構成の自動化:書籍案内|技術評論社
P.30 に記載されている gem knife-solo install を行った際に、
自身の環境(Max OS X 10.9.5)だと Error が発生したので内容、原因、対応をメモ。
Error 内容
$ gem install knife-solo Building native extensions. This could take a while... ERROR: Error installing knife-solo: ERROR: Failed to build gem native extension. /Users/kenya/.rbenv/versions/2.1.1/bin/ruby extconf.rb creating Makefile /Users/kenya/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/libyajl2-1.1.0/ext/libyajl2 extconf.rb:104:in `makemakefiles': unhandled exception from extconf.rb:138:in `<main>' extconf failed, exit code 1 Gem files will remain installed in /Users/kenya/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/libyajl2-1.1.0 for inspection. Results logged to /Users/kenya/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/extensions/x86_64-darwin-13/2.1.0-static/libyajl2-1.1.0/gem_make.out
Error 原因
Error が発生している extconf.rb ファイルを開いてみる。
# extconf.rb require 'rbconfig' require 'fileutils' if ENV["USE_SYSTEM_LIBYAJL2"] File.open("Makefile", "w+") do |f| f.write <<EOF # dummy Makefile when we're not really installing all: \ttrue install: \ttrue EOF end exit(0) end module Libyajl2Build class BuildError < StandardError; end LIBYAJL2_VENDOR_DIR = File.expand_path("../vendor/yajl", __FILE__).freeze PREFIX = File.expand_path("../../../lib/libyajl2/vendored-libyajl2", __FILE__).freeze def self.windows? !!(RUBY_PLATFORM =~ /mswin|mingw|windows/) end def self.libyajl2_vendor_dir LIBYAJL2_VENDOR_DIR end def self.prefix PREFIX end def self.deps require 'mkmf' end def self.setup_env RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC'] # set some sane defaults if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc|clang/ # magic flags copied from upstream yajl build system (-std=c99 is necessary for older gcc) $CFLAGS << " -std=c99 -pedantic -Wpointer-arith -Wno-format-y2k -Wstrict-prototypes -Wmissing-declarations -Wnested-externs -Wextra -Wundef -Wwrite-strings -Wold-style-definition -Wredundant-decls -Wno-unused-parameter -Wno-sign-compare -Wmissing-prototypes" $CFLAGS << " -O2" # match what the upstream uses for optimization # create the implib on windows if windows? $LDFLAGS << " -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--out-implib=libyajldll.a -Wl,--output-def,libyajl.def" end end $CFLAGS << " -DNDEBUG" end def self.makemakefiles if RUBY_PLATFORM == "java" File.open("Makefile", "w+") do |f| f.write <<EOF CC = gcc TARGET = libyajl DLLIB = $(TARGET).so CFLAGS = -I. -I../../../../ext/libyajl2 -fPIC -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration -fPIC -std=c99 -pedantic -Wpointer-arith -Wno-format-y2k -Wstrict-prototypes -Wmissing-declarations -Wnested-externs -Wextra -Wundef -Wwrite-strings -Wold-style-definition -Wredundant-decls -Wno-unused-parameter -Wno-sign-compare -Wmissing-prototypes -O2 -DNDEBUG LDFLAGS = -L. -fstack-protector -rdynamic #LIBS = -lpthread -ldl -lcrypt -lm -lc LIBS = -lpthread -ldl -lm -lc OBJS = yajl_alloc.o yajl_tree.o yajl_gen.o yajl_buf.o yajl.o yajl_encode.o yajl_lex.o yajl_parser.o yajl_version.o all: $(DLLIB) $(DLLIB): $(OBJS) \t$(CC) -shared -o $(DLLIB) $(OBJS) $(LDFLAGS) $(LIBS) %.o: ../../../../ext/libyajl2/%.c \t$(COMPILE.c) $(OUTPUT_OPTION) $< install: \tmkdir -p #{prefix}/lib \tcp $(DLLIB) #{prefix}/lib/$(DLLIB) \tmkdir -p #{prefix}/include/yajl \tcp yajl/*.h #{prefix}/include/yajl EOF end else deps setup_env dir_config("libyajl") create_makefile("libyajl") # on windows the Makefile will try to export Init_libyajl which is wrong because we aren't a ruby lib. # i could not figure out how to tell mkmf.rb to stop being so helpful, so instead will just patch it here. if windows? makefile = IO.read("Makefile") makefile.gsub!(/\$\(DEFFILE\)/, '') File.open("Makefile", 'w+') {|f| f.write(makefile) } end system("pwd") # we cheat and build it right away... system("make >make.out 2>&1") || raise # rubinius doesn't like the output this generates # ...so we can hack up what install does later and copy over the include files File.open("Makefile", "w+") do |f| f.write <<EOF TARGET = libyajl DLLIB = $(TARGET).#{RbConfig::MAKEFILE_CONFIG['DLEXT']} all: EOF if windows? f.write <<EOF install: \tmkdir -p #{prefix}/lib \tcp libyajl.so #{prefix}/lib/libyajl.so \tcp libyajldll.a #{prefix}/lib/libyajldll.a \tcp libyajl.def #{prefix}/lib/libyajl.def \tmkdir -p #{prefix}/include/yajl \tcp yajl/*.h #{prefix}/include/yajl EOF else f.write <<EOF install: \tmkdir -p #{prefix}/lib \tcp $(DLLIB) #{prefix}/lib/$(DLLIB) \tmkdir -p #{prefix}/include/yajl \tcp yajl/*.h #{prefix}/include/yajl EOF end end end end end Libyajl2Build.makemakefiles
該当の 104 行目を見てみると ruby から make コマンドを叩いていた。
周辺のコードも読めないなりに読んでみる。
makefile を作成時に C プログラムをコンパイルするプログラムに gcc を設定していることが解る。
エラーメッセージは unhandled exception。
そもそもの事前準備が整ってないのでは?と思いだす。
gcc コマンド使えるのかなと思って、gcc の version 確認をしてみることに。
Error 対応
sudo gcc --version You have not agreed to the Xcode license agreements. You must agree to both license agreements below in order to use Xcode. Hit the Enter key to view the license agreements at '/Applications/Xcode.app/Contents/Resources/English.lproj/License.rtf' ~ 長いので途中を省略 ~ By typing 'agree' you are agreeing to the terms of the software license agreements. Type 'print' to print them or anything else to cancel, [agree, print, cancel]
… Xcode のライセンスに同意してなかったようだ。間抜けだなー。
あとは、言われた通りに Enter key を押下して英語の同意書を確認していく。
最後まで確認していくと、同意をするのなら agree と入力して下さいとあるので agree と入力。
gcc のバージョンを確認後、再度 gem knife-solo install を実行。
今度は無事にインストールされた。
# gcc のバージョン確認 $ sudo gcc --version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn) Target: x86_64-apple-darwin13.4.0 Thread model: posix # knife-solo のインストール $ gem install knife-solo Thanks for installing knife-solo! If you run into any issues please let us know at: https://github.com/matschaffer/knife-solo/issues If you are upgrading knife-solo please uninstall any old versions by running `gem clean knife-solo` to avoid any errors. See http://bit.ly/CHEF-3255 for more information on the knife bug that causes this. Successfully installed knife-solo-0.4.2 Parsing documentation for knife-solo-0.4.2 Installing ri documentation for knife-solo-0.4.2 Done installing documentation for knife-solo after 1 seconds 1 gem installed # knife が正常にインストールされているか確認 $ gem list | grep knife knife-solo (0.4.2)
rbenv を使用している場合は rbenv rehash を忘れずに。
rbenv rehash を忘れがちな場合は、下記をインストールするのもありかと思った。