diff --git a/.gitignore b/.gitignore index 0e599bf..df576a3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ pkg/* tmp/* lib/libv8/build/* lib/libv8/VERSION +/ext/libv8/.location.yml diff --git a/Rakefile b/Rakefile index ed8bfa5..ebd3641 100644 --- a/Rakefile +++ b/Rakefile @@ -63,7 +63,10 @@ task :binary => :compile do gemspec = get_binary_gemspec gemspec.extensions.clear # We don't need most things for the binary - gemspec.files = ['lib/libv8.rb', 'ext/libv8/arch.rb', 'lib/libv8/version.rb'] + gemspec.files = [] + gemspec.files += ['lib/libv8.rb', 'lib/libv8/version.rb'] + gemspec.files += ['ext/libv8/arch.rb', 'ext/libv8/location.rb', 'ext/libv8/paths.rb'] + gemspec.files += ['ext/libv8/.location.yml'] # V8 gemspec.files += Dir['vendor/v8/include/*'] gemspec.files += Dir['vendor/v8/out/**/*.a'] diff --git a/ext/libv8/builder.rb b/ext/libv8/builder.rb new file mode 100644 index 0000000..bfac715 --- /dev/null +++ b/ext/libv8/builder.rb @@ -0,0 +1,20 @@ +require 'libv8/compiler' +require 'libv8/arch' +require 'libv8/make' + +module Libv8 + class Builder + include Libv8::Arch + include Libv8::Compiler + include Libv8::Make + + def build_libv8! + profile = enable_config('debug') ? 'debug' : 'release' + + Dir.chdir(File.expand_path '../../../vendor/v8', __FILE__) do + puts `env CXX=#{compiler} LINK=#{compiler} #{make} #{libv8_arch}.#{profile} GYPFLAGS="-Dhost_arch=#{libv8_arch}"` + end + return $?.exitstatus + end + end +end diff --git a/ext/libv8/extconf.rb b/ext/libv8/extconf.rb index 87eaddb..9d25a4f 100644 --- a/ext/libv8/extconf.rb +++ b/ext/libv8/extconf.rb @@ -1,16 +1,7 @@ require 'mkmf' create_makefile('libv8') -require File.expand_path '../arch.rb', __FILE__ -require File.expand_path '../make.rb', __FILE__ -require File.expand_path '../compiler.rb', __FILE__ -include Libv8::Arch -include Libv8::Make -include Libv8::Compiler +require File.expand_path '../location', __FILE__ +location = with_config('system-v8') ? Libv8::Location::System.new : Libv8::Location::Vendor.new -profile = enable_config('debug') ? 'debug' : 'release' - -Dir.chdir(File.expand_path '../../../vendor/v8', __FILE__) do - puts `env CXX=#{compiler} LINK=#{compiler} #{make} #{libv8_arch}.#{profile} GYPFLAGS="-Dhost_arch=#{libv8_arch}"` -end -exit $?.exitstatus +exit location.install! diff --git a/ext/libv8/location.rb b/ext/libv8/location.rb new file mode 100644 index 0000000..6994bfa --- /dev/null +++ b/ext/libv8/location.rb @@ -0,0 +1,81 @@ +require 'yaml' +require 'pathname' +require File.expand_path '../paths', __FILE__ + +module Libv8 + class Location + def install! + File.open(Pathname(__FILE__).dirname.join('.location.yml'), "w") do |f| + f.write self.to_yaml + end + return 0 + end + + def self.load! + File.open(Pathname(__FILE__).dirname.join('.location.yml')) do |f| + YAML.load f + end + end + + class Vendor < Location + def install! + require File.expand_path '../builder', __FILE__ + builder = Libv8::Builder.new + exit_status = builder.build_libv8! + super if exit_status == 0 + verify_installation! + return exit_status + end + def configure(context = MkmfContext.new) + context.incflags.insert 0, Libv8::Paths.include_paths.map{|p| "-I#{p}"}.join(" ") + " " + context.ldflags.insert 0, Libv8::Paths.object_paths.join(" ") + " " + end + + def verify_installation! + Libv8::Paths.object_paths.each do |p| + fail ArchiveNotFound, p unless File.exists? p + end + end + + class ArchiveNotFound < StandardError + def initialize(filename) + super "libv8 did not install properly, expected binary v8 archive '#{filename}'to exist, but it was not found" + end + end + end + + class System < Location + def configure(context = MkmfContext.new) + context.dir_config('v8') + context.find_header('v8.h') or fail NotFoundError + end + + class NotFoundError < StandardError + def initialize(*args) + super(<<-EOS) +You have chosen to use the version of V8 found on your system +and *not* the one that is bundle with the libv8 rubygem. However, +it could not be located. please make sure you have a version of +v8 that is compatible with #{Libv8::VERSION} installed. You may +need to special --with-v8-dir options if it is in a non-standard +location + +thanks, +The Mgmt + +EOS + end + end + end + + class MkmfContext + def incflags + $INCFLAGS + end + + def ldflags + $LDFLAGS + end + end + end +end diff --git a/ext/libv8/paths.rb b/ext/libv8/paths.rb new file mode 100644 index 0000000..f81b582 --- /dev/null +++ b/ext/libv8/paths.rb @@ -0,0 +1,38 @@ +require 'rbconfig' +require File.expand_path '../arch', __FILE__ + +module Libv8 + module Paths + module_function + + def include_paths + ["#{vendored_source_path}/include"] + end + + def object_paths + [libv8_object(:base), libv8_object(:snapshot)] + end + + def config + RbConfig::MAKEFILE_CONFIG + end + + def libv8_object(name) + filename = "#{libv8_profile}/libv8_#{name}.#{config['LIBEXT']}" + unless File.exists? filename + filename = "#{libv8_profile}/obj.target/tools/gyp/libv8_#{name}.#{config['LIBEXT']}" + end + return filename + end + + def libv8_profile + base = "#{vendored_source_path}/out/#{Libv8::Arch.libv8_arch}" + debug = "#{base}.debug" + File.exists?(debug) ? debug : "#{base}.release" + end + + def vendored_source_path + File.expand_path "../../../vendor/v8", __FILE__ + end + end +end diff --git a/lib/libv8.rb b/lib/libv8.rb index f017b5a..1904b75 100644 --- a/lib/libv8.rb +++ b/lib/libv8.rb @@ -1,61 +1,9 @@ -require 'rbconfig' +require 'libv8/version' +require 'libv8/location' -require 'libv8/arch' module Libv8 - - module_function - - def config - Config::MAKEFILE_CONFIG - end - - def libv8_object(name) - filename = "#{libv8_profile}/libv8_#{name}.#{config['LIBEXT']}" - unless File.exists? filename - filename = "#{libv8_profile}/obj.target/tools/gyp/libv8_#{name}.#{config['LIBEXT']}" - end - return filename - end - - def libv8_profile - base = "#{libv8_source_path}/out/#{Libv8::Arch.libv8_arch}" - debug = "#{base}.debug" - File.exists?(debug) ? debug : "#{base}.release" - end - - def libv8_base - libv8_object :base - end - - def libv8_snapshot - libv8_object :snapshot - end - - def libv8_nosnapshot - libv8_object :nosnapshot - end - - def libv8_objects(*names) - names = [:base, :snapshot] if names.empty? - names.map do |name| - fail "no libv8 object #{name}" unless File.exists?(object = libv8_object(name)) - object - end - end - - def libv8_ldflags - "-L#{libv8_base} -L#{libv8_snapshot}" - end - - def libv8_include_flags - "-I#{libv8_include_path}" - end - - def libv8_include_path - "#{libv8_source_path}/include" - end - - def libv8_source_path - File.expand_path "../../vendor/v8", __FILE__ + def self.configure_makefile + location = Location.load! + location.configure end end diff --git a/lib/libv8/version.rb b/lib/libv8/version.rb index f89d33f..a47fd9a 100644 --- a/lib/libv8/version.rb +++ b/lib/libv8/version.rb @@ -1,3 +1,3 @@ module Libv8 - VERSION = "3.11.8.3" + VERSION = "3.11.8.5" end diff --git a/libv8.gemspec b/libv8.gemspec index 1c1080e..55775cf 100644 --- a/libv8.gemspec +++ b/libv8.gemspec @@ -24,7 +24,8 @@ Gem::Specification.new do |s| s.extensions = ["ext/libv8/extconf.rb"] s.require_paths = ["lib", "ext"] - s.add_development_dependency "rake", "~> 0.9.2" + s.add_development_dependency "rake" s.add_development_dependency "rake-compiler" s.add_development_dependency "rspec" + s.add_development_dependency "rspec-spies" end diff --git a/spec/libv8_spec.rb b/spec/libv8_spec.rb deleted file mode 100644 index 8397456..0000000 --- a/spec/libv8_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'spec_helper' -require 'pathname' - -describe Libv8 do - include Libv8 - - it "can find the static library components" do - Pathname(libv8_base).should exist - Pathname(libv8_snapshot).should exist - end - - it "has a valid include path" do - Pathname(libv8_include_path).should be_exist - end - - it "can retrieve objects by name" do - libv8_objects(:base, :snapshot).each do |obj| - Pathname(obj).should exist - end - end - -end diff --git a/spec/location_spec.rb b/spec/location_spec.rb new file mode 100644 index 0000000..1ce952e --- /dev/null +++ b/spec/location_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe "libv8 locations" do + before do + @context = mock(:CompilationContext) + end + describe "the system location" do + before do + @location = Libv8::Location::System.new + @context.stub(:dir_config) + end + describe "configuring a compliation context with it" do + before do + @context.stub(:find_header) {true} + @location.configure @context + end + it "adds the include path to the front of the include flags" do + @context.should have_received(:dir_config).with 'v8' + @context.should have_received(:find_header).with 'v8.h' + end + end + describe "when the v8.h header cannot be found" do + before do + @context.stub(:find_header) {false} + end + it "raises a NotFoundError" do + expect {@location.configure @context}.to raise_error Libv8::Location::System::NotFoundError + end + end + end + + describe "the vendor location" do + before do + @location = Libv8::Location::Vendor.new + @context.stub(:incflags) {@incflags ||= "-I/usr/include -I/usr/local/include"} + @context.stub(:ldflags) {@ldflags ||= "-lobjc -lpthread"} + + Libv8::Paths.stub(:include_paths) {["/frp/v8/include"]} + Libv8::Paths.stub(:object_paths) {["/frp/v8/obj/libv8_base.a", "/frp/v8/obj/libv8_snapshot.a"]} + @location.configure @context + end + + it "prepends its own incflags before any pre-existing ones" do + @context.incflags.should eql "-I/frp/v8/include -I/usr/include -I/usr/local/include" + end + + it "prepends the locations of any libv8 objects on the the ldflags" do + @context.ldflags.should eql "/frp/v8/obj/libv8_base.a /frp/v8/obj/libv8_snapshot.a -lobjc -lpthread" + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 05c0788..9e6d775 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,2 +1,4 @@ $:.unshift File.expand_path '../../lib', __FILE__ -require 'libv8' \ No newline at end of file +require 'rspec' +require 'rspec-spies' +require 'libv8'