diff --git a/ext/fiddle/depend b/ext/fiddle/depend index 0513af4801..9146ef07a8 100644 --- a/ext/fiddle/depend +++ b/ext/fiddle/depend @@ -1,7 +1,6 @@ PWD = CONFIGURE_LIBFFI = \ - cd $(LIBFFI_DIR) && \ $(LIBFFI_CONFIGURE) --disable-shared \ --host=$(LIBFFI_ARCH) --enable-builddir=$(arch) \ CC="$(CC)" CFLAGS="$(LIBFFI_CFLAGS)" \ @@ -31,7 +30,7 @@ clean-libffi: distclean-libffi: $(Q) $(SUBMAKE_LIBFFI) distclean $(Q) $(RM) $(LIBFFI_DIR)/local.exp - $(Q) $(RUBY) -rfileutils -e 'FileUtils.rmdir(Dir.glob(ARGV[0]+"/**/"), :parents=>true)' $(LIBFFI_DIR) + $(Q) $(RUBY) -rfileutils -e "FileUtils.rmdir(Dir.glob(ARGV[0]+'/**/'), :parents=>true)" $(LIBFFI_DIR) realclean-libffi: $(Q) $(RMALL) $(LIBFFI_DIR) diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb index ca5fc35496..2bc5b8560d 100644 --- a/ext/fiddle/extconf.rb +++ b/ext/fiddle/extconf.rb @@ -47,25 +47,27 @@ begin libffi.arch = RbConfig::CONFIG['host'] if $mswin $defs << "-DFFI_BUILDING" - libffi.opt = '-C' - cc = "#{libffi.srcdir}/msvcc.sh" - libffi.arch = libffi.arch.sub(/mswin\d+(_\d+)?\z/, 'mingw32') - cc << (libffi.arch.sub!(/^x64/, 'x86_64') ? " -m64" : " -m32") - libffi.ldflags = '' - cxx = cc - ld = "link" - cpp = "cl -nologo -EP" + libffi_config = "#{relative_from($srcdir, '..')}/win32/libffi-config.rb" + config = CONFIG.merge("top_srcdir" => $top_srcdir) + args = $ruby.gsub(/:\/=\\/, '') + args.gsub!(/\)\\/, ')/') + args = args.shellsplit + args.map! {|s| RbConfig.expand(s, config)} + args << '-C' << libffi.dir << libffi_config + opts = {} else - cc = RbConfig::CONFIG['CC'] - ld = RbConfig::CONFIG['LD'] + args = %W[sh #{libffi.srcdir}/configure ] + opts = {chdir: libffi.dir} end - args = %W[ - sh #{libffi.srcdir}/configure + cc = RbConfig::CONFIG['CC'] + cxx = RbConfig::CONFIG['CXX'] + ld = RbConfig::CONFIG['LD'] + args.concat %W[ + --srcdir=#{libffi.srcdir} --disable-shared --host=#{libffi.arch} --enable-builddir=#{RUBY_PLATFORM} ] args << libffi.opt if libffi.opt - args << "CPP=#{cpp}" if cpp args.concat %W[ CC=#{cc} CFLAGS=#{libffi.cflags} CXX=#{cxx} CXXFLAGS=#{RbConfig.expand("$(CXXFLAGS)", nowarn)} @@ -74,8 +76,8 @@ begin FileUtils.rm_f("#{libffi.include}/ffitarget.h") Logging::open do - Logging.message("%p in %s\n", args, libffi.dir) - system(*args, chdir: libffi.dir) or + Logging.message("%p in %p\n", args, opts) + system(*args, **opts) or raise "failed to configure libffi. Please install libffi." end if $mswin && File.file?("#{libffi.include}/ffitarget.h") @@ -131,18 +133,21 @@ end create_makefile 'fiddle' do |conf| if !libffi next conf << "LIBFFI_CLEAN = none\n" - elsif $mswin - submake = "make -C $(LIBFFI_DIR)\n" - elsif $gnumake + elsif $gnumake && !$nmake submake = "$(MAKE) -C $(LIBFFI_DIR)\n" else submake = "cd $(LIBFFI_DIR) && \\\n\t\t" << "#{config_string("exec")} $(MAKE)".strip end + if $nmake + cmd = "$(RUBY) -C $(LIBFFI_DIR) #{libffi_config} --srcdir=$(LIBFFI_SRCDIR)" + else + cmd = "cd $(LIBFFI_DIR) && #$exec $(LIBFFI_SRCDIR)/configure #{libffi.opt}" + end sep = "/" seprpl = config_string('BUILD_FILE_SEPARATOR') {|s| sep = s; ":/=#{s}" if s != "/"} || "" conf << <<-MK.gsub(/^ +| +$/, '') PWD = - LIBFFI_CONFIGURE = $(LIBFFI_SRCDIR#{seprpl})#{sep}configure #{libffi.opt} + LIBFFI_CONFIGURE = #{cmd} LIBFFI_ARCH = #{libffi.arch} LIBFFI_SRCDIR = #{libffi.srcdir} LIBFFI_DIR = #{libffi.dir} diff --git a/ext/fiddle/win32/fficonfig.h b/ext/fiddle/win32/fficonfig.h new file mode 100755 index 0000000000..776808159c --- /dev/null +++ b/ext/fiddle/win32/fficonfig.h @@ -0,0 +1,29 @@ +#define HAVE_ALLOCA 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +#if _MSC_VER >= 1600 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#endif + +#define SIZEOF_DOUBLE 8 +#if defined(X86_WIN64) +#define SIZEOF_SIZE_T 8 +#else +#define SIZEOF_SIZE_T 4 +#endif + +#define STACK_DIRECTION -1 + +#define STDC_HEADERS 1 + +#ifdef LIBFFI_ASM +#define FFI_HIDDEN(name) +#else +#define FFI_HIDDEN +#endif + diff --git a/ext/fiddle/win32/libffi-config.rb b/ext/fiddle/win32/libffi-config.rb new file mode 100755 index 0000000000..ecd3b086c0 --- /dev/null +++ b/ext/fiddle/win32/libffi-config.rb @@ -0,0 +1,47 @@ +#!/usr/bin/ruby +require 'fileutils' + +basedir = File.dirname(__FILE__) +conf = {} +enable = {} +until ARGV.empty? + arg = ARGV.shift + case arg + when '-C' + # ignore + when /\A--srcdir=(.*)/ + conf['SRCDIR'] = srcdir = $1 + when /\A(CC|CFLAGS|CXX|CXXFLAGS|LD|LDFLAGS)=(.*)/ + conf[$1] = $2 + when /\A--host=(.*)/ + host = $1 + when /\A--enable-([^=]+)(?:=(.*))?/ + enable[$1] = $2 || true + when /\A--disable-([^=]+)/ + enable[$1] = false + end +end + +IO.foreach("#{srcdir}/configure.ac") do |line| + if /^AC_INIT\((.*)\)/ =~ line + version = $1.split(/,\s*/)[1] + version.gsub!(/\A\[|\]\z/, '') + conf['VERSION'] = version + break + end +end + +builddir = srcdir == "." ? enable['builddir'] : "." +conf['TARGET'] = /^x64/ =~ host ? "X86_WIN64" : "X86_WIN32" + +FileUtils.mkdir_p([builddir, "#{builddir}/include", "#{builddir}/src/x86"]) +FileUtils.cp("#{basedir}/fficonfig.h", ".", preserve: true) + +hdr = IO.binread("#{srcdir}/include/ffi.h.in") +hdr.gsub!(/@(\w+)@/) {conf[$1] || $&} +hdr.gsub!(/^(#if\s+)@\w+@/, '\10') +IO.binwrite("#{builddir}/include/ffi.h", hdr) + +mk = IO.binread("#{basedir}/libffi.mk.tmpl") +mk.gsub!(/@(\w+)@/) {conf[$1] || $&} +IO.binwrite("Makefile", mk) diff --git a/ext/fiddle/win32/libffi.mk.tmpl b/ext/fiddle/win32/libffi.mk.tmpl new file mode 100755 index 0000000000..621451e7a2 --- /dev/null +++ b/ext/fiddle/win32/libffi.mk.tmpl @@ -0,0 +1,96 @@ +# -*- makefile -*- +# ==================================================================== +# +# libffi Windows Makefile +# +# +# ==================================================================== +# +NAME = ffi +TARGET = @TARGET@ +CC = cl +!if "$(TARGET)" == "X86_WIN64" +AS = ml64 +!else +AS = ml +!endif +AR = link +DLEXT = dll +OBJEXT = obj +LIBEXT = lib +TOPDIR = @SRCDIR@ +CPP = $(CC) -EP +CFLAGS = @CFLAGS@ +ARFLAGS = -lib +ASFLAGS = -coff -W3 -Cx +INCLUDES= -I. -I./include -I./src/x86 \ + -I$(TOPDIR)/include -I$(TOPDIR)/include/src/x86 + +SRCDIR = $(TOPDIR)/src +WORKDIR = ./.libs +BUILDDIR= ./src +LIBNAME = lib$(NAME) +STATICLIB= $(WORKDIR)/$(LIBNAME).$(LIBEXT) + +HEADERS = \ + ./fficonfig.h +FFI_HEADERS = \ + ./include/ffi.h \ + ./include/ffitarget.h + +!if "$(TARGET)" == "X86_WIN32" +OSSRC = win32 +!else if "$(TARGET)" == "X86_WIN64" +OSSRC = win64 +!else +! error unknown target: $(TARGET) +!endif + +OBJECTS = \ + $(BUILDDIR)/closures.$(OBJEXT) \ + $(BUILDDIR)/debug.$(OBJEXT) \ + $(BUILDDIR)/java_raw_api.$(OBJEXT) \ + $(BUILDDIR)/prep_cif.$(OBJEXT) \ + $(BUILDDIR)/raw_api.$(OBJEXT) \ + $(BUILDDIR)/types.$(OBJEXT) \ + $(BUILDDIR)/x86/ffi.$(OBJEXT) \ + $(BUILDDIR)/x86/$(OSSRC).$(OBJEXT) +ASMSRCS = \ + $(BUILDDIR)/x86/$(OSSRC).asm + +.SUFFIXES : .S .asm + +all: $(WORKDIR) $(STATICLIB) + +{$(SRCDIR)}.c{$(BUILDDIR)}.$(OBJEXT): + $(CC) -c $(CFLAGS) $(INCLUDES) -Fo$(@:\=/) -Fd$(WORKDIR)/$(NAME)-src $(<:\=/) + +{$(SRCDIR)/x86}.c{$(BUILDDIR)/x86}.$(OBJEXT): + $(CC) -c $(CFLAGS) $(INCLUDES) -Fo$(@:\=/) -Fd$(WORKDIR)/$(NAME)-src $(<:\=/) + +{$(SRCDIR)/x86}.S{$(BUILDDIR)/x86}.asm: + $(CPP) $(CFLAGS) $(INCLUDES) $(<:\=/) >$(@:\=/) + +{$(BUILDDIR)/x86}.asm{$(BUILDDIR)/x86}.$(OBJEXT): + $(AS) -c $(ASFLAGS) -Fo $(@:\=/) $(<:\=/) + +$(BUILDDIR)/x86/$(OSSRC).asm: $(SRCDIR)/x86/$(OSSRC).S + +$(OBJECTS): $(FFI_HEADERS) $(HEADERS) + +$(WORKDIR): + -@if not exist "$(WORKDIR:/=\)\$(NULL)" mkdir $(WORKDIR:/=\) + +$(STATICLIB): $(WORKDIR) $(OBJECTS) + $(AR) $(ARFLAGS) -out:$(STATICLIB) @<< + $(OBJECTS) +<< + +clean: + -@del /Q $(OBJECTS:/=\) 2>NUL + -@del /Q $(ASMSRCS:/=\) 2>NUL + -@del /Q /S $(WORKDIR:/=\) 2>NUL + +distclean: clean + -@del /Q $(HEADERS:/=\) $(FFI_HEADERS:/=\) 2>NUL + -@del /Q Makefile 2>NUL