class Rake::ExtensionTask

def define_native_tasks(for_platform = nil, ruby_ver = RUBY_VERSION, callback = nil)

def define_native_tasks(for_platform = nil, ruby_ver = RUBY_VERSION, callback = nil)
  platf = for_platform || platform
  # tmp_path
  tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}"
  stage_path = "#{@tmp_dir}/#{platf}/stage"
  # lib_path
  lib_path = lib_dir
  # create 'native:gem_name' and chain it to 'native' task
  unless Rake::Task.task_defined?("native:#{@gem_spec.name}:#{platf}")
    task "native:#{@gem_spec.name}:#{platf}" do |t|
      # FIXME: workaround Gem::Specification limitation around cache_file:
      # http://github.com/rubygems/rubygems/issues/78
      spec = gem_spec.dup
      spec.instance_variable_set(:"@cache_file", nil) if spec.respond_to?(:cache_file)
      # adjust to specified platform
      spec.platform = Gem::Platform.new(platf)
      # clear the extensions defined in the specs
      spec.extensions.clear
      # add the binaries that this task depends on
      ext_files = []
      # go through native prerequisites and grab the real extension files from there
      t.prerequisites.each do |ext|
        # strip stage path and keep lib/... only
        ext_files << ext.sub(stage_path+"/", '')
      end
      # include the files in the gem specification
      spec.files += ext_files
      # expose gem specification for customization
      if callback
        callback.call(spec)
      end
      # Generate a package for this gem
      pkg = Gem::PackageTask.new(spec) do |pkg|
        pkg.need_zip = false
        pkg.need_tar = false
        # Do not copy any files per PackageTask, because
        # we need the files from the staging directory
        pkg.package_files.clear
      end
      # Copy from staging directory to gem package directory.
      # This is derived from the code of Gem::PackageTask
      # but uses stage_path as source directory.
      stage_files = spec.files.map do |gem_file|
        File.join(stage_path, gem_file)
      end
      file pkg.package_dir_path => stage_files do
        mkdir_p pkg.package_dir rescue nil
        spec.files.each do |ft|
          fn = File.join(stage_path, ft)
          f = File.join(pkg.package_dir_path, ft)
          fdir = File.dirname(f)
          mkdir_p(fdir) if !File.exist?(fdir)
          if File.directory?(fn)
            mkdir_p(f)
          else
            rm_f f
            safe_ln(fn, f)
          end
        end
      end
    end
  end
  # add binaries to the dependency chain
  task "native:#{@gem_spec.name}:#{platf}" => ["#{stage_path}/#{lib_dir}/#{binary(platf)}"]
  # ensure the extension get copied
  unless Rake::Task.task_defined?("#{lib_path}/#{binary(platf)}") then
    file "#{lib_path}/#{binary(platf)}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"]
  end
  file "#{stage_path}/#{lib_dir}/#{binary(platf)}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"]
  # Allow segmented packaging by platform (open door for 'cross compile')
  task "native:#{platf}" => ["native:#{@gem_spec.name}:#{platf}"]
  # Only add this extension to the compile chain if current
  # platform matches the indicated one.
  if platf == RUBY_PLATFORM then
    task "native:#{@gem_spec.name}" => ["native:#{@gem_spec.name}:#{platf}"]
    task "native" => ["native:#{platf}"]
  end
end