From f0959778cfac41e4673117993c3abf26ef1ae76c Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Wed, 23 Jan 2019 22:02:56 +0100 Subject: [PATCH 1/6] Allow to forcibly enable/disable system libffi This lets the user select if system or builtin libffi version shall be used. Default is still "try system libffi and fallback to builtin". The option can be used like so: gem install ffi -- --disable-system-libffi Primary use is to run specs on builtin libffi on Windows in addition to system libffi. --- appveyor.yml | 5 ++++- ext/ffi_c/extconf.rb | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 6b2d8e882..9d7f4bcd3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,11 +12,14 @@ install: - bundle install build: off build_script: - - bundle exec rake compile || bundle exec rake compile + - bundle exec rake 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: "--enable-system-libffi" - RUBYVER: 25-x64 + 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/ From 35049d3dbac240ad039e75073d40e3ae2783bb6c Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Wed, 23 Jan 2019 22:24:19 +0100 Subject: [PATCH 2/6] Update rake dependency to avoid warning on ruby-head rake-10.5.0/lib/rake/application.rb:381: warning: deprecated Object#=~ is called on Proc; it always returns nil --- Gemfile | 2 +- ffi.gemspec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/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 From 9e300987b9391c3995bc7899d1e218a8865d55de Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Thu, 24 Jan 2019 09:07:54 +0100 Subject: [PATCH 3/6] Add task "libffi" to trigger download of the submodule ... and use it in Appveyor-CI. --- Rakefile | 1 + appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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 9d7f4bcd3..3242a4a99 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ install: - bundle install build: off build_script: - - bundle exec rake compile -- %EXTCONFOPTS% || bundle exec rake compile -- %EXTCONFOPTS% + - bundle exec rake libffi compile -- %EXTCONFOPTS% || bundle exec rake compile -- %EXTCONFOPTS% test_script: - bundle exec rake test environment: From 52927e73e29de213bae4696a388519e4f11f0e6d Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Thu, 24 Jan 2019 09:22:15 +0100 Subject: [PATCH 4/6] Appveyor: Run two rubies with system and two more with bundled libffi --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 3242a4a99..958d12c19 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,6 +20,8 @@ environment: - RUBYVER: "head-x64" EXTCONFOPTS: "--disable-system-libffi" - RUBYVER: 24 - EXTCONFOPTS: "--enable-system-libffi" + EXTCONFOPTS: "--disable-system-libffi" - RUBYVER: 25-x64 EXTCONFOPTS: "--enable-system-libffi" + - RUBYVER: 25 + EXTCONFOPTS: "--enable-system-libffi" From 4fc764758ab278bd9f86c883cc227e0d6f80da0b Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Thu, 24 Jan 2019 09:43:51 +0100 Subject: [PATCH 5/6] Fix stdcall closure on Win32 This temporary switches to a forked libffi, until the fixing PR is merged: https://github.com/libffi/libffi/pull/465 Use the following command to update the submodule: git submodule update --init --remote --- .gitmodules | 3 ++- ext/ffi_c/libffi | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) 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/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 From da7b3c2ae198f666707451246238e40d7fd2c3c5 Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Thu, 24 Jan 2019 09:59:40 +0100 Subject: [PATCH 6/6] Avoid copiler warning at sprintf PipeHelperWindows.c:15:5: warning: implicit declaration of function 'sprintf' [-Wimplicit-function-declaration] sprintf( name, "\\\\.\\Pipe\\pipeHelper-%u-%i", ^~~~~~~ --- spec/ffi/fixtures/PipeHelperWindows.c | 1 + 1 file changed, 1 insertion(+) 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])