diff --git a/.gitmodules b/.gitmodules index fd11f34a2..711d89da6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "ext/ffi_c/libffi"] path = ext/ffi_c/libffi - url = https://github.com/libffi/libffi.git + url = https://github.com/larskanis/libffi.git + branch = fix-stdcall diff --git a/Gemfile b/Gemfile index c2549f786..1662a9784 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' group :development do - gem 'rake', '~> 10.1' + gem 'rake', '~> 12.1' gem 'rake-compiler', '~> 1.0.3' gem 'rake-compiler-dock', '~> 0.7.0' gem 'rspec', '~> 3.0' diff --git a/Rakefile b/Rakefile index 5703c3322..30a8e2251 100644 --- a/Rakefile +++ b/Rakefile @@ -137,6 +137,7 @@ file "ext/ffi_c/libffi/autogen.sh" => "ext/ffi_c/libffi" do warn "Downloading libffi ..." sh "git submodule update --init --recursive" end +task :libffi => "ext/ffi_c/libffi/autogen.sh" LIBFFI_GIT_FILES = `git --git-dir ext/ffi_c/libffi/.git ls-files -z`.split("\x0") diff --git a/appveyor.yml b/appveyor.yml index 6b2d8e882..958d12c19 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,11 +12,16 @@ install: - bundle install build: off build_script: - - bundle exec rake compile || bundle exec rake compile + - bundle exec rake libffi compile -- %EXTCONFOPTS% || bundle exec rake compile -- %EXTCONFOPTS% test_script: - bundle exec rake test environment: matrix: - RUBYVER: "head-x64" + EXTCONFOPTS: "--disable-system-libffi" - RUBYVER: 24 + EXTCONFOPTS: "--disable-system-libffi" - RUBYVER: 25-x64 + EXTCONFOPTS: "--enable-system-libffi" + - RUBYVER: 25 + EXTCONFOPTS: "--enable-system-libffi" diff --git a/ext/ffi_c/extconf.rb b/ext/ffi_c/extconf.rb index 45ab9770f..81dad9832 100644 --- a/ext/ffi_c/extconf.rb +++ b/ext/ffi_c/extconf.rb @@ -3,6 +3,21 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' require 'mkmf' require 'rbconfig' + + def system_libffi_usable? + # We need pkg_config or ffi.h + libffi_ok = pkg_config("libffi") || + have_header("ffi.h") || + find_header("ffi.h", "/usr/local/include", "/usr/include/ffi") + + # Ensure we can link to ffi_call + libffi_ok &&= have_library("ffi", "ffi_call", [ "ffi.h" ]) || + have_library("libffi", "ffi_call", [ "ffi.h" ]) + + # And we need a libffi version recent enough to provide ffi_closure_alloc + libffi_ok &&= have_func("ffi_closure_alloc") + end + dir_config("ffi_c") # recent versions of ruby add restrictive ansi and warning flags on a whim - kill them all @@ -12,17 +27,13 @@ # solaris 10 needs -c99 for $CFLAGS << " -std=c99" if RbConfig::CONFIG['host_os'] =~ /solaris(!?2\.11)/ - if ENV['RUBY_CC_VERSION'].nil? && (pkg_config("libffi") || - have_header("ffi.h") || - find_header("ffi.h", "/usr/local/include", "/usr/include/ffi")) - - # We need at least ffi_call and ffi_closure_alloc - libffi_ok = have_library("ffi", "ffi_call", [ "ffi.h" ]) || - have_library("libffi", "ffi_call", [ "ffi.h" ]) - libffi_ok &&= have_func("ffi_closure_alloc") + # Check whether we use system libffi + system_libffi = enable_config('system-libffi', :try) - # Check if the raw api is available. - $defs << "-DHAVE_RAW_API" if have_func("ffi_raw_call") && have_func("ffi_prep_raw_closure") + if system_libffi == :try + system_libffi = ENV['RUBY_CC_VERSION'].nil? && system_libffi_usable? + elsif system_libffi + abort "system libffi is not usable" unless system_libffi_usable? end have_header('shlwapi.h') @@ -31,23 +42,24 @@ have_func('rb_thread_call_with_gvl') have_func('rb_thread_call_without_gvl') - if libffi_ok + if system_libffi have_func('ffi_prep_cif_var') + $defs << "-DHAVE_RAW_API" if have_func("ffi_raw_call") && have_func("ffi_prep_raw_closure") else $defs << "-DHAVE_FFI_PREP_CIF_VAR" + $defs << "-DUSE_INTERNAL_LIBFFI" end $defs << "-DHAVE_EXTCONF_H" if $defs.empty? # needed so create_header works - $defs << "-DUSE_INTERNAL_LIBFFI" unless libffi_ok $defs << "-DRUBY_1_9" if RUBY_VERSION >= "1.9.0" $defs << "-DFFI_BUILDING" if RbConfig::CONFIG['host_os'] =~ /mswin/ # for compatibility with newer libffi create_header - $LOCAL_LIBS << " ./libffi/.libs/libffi_convenience.lib" if !libffi_ok && RbConfig::CONFIG['host_os'] =~ /mswin/ + $LOCAL_LIBS << " ./libffi/.libs/libffi_convenience.lib" if !system_libffi && RbConfig::CONFIG['host_os'] =~ /mswin/ create_makefile("ffi_c") - unless libffi_ok + unless system_libffi File.open("Makefile", "a") do |mf| mf.puts "LIBFFI_HOST=--host=#{RbConfig::CONFIG['host_alias']}" if RbConfig::CONFIG.has_key?("host_alias") if RbConfig::CONFIG['host_os'].downcase =~ /darwin/ diff --git a/ext/ffi_c/libffi b/ext/ffi_c/libffi index b55baf0b5..024800a13 160000 --- a/ext/ffi_c/libffi +++ b/ext/ffi_c/libffi @@ -1 +1 @@ -Subproject commit b55baf0b500ccc7636a8a55e0506d9da787ad2dd +Subproject commit 024800a1331d38794c24cf191cd74b70af1078a1 diff --git a/ffi.gemspec b/ffi.gemspec index cc0f39535..94a934433 100644 --- a/ffi.gemspec +++ b/ffi.gemspec @@ -27,9 +27,9 @@ Gem::Specification.new do |s| s.license = 'BSD-3-Clause' s.require_paths << 'ext/ffi_c' s.required_ruby_version = '>= 1.9' - s.add_development_dependency 'rake', '~> 10.1' + s.add_development_dependency 'rake', '~> 12.1' s.add_development_dependency 'rake-compiler', '~> 1.0' - s.add_development_dependency 'rake-compiler-dock', '~> 0.6.2' + s.add_development_dependency 'rake-compiler-dock', '~> 0.7.0' s.add_development_dependency 'rspec', '~> 2.14.1' s.add_development_dependency 'rubygems-tasks', "~> 0.2.4" end diff --git a/spec/ffi/fixtures/PipeHelperWindows.c b/spec/ffi/fixtures/PipeHelperWindows.c index 470bacc14..0bdbd2ec8 100644 --- a/spec/ffi/fixtures/PipeHelperWindows.c +++ b/spec/ffi/fixtures/PipeHelperWindows.c @@ -6,6 +6,7 @@ #ifdef _WIN32 #include +#include #include "PipeHelper.h" int pipeHelperCreatePipe(FD_TYPE pipefd[2])