[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[Patch] Compiling Ruby bindings on Windows

From: Joe Swatosh <joe.swatosh_at_gmail.com>
Date: 2006-12-27 08:46:01 CET

Okay, here is a cut a patch that will let the Ruby bindings compile using VC6
and SWIG 1.3.24. I'm dissatisfied because I can't get the tests to run. The
core tests usually pass except for some line ending comparison problems. The
other tests generally cause a segmentation fault:

<Quote>
D:\SVN\src-trunk\subversion\bindings\swig\ruby>ruby -I.ext -Itest
-rtest\my-assertions.rb test\test_client.rb -v
Loaded suite test/test_client
Started
test_add_force(SvnClientTest): E
test_add_no_ignore(SvnClientTest): .
test_add_not_recurse(SvnClientTest): ./.ext/svn/util.rb:68: [BUG]
Segmentation fault
ruby 1.8.4 (2006-04-14) [i386-mswin32]

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
</Quote>

Most failures occur at svn/util.rb:68 where a Proc for a forwarding function is
created. I tried "puts" of the target_method before the "call," but that moved
the SegFault around too. It often claimed to be svn_utf_cstring_to_utf8, but I
couldn't figure out how we were getting there from any of the test code.

So this patch is in no way ready for primetime, but I'm hoping someone will be
interested enough to help me figure something out. In spite of that I tried to
get the format right. If I fouled that up, please let me know about that too.

The test code modifications create a dependency on win32-service which is part
of Win32Utils on RubyForge (http://rubyforge.org/projects/win32utils/) or as a
gem.

Attached find the log of my build attempt complete with 28 warnings. Here are
the versions I'm using:

db4-win32-4.4.20
gettext-0.14.4
httpd-2.0.59
neon-0.26.1
openssl-0.9.7d
svn-win32-libintl
SWIG-1.3.24
zlib123
ruby 1.8.4 (2006-04-14) [i386-mswin32]
VC6 SP6

[[[

Compile the Ruby bindings on Windows with VC6. Get a start on getting the
testing working on Windows.

* subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c
  define a EMPTY_WORKAROUND_FOR_VC6_PREPROCESSOR macro and replace the empty
  space in the argument of every "function-like" macro. Don't define the
  MESSAGES constant when _WIN32 is defined. Use SIZEOF_LONG_LONG instead of
  sizeof(long long).

* subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h
  When building with VC compiler use the #pragma comment directive to link with
  the ruby library.

* subversion/bindings/swig/ruby/test/run-test.rb
  Copy files around to create the directory structure for testing, not using
  links. Create a Service entry for svnserve.

* subversion/bindings/swig/ruby/test/util.rb
  Start and stop the Service, without using fork. Fix typo in URI?

]]]

Index: subversion/bindings/swig/ruby/test/util.rb
===================================================================
--- subversion/bindings/swig/ruby/test/util.rb (revision 22814)
+++ subversion/bindings/swig/ruby/test/util.rb (working copy)
@@ -17,7 +17,7 @@
     @realm = "sample realm"
     @repos_path = File.join("test", "repos")
     @full_repos_path = File.expand_path(@repos_path)
- @repos_uri = "file://#{@full_repos_path}"
+ @repos_uri = "file:///#{@full_repos_path}"
     @svnserve_host = "127.0.0.1"
     @svnserve_ports = (64152..64282).collect{|x| x.to_s}
     @wc_base_dir = File.join("test", "wc-tmp")
@@ -142,6 +142,19 @@
     end
   end

+ if RUBY_PLATFORM =~ /mswin/
+ require 'win32/service'
+
+ def setup_svnserve
+ Win32::Service.start('testsvn')
+ @repos_svnserve_uri = "svn://#{@svnserve_host}"
+ end
+
+ def teardown_svnserve
+ Win32::Service.stop('testsvn')
+ end
+ end
+
   def setup_wc
     teardown_wc
     make_context("").checkout(@repos_uri, @wc_path)
Index: subversion/bindings/swig/ruby/test/run-test.rb
===================================================================
--- subversion/bindings/swig/ruby/test/run-test.rb (revision 22814)
+++ subversion/bindings/swig/ruby/test/run-test.rb (working copy)
@@ -3,6 +3,7 @@
 require "test/unit"
 require "fileutils"

+if RUBY_PLATFORM !~ /mswin/
 ENV["PATH"] = File.join(Dir.pwd, "..", "..", "..", "svnserve") + ":"
+ ENV["PATH"]
 ext_dir = File.join(Dir.pwd, ".ext")
 ext_svn_dir = File.join(ext_dir, "svn")
@@ -12,7 +13,36 @@

 $LOAD_PATH.unshift(ext_dir)
 $LOAD_PATH.unshift(Dir.pwd)
+else
+ require 'win32/file'
+ require 'win32/service'

+ ext_dir = File.join(Dir.pwd, ".ext")
+ ext_svn_dir = File.join(ext_dir, "svn")
+ ext_svn_ext_dir = File.join(ext_svn_dir, "ext")
+ FileUtils.mkdir_p(ext_svn_ext_dir)
+ Dir.glob(File.join(Dir.pwd, "svn", '*.rb')).each do |f|
+ FileUtils.cp(f, File.join(ext_svn_dir, File.basename(f) ) )
+ end
+ Dir.glob(File.join(Dir.pwd,
'..','..','..','..',ENV['build_type'],'subversion','bindings','swig','ruby',
'*.dll')).each do |f|
+ FileUtils.cp(f, File.join(ext_svn_ext_dir, File.basename(f) ) )
+ end
+ repo_dir = File.join(Dir.pwd, "test", "repos")
+ FileUtils.mkdir_p(repo_dir)
+ svnserve_full_path =
File.expand_path(File.join(Dir.pwd,'..','..','..','..','..','svn-win32-1.4.2','bin','svnserve.exe'))
+ Win32::Service.delete('testsvn') rescue Win32::ServiceError
+ s = Win32::Service.new
+ s.create_service{ |s|
+ s.service_name = "testsvn"
+ s.binary_path_name = "\"#{svnserve_full_path}\"".tr('/','\\')
+ s.binary_path_name << " --service"
+ s.binary_path_name << " --root \"#{repo_dir}\"".tr('/','\\')
+ }
+ #at_exit {Win32::Service.delete('testsvn')}
+ #at_exit {FileUtils.rm_rf(ext_dir)}
+ $LOAD_PATH.unshift(ext_dir)
+end
+
 require 'svn/core'
 Svn::Locale.set

Index: subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h
===================================================================
--- subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h (revision
22814)
+++ subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h (working copy)
@@ -16,6 +16,10 @@
 #include "svn_client.h"
 #include "svn_repos.h"

+#ifdef _MSC_VER
+ #pragma comment(lib,"msvcrt-ruby18.lib")
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
Index: subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c
===================================================================
--- subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c (revision
22814)
+++ subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.c (working copy)
@@ -20,6 +20,7 @@
 #define POOL_P(obj) (RTEST(rb_obj_is_kind_of(obj, rb_svn_core_pool())))
 #define CONTEXT_P(obj) (RTEST(rb_obj_is_kind_of(obj, rb_svn_client_context())))
 #define SVN_ERR_P(obj) (RTEST(rb_obj_is_kind_of(obj, rb_svn_error())))
+#define EMPTY_WORKAROUND_FOR_VC6_PREPROCESSOR

 static VALUE mSvn = Qnil;
 static VALUE mSvnClient = Qnil;
@@ -295,7 +296,9 @@
   rb_define_const(mSvnLocale, "ALL", INT2NUM(LC_ALL));
   rb_define_const(mSvnLocale, "COLLATE", INT2NUM(LC_COLLATE));
   rb_define_const(mSvnLocale, "CTYPE", INT2NUM(LC_CTYPE));
+#ifndef _WIN32
   rb_define_const(mSvnLocale, "MESSAGES", INT2NUM(LC_MESSAGES));
+#endif
   rb_define_const(mSvnLocale, "MONETARY", INT2NUM(LC_MONETARY));
   rb_define_const(mSvnLocale, "NUMERIC", INT2NUM(LC_NUMERIC));
   rb_define_const(mSvnLocale, "TIME", INT2NUM(LC_TIME));
@@ -779,21 +782,21 @@
 }

 DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_string,
- c2r_string, , const char *, NULL)
+ c2r_string,
EMPTY_WORKAROUND_FOR_VC6_PREPROCESSOR, const char *, NULL)
 DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_svn_string,
                           c2r_svn_string, &, svn_string_t, NULL)
 DEFINE_APR_ARRAY_TO_ARRAY(static VALUE, c2r_commit_item3_array,
- c2r_client_commit_item3_dup, ,
+ c2r_client_commit_item3_dup,
EMPTY_WORKAROUND_FOR_VC6_PREPROCESSOR,
                           svn_client_commit_item3_t *, NULL)
 DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_prop,
                           c2r_prop_dup, &, svn_prop_t, NULL)
 DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_svn_rev,
                           c2r_long, &, svn_revnum_t, NULL)
 DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_proplist_item,
