Thoughts and tutorials on programming

Thursday, July 23, 2009

How to compile using visual studio for ruby

Extension building in ruby on windows is a little complicated, because the "mainstream" one click installer uses mingw for its build, which is based on a rather outdated msvcrt.dll [version 6 I believe--the one used by Visual Studio 6, no longer in production].

It is, however, according to Charlie Savage, possible to mix code built from newer compilers into it [1].


Mixing runtime libraries
========================

The most obvious criticism of this plan is that it will lead to mixing of microsoft runtime c libraries. From my experience this works as long as extension developers follow the rules described here:

http://msdn.microsoft.com/en-us/library/ms235460(VS.80).aspx

To be more concrete, this boils down to two simple rules:

* If you call ALLOC or ALLOC_N, use xfree and not free
* Don't call sprintf or printf in an extension, instead use rb_f_sprintf/rb_vsprintf/rb_io_printf

If an extension violate these two rules then its obvious, a segmentation fault happens. Thus these bugs are easy to find and easy to fix.

Since VC6 is thankfully no longer available, supporting msvc absolutely, positively requires mixing c runtime libraries and therefore extension writers must follow these two simple rules.

(Note that if you use rb_x_malloc and its siblings, they will use the right free call for you).

i.e. (summarizing) "If it uses ALLOC, xfree, doesn't use STDIN/STDOUT, it can link against any runtime it wants" [though nobu did note there may be a problem with errno's differing, probably not a problem.]

That being said it would appear that you need to also avoid the /MD compiler directive in MS compilers, as well [2].

Also, users may need to download a redistributable for the version of C compiler you used.

However, it should work.
Note that for distributing gems, you can use Luis Lavena's "rake compiler" to build your binaries for you [3].
Good luck!
[1] http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/22727
[2] http://groups.google.com/group/thin-ruby/browse_thread/thread/c15b2472eb97c2ba/ea7c5127035d193b
[3] http://github.com/luislavena/rake-compiler/tree/master ex: ext.cross_platform = ['i386-mswin32', 'i386-mingw32']

7 comments:

Roger Pack said...

and:

Using /MD should be fine.

Actually, it sounded more like to me that they didn't compile the dll correctly. The dll has to have a manifest embedded in it - which the the regular version of Visual Studio does but nmake does not. Or they didn't have the redistibutables installed (don't do in manually, run the Microsoft installation program).

Roger Pack said...

might need to install the redistributable for [whatever compiler you want to use, like vc2009].

kirbson12 said...

http://blogs.law.harvard.edu/hoanga/2006/12/14/getting-a-ruby-c-extension-to-compile-on-windows/
might be useful, as well

Unknown said...
This comment has been removed by a blog administrator.
Roger Pack said...

http://groups.google.com/group/comp.lang.python/msg/e3c0937557dc2a7c

might be helpful, too

Roger Pack said...

apparently "long doubles" are incompatible

http://groups.google.com/group/rubyinstaller/browse_thread/thread/c948e28a72c7f81a/450ddb1540d7f411?lnk=gst&q=python#450ddb1540d7f411

but ruby "doesn't seem to use those"
http://mail.python.org/pipermail/python-dev/2009-July/090739.html

Unknown said...

more fodder:

There might be complications if you use time_t, as well.
"> Also, somewhat unrelated, it appears that long doubles differ in size
> between mingw/msvc 6, and the size of time_t varies from MSVC compiler
> to compiler. Does this mean that using dll's created by those
> compilers might not work with mingw created binaries?


If the APIs of the DLLs includes time_t or long double parameters or
fields in structs pointed to by parameters, etc, then yes indeed."


But I really don't know all the guts.
Presumably if you only used these internally, that would be ok. Something like that.

Contributors

Followers