注:大部分代码来源于 rubyinline

#!/usr/bin/env ruby -wKU

# usage: ruby path/to/this/script path/to/your/c/source

require "rbconfig"

class MKCMD

  def self.cmd(base_name)
    new("#{base_name}.c", "#{base_name}.so").cmd
  end

  def initialize(src_name, so_name)
    @src_name = src_name
    @so_name  = so_name
  end

  def cmd
    hdrdir = %w(srcdir includedir archdir rubyhdrdir).map { |name|
      RbConfig::CONFIG[name]
    }.find { |dir|
      dir and File.exist? File.join(dir, "ruby.h")
    } or abort "ERROR: Can't find header dir for ruby. Exiting..."

    config_hdrdir = if RbConfig::CONFIG['rubyarchhdrdir']
      "-I #{RbConfig::CONFIG['rubyarchhdrdir']}"
    elsif RUBY_VERSION > '1.9'
      "-I #{File.join hdrdir, RbConfig::CONFIG['arch']}"
    end

    cmd = [
      RbConfig::CONFIG['LDSHARED'],
      RbConfig::CONFIG['CFLAGS'],
      '-I', hdrdir,
      config_hdrdir,
      '-I', RbConfig::CONFIG['includedir'],
      File.expand_path(@src_name).inspect,
      crap_for_windoze,
      RbConfig::CONFIG['LDFLAGS'],
      RbConfig::CONFIG['CCDLFLAGS'],
    ].compact.join(' ')

    # odd compilation error on clang + freebsd 10. Ruby built w/ rbenv.
    cmd.gsub!(/-Wl,-soname,\$@/, "-Wl,-soname,#{File.basename @so_name}")

    # strip off some makefile macros for mingw 1.9
    cmd.gsub!(/\$\(.*\)/, '') if RUBY_PLATFORM =~ /mingw/

    cmd
  end


  private

  def crap_for_windoze
    # gawd windoze land sucks
    case RUBY_PLATFORM
    when /mswin32/ then
      " -link /OUT:\"#{self.so_name}\" /LIBPATH:\"#{RbConfig::CONFIG['libdir']}\" /DEFAULTLIB:\"#{RbConfig::CONFIG['LIBRUBY']}\" /INCREMENTAL:no /EXPORT:Init_#{module_name}"
    when /mingw32/ then
      c = RbConfig::CONFIG
      " -Wl,--enable-auto-import -L#{c['libdir']} -l#{c['RUBY_SO_NAME']} -o #{@so_name.inspect}"
    when /i386-cygwin/ then
      ' -L/usr/local/lib -lruby.dll'
    else
      ''
    end
  end
end

system MKCMD.cmd((ARGV[0] || gets.chomp).chomp('.c')) if $0 == __FILE__