- c2r_client_proplist_item_dup, ,
+ c2r_client_proplist_item_dup,
EMPTY_WORKAROUND_FOR_VC6_PREPROCESSOR,
                           svn_client_proplist_item_t *, NULL)
 DEFINE_APR_ARRAY_TO_ARRAY(VALUE, svn_swig_rb_apr_array_to_array_external_item,
- c2r_wc_external_item_dup, ,
+ c2r_wc_external_item_dup,
EMPTY_WORKAROUND_FOR_VC6_PREPROCESSOR,
                           svn_wc_external_item_t *, NULL)

 
@@ -2056,10 +2059,10 @@
     cbb.receiver = callbacks;
     cbb.message = rb_id_progress_func();
     cbb.args = rb_ary_new3(2,
- sizeof(apr_off_t) == sizeof(long long) ?
+ sizeof(apr_off_t) == SIZEOF_LONG_LONG ?
                              LL2NUM(progress):
                              LONG2NUM(progress),
- sizeof(apr_off_t) == sizeof(long long) ?
+ sizeof(apr_off_t) == SIZEOF_LONG_LONG ?
                              LL2NUM(total):
                              LONG2NUM(total));
     invoke_callback((VALUE)(&cbb), Qnil);
@@ -2665,7 +2668,7 @@
     cbb.receiver = proc;
     cbb.message = rb_id_call();
     cbb.args = rb_ary_new3(5,
- sizeof(apr_int64_t) == sizeof(long long) ?
+ sizeof(apr_int64_t) == SIZEOF_LONG_LONG ?
                              LL2NUM(line_no):
                              LONG2NUM(line_no),
                            INT2NUM(revision),

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Received on Wed Dec 27 08:46:37 2006

This is an archived mail posted to the Subversion Dev mailing list.