Luis Lavena has created rake-compiler
just for this purpose.
However, are you sure that you need a C extension? The thing about C extensions is that every Ruby implementation has their own C extension API (and non-C based ones like XRuby, JRuby, Ruby.NET, IronRuby, HotRuby, MagLev, Red Sun don't have one at all), which means that your C extension will only work on one implementation. And, since MRI only implements Ruby 1.8 and YARV only implements Ruby 1.9, and we are currently in a transition phase between 1.8 and 1.9, chances are that a lot of people will use at least two different implementations. (I personally use 5: MRI, YARV, JRuby, IronRuby and Rubinius.)
Maybe you are better off using Ruby-FFI. Ruby-FFI is an FFI (Foreign Function Interface) for Ruby (duh), which allows you to bind to and map C libraries in pure Ruby in a manner that is portable across Ruby implementations. The FFI API was first developed by Evan Phoenix as the native extension API for Rubinius, it was then adopted by Charles Oliver Nutter (and implemented by Wayne Meissner) for JRuby. Wayne then also wrote the Ruby-FFI gem, which contains C extensions for MRI and YARV. Laurent Sansonetti implemented Ruby-FFI for MacRuby, Marc-André Cournoyer's tinyrb also supports FFI (again written by Wayne Meissner) and the MagLev developers are also working on it. Which means that if you can make your library work with FFI as opposed to a C extension, you will automatically support 6 Ruby implementations instead of just one.
The only reason to use a C extension as opposed to an FFI extension would be, if you really do want some implementation specific behavior. One example of this would be the ParseTree gem, which reaches deep into the intestines of MRI and rips out the in-memory representation of the parse tree.
Last but not least, take a look at the Nice-FFI project by John Croisant, which aims to make using Ruby-FFI even nicer.