class FFI::Compiler::CompileTask

def define_task!

def define_task!
  pic_flags = %w(-fPIC)
  so_flags = []
  if @platform.mac?
    pic_flags = []
    so_flags << '-bundle'
  elsif @platform.name =~ /linux/
    so_flags << "-shared -Wl,-soname,#{lib_name}"
  else
    so_flags << '-shared'
  end
  so_flags = shelljoin(so_flags)
  out_dir = "#{@platform.arch}-#{@platform.os}"
  if @ext_dir != '.'
    out_dir = File.join(@ext_dir, out_dir)
  end
  directory(out_dir)
  CLOBBER.include(out_dir)
  lib_name = File.join(out_dir, Platform.system.map_library_name(@name))
  iflags = @include_paths.uniq.map { |p| "-I#{p}" }
  @defines += @functions.uniq.map { |f| "-DHAVE_#{f.upcase}=1" }
  @defines += @headers.uniq.map { |h| "-DHAVE_#{h.upcase.sub(/\./, '_')}=1" }
  cflags = shelljoin(@cflags.to_a + pic_flags + iflags + @defines)
  cxxflags = shelljoin(@cxxflags.to_a + @cflags.to_a + pic_flags + iflags + @defines)
  ld_flags = shelljoin(@library_paths.map { |path| "-L#{path}" } + @ldflags.to_a)
  libs = shelljoin(@libraries.map { |l| "-l#{l}" } + @libs)
  src_files = []
  obj_files = []
  @source_dirs.each do |dir|
    files = FileList["#{dir}/**/*.{c,cpp}"]
    unless @exclude.empty?
      files.delete_if { |f| f =~ Regexp.union(*@exclude) }
    end
    src_files += files
    obj_files += files.ext('.o').map { |f| File.join(out_dir, f.sub(/^#{dir}\//, '')) }
  end
  index = 0
  src_files.each do |src|
    obj_file = obj_files[index]
    if src =~ /\.c$/
      file obj_file => [ src, File.dirname(obj_file) ] do |t|
        sh "#{cc} #{cflags} -o #{shellescape(t.name)} -c #{shellescape(t.prerequisites[0])}"
      end
    else
      file obj_file => [ src, File.dirname(obj_file) ] do |t|
        sh "#{cxx} #{cxxflags} -o #{shellescape(t.name)} -c #{shellescape(t.prerequisites[0])}"
      end
    end
    CLEAN.include(obj_file)
    index += 1
  end
  ld = src_files.detect { |f| f =~ /\.cpp$/ } ? cxx : cc
  # create all the directories for the output files
  obj_files.map { |f| File.dirname(f) }.sort.uniq.map { |d| directory d }
  desc "Build dynamic library"
  MultiFileTask.define_task(lib_name => src_files + obj_files) do |t|
    objs = t.prerequisites.select { |file| file.end_with?('.o') }
    sh "#{ld} #{so_flags} -o #{shellescape(t.name)} #{shelljoin(objs)} #{ld_flags} #{libs}"
  end
  CLEAN.include(lib_name)
  @exports.each do |e|
    desc "Export #{e[:rb_file]}"
    file e[:header] => [ e[:rb_file] ] do |t|
      ruby "-I#{File.join(File.dirname(__FILE__), 'fake_ffi')} -I#{File.dirname(t.prerequisites[0])} #{File.join(File.dirname(__FILE__), 'exporter.rb')} #{shellescape(t.prerequisites[0])} #{shellescape(t.name)}"
    end
    obj_files.each { |o| file o  => [ e[:header] ] }
    CLEAN.include(e[:header])
    desc "Export API headers"
    task :api_headers => [ e[:header] ]
  end
  task :default => [ lib_name ]
  task :package => [ :api_headers ]
end