# -*- mode: ruby; coding: utf-8 -*-


require 'rbconfig'
require 'rake/loaders/makefile'


task :lib => 'lib:build'

%w[clean].each do |t|
  task t.intern => "lib:#{t}"
end


namespace :lib do


  rbconf = RbConfig::CONFIG

  mod      = MODULE
  name     = env :NAME,     MODULE.name.downcase
  incdir   = env :INCDIR,   'include'
  srcdir   = env :SRCDIR,   'src'
  libdir   = env :LIBDIR,   'lib'
  cxx      = env :CXX,      rbconf['CXX'] || 'g++'
  ar       = env :AR,       rbconf['AR']  || 'ar'
  defs     = env :DEFS,     []
  debug    = env :DEBUG,    false
  incdirs  = env :INCDIRS,  []
  cxxflags = env(:CXXFLAGS, rbconf['CXXFLAGS']).dup
  arflags  = env(:ARFLAGS,  'crs').dup

  outname = "lib#{name}.a"
  out     = File.join libdir, outname

  erbs    = glob *[incdir, srcdir].map {|s| "#{s}/**/*.erb"}
  erbs    = convertions erbs, {".erb" => ""}
  headers = glob("include/**/*.h") | erbs.values.grep(/\.h$/)
  srcs    = glob("src/**/*.cpp")   | erbs.values.grep(/\.cpp$/)
  srcs   += glob("src/**/*.mm") if cocoa?
  srcs    = srcs.reject {|s| s =~ %r(/win32/)} unless win32?
  srcs    = srcs.reject {|s| s =~ %r(/cocoa/)} unless cocoa?

  incroot = rbconf['rubyhdrdir']
  incdirs.concat Xot.include_dirs + [
    incroot,
    "#{incroot}/#{RUBY_PLATFORM}",
    '/opt/local/include',
    '/opt/include'
  ]
  incdirs.uniq!

  defs     << '_DEBUG' if debug
  defs     << 'NDEBUG' unless debug
  defs     << 'WIN32' if win32?
  defs     << 'COCOA' if cocoa?
  defs     << $~[0].upcase if RUBY_PLATFORM =~ /mswin|ming|cygwin|darwin/i
  cxxflags << ' ' << rbconf['debugflags'] if debug
  cxxflags.gsub! /-O\d?/, '' if debug
  cxxflags << ' --stdlib=libc++' if clang?
  cxxflags << defs.map{|s| " -D#{s}"}.join
  cxxflags << incdirs.map{|s| " -I#{s}"}.join

  depend = 'depend.mf'
  objs   = convertions srcs, {".cpp" => ".o", ".mm" => ".o"}
  tmps   = (objs.values | erbs.values) + [depend]


  task :build => out

  task :clean do
    sh %( rm -rf #{tmps.join " "} #{out} )
  end

  task :compile => objs.values

  task :erb => erbs.values

  file out => objs.values do
    sh %( #{ar} #{arflags} #{out} #{objs.values.join " "} )
  end

  file depend => erbs.values do
    sh %( #{cxx} -M #{cxxflags} #{srcs.join ' '} > #{depend} )
    input = open(depend) {|f| f.read}
    open(depend, 'w') do |output|
      output << input.gsub(/\w+\.o/, srcdir + '/\0')
    end
  end

  import depend if File.exist? depend

  objs.each do |(src, obj)|
    file obj => [depend, src] + erbs.values do
      sh %( #{cxx} -c #{cxxflags} -o #{obj} #{src} )
    end
  end

  erbs.each do |(erb, out)|
    file out => erb do
      print "#{erb}: compiling to #{out} ..."
      compile erb, out
      puts "ok"
    end
  end


end# :lib