#
# Author: Yasuhito Takamiya <yasuhito@gmail.com>
#
# Copyright (C) 2008-2012 NEC Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#


$LOAD_PATH.unshift File.expand_path( File.join File.dirname( __FILE__ ), "ruby" )
$LOAD_PATH.unshift File.expand_path( File.join File.dirname( __FILE__ ), "vendor", "ruby-ifconfig-1.2", "lib" )


require "trema/executables"
require "trema/path"
require "trema/dsl/parser"

import "c/dependencies"
import "directedrule"


################################################################################
# Main tasks
################################################################################

desc "Build trema."
task :default => [
  :libtrema,
  :rubylib,
  :switch_manager,
  :switch,
  :packetin_filter,
  :tremashark,
  :packet_capture,
  :syslog_relay,
  :stdin_relay,
  :vendor,
  :examples
]


task :examples => [
  "examples:cbench_switch",
  "examples:dumper",
  "examples:hello_trema",
  "examples:learning_switch",
  "examples:list_switches",
  "examples:multi_learning_switch",
  "examples:openflow_message",
  "examples:packet_in",
  "examples:repeater_hub",
  "examples:packetin_filter_config",
  "examples:switch_info",
  "examples:switch_monitor",
  "examples:traffic_monitor",
]


import "clean"

desc "Cleanup generated files."
gen Clean

var[ :clean ] << Trema.objects
var[ :clean ] << File.join( Trema.home, "objects/unittests" )
var[ :clean ] << File.join( Trema.home, "unittests/objects" )
var[ :clean ] << Trema::DSL::Context::PATH


desc "Cleanup everything."
task :distclean => :clean


desc "Generate build.rb."
task :buildrb do
  sys "rant-import --force --imports c/dependencies,directedrule,clean,sys/tgz build.rb"
  sys "chmod +x build.rb"
end


################################################################################
# Helpers
################################################################################

def objects path
  File.join Trema.objects, path
end


def dependency name
  file = ".#{ name }.dependency"
  var[ :clean ] << file
  ".#{ name }.dependency"
end


################################################################################
# !!!!!! DO NOT MODIFY !!!!!!
################################################################################

var :CFLAGS => "-g -std=gnu99 -D_GNU_SOURCE -fno-strict-aliasing -Werror -Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wfloat-equal -Wpointer-arith"


################################################################################
# Run cbench benchmarks.
################################################################################


def cbench_command
  File.join Trema.objects, "oflops/bin/cbench"
end


def cbench_latency_mode_options
  "--switches 1 --loops 10 --delay 1000"
end


def cbench_throughput_mode_options
  cbench_latency_mode_options + " --throughput"
end


def cbench controller, options
  begin
    sys "#{ controller }"
    sys "#{ cbench_command } #{ options }"
  ensure
    sys "./trema killall"
  end
end


def cbench_c_controller
  "./trema run ./objects/examples/cbench_switch/cbench_switch -d"
end


def cbench_ruby_controller
  "./trema run src/examples/cbench_switch/cbench-switch.rb -d"
end


def run_cbench controller
  cbench controller, cbench_latency_mode_options
  cbench controller, cbench_throughput_mode_options
end


var[ :clean ].include sys[ "callgrind.out.*" ]


def cbench_profile options
  valgrind = "valgrind --tool=callgrind --trace-children=yes"
  begin
    sys "#{ valgrind } #{ cbench_c_controller }"
    sys "#{ cbench_command } #{ options }"
  ensure
    sys "./trema killall"
  end
end


desc "Run the c cbench switch controller to benchmark"
task "cbench" => "cbench:c"


desc "Run the c cbench switch controller to benchmark"
task "cbench:c" => :default do | t |
  run_cbench cbench_c_controller
end


desc "Run the ruby cbench switch controller to benchmark"
task "cbench:ruby" => :default do | t |
  run_cbench cbench_ruby_controller
end


desc "Run cbench with profiling enabled."
task "cbench:profile" => :default do
  cbench_profile cbench_latency_mode_options
  cbench_profile cbench_throughput_mode_options
end


################################################################################
# Build vendor/*
################################################################################

import "sys/tgz"


task :vendor => [
  "vendor:oflops",
  "vendor:openflow",
  "vendor:openvswitch",
  "vendor:phost",
]

task :distclean => [
  "vendor:cmockery:distclean",
  "vendor:oflops:distclean",
  "vendor:openflow:distclean",
  "vendor:openvswitch:distclean",
  "vendor:phost:distclean",
]


#
# OpenFlow reference implementation
#

gen Directory, Trema.objects

task "vendor:openflow" => Trema.openflow_h
file Trema.openflow_h => Trema.objects do
  sys.unpack_tgz "#{ Trema.vendor_openflow }.tar.gz", :in => Trema.vendor
  sys.cp_r "#{ Trema.vendor_openflow }/include/openflow", Trema.objects
end

task "vendor:openflow:distclean" do
  sys.rm_rf Trema.vendor_openflow
end


#
# Use the Stanford openflow reference software to compile and copy the wireshark
# plugin to enable viewing of openflow messages.
# The plugin would be compiled and copied to your home directory
# (.wireshark/plugins) if it is found, otherwise it is left for you to copy
# from openflow.git/utilities/wireshark_dissectors/openflow directory
#
desc "Build openflow wireshark plugin"
task :openflow_wireshark_plugin => Trema.vendor_openflow_git
file Trema.vendor_openflow_git do | t |
  sys.unpack_tgz "#{ t.name }.tar.gz", :in => Trema.vendor
  subpath = "utilities/wireshark_dissectors/openflow"
  sys.cd "#{ Trema.vendor_openflow_git }/#{ subpath }" do
    sys "make"
    plugin_path = "#{ File.expand_path(" ~ ") }/.wireshark/plugins"
    sys.cp "packet-openflow.so", plugin_path if File.directory?( plugin_path )
  end
end


task "openflow_wireshark_plugin:clean" => "openflow_wireshark_plugin:distclean"
task "openflow_wireshark_plugin:distclean" do
  sys.rm_rf Trema.vendor_openflow_git
end


#
# Open vSwitch
#

task "vendor:openvswitch" => Trema::Executables.ovs_openflowd
file Trema::Executables.ovs_openflowd do
  sys.unpack_tgz "#{ Trema.vendor_openvswitch }.tar.gz", :in => Trema.vendor
  sys.cd Trema.vendor_openvswitch do
    sys "./configure --prefix=#{ Trema.openvswitch } --with-rundir=#{ Trema.sock }"
    sys "make install"
    sys "cp ./tests/test-openflowd #{ Trema::Executables.ovs_openflowd }"
  end
end

task "vendor:openvswitch:distclean" do
  sys.rm_rf Trema.vendor_openvswitch
end


#
# oflops
#

task "vendor:oflops" => cbench_command
file cbench_command => Trema.openflow_h do
  sys.unpack_tgz "#{ Trema.vendor_oflops }.tar.gz", :in => Trema.vendor
  sys.cd Trema.vendor_oflops do
    sys "./configure --prefix=#{ Trema.oflops } --with-openflow-src-dir=#{ Trema.vendor_openflow }"
    sys "make install"
  end
end

task "vendor:oflops:distclean" do
  sys.rm_rf Trema.vendor_oflops
end


#
# phost
#

def phost_src
  File.join Trema.vendor_phost, "src"
end


task "vendor:phost" => [ Trema::Executables.phost, Trema::Executables.cli ]

file Trema::Executables.phost do
  sys.cd phost_src do
    sys "make"
  end
  sys.mkdir_p File.dirname( Trema::Executables.phost )
  sys.install File.join( phost_src, "phost" ), Trema::Executables.phost, :mode => 0755
end

file Trema::Executables.cli do
  sys.cd phost_src do
    sys "make"
  end
  sys.mkdir_p File.dirname( Trema::Executables.cli )
  sys.install File.join( phost_src, "cli" ), Trema::Executables.cli, :mode => 0755
end

task "vendor:phost:distclean" do
  begin
    sys.cd phost_src do
      sys "make clean"
    end
  rescue
    # ignore.
  end
end


#
# cmockery
#

task "vendor:cmockery" => Trema.libcmockery_a
file Trema.libcmockery_a do
  sys.unpack_tgz "#{ Trema.vendor_cmockery }.tar.gz", :in => Trema.vendor
  sys.cd Trema::vendor_cmockery do
    sys "./configure --prefix=#{ Trema.cmockery }"
    sys "make install"
  end
end

task "vendor:cmockery:distclean" do
  sys.rm_rf Trema.vendor_cmockery
end


################################################################################
# Build libtrema.a
################################################################################

build_libtrema_a = Proc.new do | t |
  sys "rm -f #{ t.name }"
  sys "ar -cq #{ t.name } #{ sys.sp t.prerequisites }"
  sys "ranlib #{ t.name }"
end


task dependency( "libtrema" ) => "vendor:openflow"
gen C::Dependencies, dependency( "libtrema" ),
  :search => [ Trema.include, objects( "openflow" ) ],
  :sources => sys[ "#{ Trema.include }/*.c" ]

gen Action do
  source dependency( "libtrema" )
end


gen Directory, Trema.lib
gen Directory, "#{ Trema.home }/objects/unittests"

libtrema = File.join( Trema.lib, "libtrema.a" )
libtrema_gcov = File.join( "#{ Trema.home }/objects/unittests", "libtrema.a" )

libtrema_o = gen DirectedRule, Trema.lib => [ Trema.include ], :o => :c do | t |
  sys "gcc -I#{ objects "openflow" } #{ var :CFLAGS } -fPIC -c -o #{ t.name } #{ t.source }"
end
libtrema_gcov_o = gen DirectedRule, "#{ Trema.home }/objects/unittests" => [ Trema.include ], :o => :c do | t |
  sys "gcc --coverage -I#{ objects "openflow" } #{ var :CFLAGS } -fPIC -c -o #{ t.name } #{ t.source }"
end

desc "Build trema library."
task :libtrema => libtrema
file libtrema => libtrema_o.candidates do | t |
  build_libtrema_a.call t
end

desc "Build trema library (coverage)."
task "coverage:libtrema" => libtrema_gcov
file libtrema_gcov => libtrema_gcov_o.candidates do | t |
  build_libtrema_a.call t
end


################################################################################
# Build trema.so (ruby library)
################################################################################

task :clean => "rubylib:clean"
task :distclean => "rubylib:distclean"


desc "Build ruby library."
task :rubylib => "ruby/trema.so"
file "ruby/trema.so" => FileList[ "ruby/trema/*.c", "ruby/trema/*.h", libtrema ] do
  sys.cd "ruby" do
    sys "ruby extconf.rb --with-trema-include=#{ Trema.include } --with-trema-lib=#{ Trema.lib } --with-openflow-include=#{ Trema.openflow }"
    sys "make"
  end
end


task "rubylib:clean" do
  sys.cd "ruby" do
    sys "make clean" rescue nil
  end
end

task "rubylib:distclean" do
  sys.rm_f "ruby/Makefile"
end


################################################################################
# Build switch manager
################################################################################

switch_manager_objects_dir = objects( "switch_manager" )

gen C::Dependencies, dependency( "switch_manager" ),
  :search => [ "src/switch_manager", Trema.include ], :sources => sys[ "src/switch_manager/*.c" ]

gen Action do
  source dependency( "switch_manager" )
end


gen Directory, switch_manager_objects_dir

gen DirectedRule, switch_manager_objects_dir => [ "src/switch_manager" ], :o => :c do | t |
  sys "gcc -I#{ Trema.include } -I#{ Trema.openflow } #{ var :CFLAGS } -c -o #{ t.name } #{ t.source }"
end


switch_manager_objects = [
  "dpid_table.o",
  "switch_manager.o",
  "secure_channel_listener.o"
].collect do | each |
  File.join switch_manager_objects_dir, each
end

desc "Build switch manager."
task :switch_manager => Trema::Executables.switch_manager
file Trema::Executables.switch_manager => switch_manager_objects + [ libtrema ] do | t |
  sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt"
end


switch_objects = [
  "cookie_table.o",
  "ofpmsg_recv.o",
  "ofpmsg_send.o",
  "secure_channel_receiver.o",
  "secure_channel_sender.o",
  "service_interface.o",
  "switch.o",
  "xid_table.o",
].collect do | each |
  File.join switch_manager_objects_dir, each
end

desc "Build switch."
task :switch => Trema::Executables.switch
file Trema::Executables.switch => switch_objects + [ libtrema ] do | t |
  sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt"
end


################################################################################
# Build packetin filter
################################################################################

gen C::Dependencies, dependency( "packetin_filter" ),
  :search => [ "src/packetin_filter", Trema.include ], :sources => sys[ "src/packetin_filter/*.c" ]

gen Action do
  source dependency( "packetin_filter" )
end


gen Directory, objects( "packetin_filter" )

packetin_filter_objects = gen DirectedRule, objects( "packetin_filter" ) => [ "src/packetin_filter" ], :o => :c do | t |
  sys "gcc -I#{ Trema.include } -I#{ Trema.openflow } #{ var :CFLAGS } -c -o #{ t.name } #{ t.source }"
end

desc "Build packetin filter."
task :packetin_filter => Trema::Executables.packetin_filter
file Trema::Executables.packetin_filter => packetin_filter_objects.candidates + [ libtrema ] do | t |
  sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt"
end


################################################################################
# tremashark
################################################################################

tremashark_objects_dir = objects( "tremashark" )

gen C::Dependencies, dependency( "tremashark" ),
  :search => [ "src/tremashark", Trema.include ], :sources => sys[ "src/tremashark/*.c" ]

gen Action do
  source dependency( "tremashark" )
end


gen Directory, tremashark_objects_dir

gen DirectedRule, tremashark_objects_dir => [ "src/tremashark" ], :o => :c do | t |
  sys "gcc -I#{ Trema.include } -I#{ Trema.openflow } #{ var :CFLAGS } -c -o #{ t.name } #{ t.source }"
end


tremashark_objects = [
  "pcap_queue.o",
  "queue.o",
  "tremashark.o",
].collect do | each |
  File.join tremashark_objects_dir, each
end

desc "Build tremashark."
task :tremashark => Trema::Executables.tremashark
file Trema::Executables.tremashark => tremashark_objects + [ libtrema ] do | t |
  sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt -lpcap"
end


packet_capture_objects = [
  "packet_capture.o",
  "queue.o",
].collect do | each |
  File.join tremashark_objects_dir, each
end

desc "Build packet_capture."
task :packet_capture => Trema::Executables.packet_capture
file Trema::Executables.packet_capture => packet_capture_objects + [ libtrema ] do | t |
  sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt -lpcap"
end


syslog_relay_objects = [
  "syslog_relay.o",
].collect do | each |
  File.join tremashark_objects_dir, each
end

desc "Build syslog_relay."
task :syslog_relay => Trema::Executables.syslog_relay
file Trema::Executables.syslog_relay => syslog_relay_objects + [ libtrema ] do | t |
  sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt -lpcap"
end


stdin_relay_objects = [
  "stdin_relay.o",
].collect do | each |
  File.join tremashark_objects_dir, each
end

desc "Build stdin_relay."
task :stdin_relay => Trema::Executables.stdin_relay
file Trema::Executables.stdin_relay => stdin_relay_objects + [ libtrema ] do | t |
  sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt -lpcap"
end


################################################################################
# Build standalone examples
################################################################################

standalone_examples = [
  "cbench_switch",
  "dumper",
  "hello_trema",
  "learning_switch",
  "list_switches",
  "multi_learning_switch",
  "packet_in",
  "repeater_hub",
  "switch_info",
  "switch_monitor",
  "traffic_monitor",
]

standalone_examples.each do | each |
  objects_dir = objects( "examples/#{ each }" )
  target = objects( "examples/#{ each }/#{ each }" )

  gen C::Dependencies, dependency( each ),
    :search => [ "src/examples/#{ each }", Trema.include ], :sources => sys[ "src/examples/#{ each }/*.c" ]

  gen Action do
    source dependency( each )
  end


  gen Directory, objects_dir

  objects = gen DirectedRule, objects_dir => [ "src/examples/#{ each }" ], :o => :c do | t |
    sys "gcc -I#{ Trema.include } -I#{ Trema.openflow } #{ var :CFLAGS } -c -o #{ t.name } #{ t.source }"
  end


  desc "Build #{ each } example."
  task "examples:#{ each }" => target
  file target => objects.candidates + [ libtrema ] do | t |
    sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ sys.sp t.prerequisites } -ltrema -lsqlite3 -ldl -lrt"
  end
end


################################################################################
# Build openflow messages
################################################################################

openflow_messages = [
  "echo_reply",
  "echo_request",
  "features_request",
  "hello",
  "set_config",
]

openflow_message_source_dir = "src/examples/openflow_message"
openflow_message_objects_dir = objects( "examples/openflow_message" )

gen C::Dependencies, dependency( "openflow_message" ),
  :search => [ Trema.include ], :sources => sys[ "#{ openflow_message_source_dir }/*.c" ]

gen Action do
  source dependency( "openflow_message" )
end

gen Directory, openflow_message_objects_dir


gen DirectedRule, openflow_message_objects_dir => [ openflow_message_source_dir ], :o => :c do | t |
  sys "gcc -I#{ Trema.include } -I#{ Trema.openflow } #{ var :CFLAGS } -c -o #{ t.name } #{ t.source }"
end


openflow_messages.each do | each |
  target = File.join( openflow_message_objects_dir, each )
  task "examples:openflow_message" => target
  file target => [ File.join( openflow_message_objects_dir, "#{ each }.o" ), libtrema ] do | t |
    sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ t.source } -ltrema -lsqlite3 -ldl -lrt"
  end
end


################################################################################
# Build packetin_filter_config
################################################################################

packetin_filter_config = [
  "add_filter",
  "delete_filter",
  "delete_filter_strict",
  "dump_filter",
  "dump_filter_strict",
]

packetin_filter_config_source_dir = "src/examples/packetin_filter_config"
packetin_filter_config_objects_dir = objects( "examples/packetin_filter_config" )

gen C::Dependencies, dependency( "packetin_filter_config" ),
  :search => [ Trema.include ], :sources => sys[ "#{ packetin_filter_config_source_dir }/*.c" ]

gen Action do
  source dependency( "packetin_filter_config" )
end

gen Directory, packetin_filter_config_objects_dir


gen DirectedRule, packetin_filter_config_objects_dir => [ packetin_filter_config_source_dir ], :o => :c do | t |
  sys "gcc -I#{ Trema.include } -I#{ Trema.openflow } #{ var :CFLAGS } -c -o #{ t.name } #{ t.source }"
end


packetin_filter_config.each do | each |
  packetin_filter_config_utils_o = File.join( packetin_filter_config_objects_dir, "utils.o" )
  target = File.join( packetin_filter_config_objects_dir, each )
  task "examples:packetin_filter_config" => target
  file target => [
    File.join( packetin_filter_config_objects_dir, "#{ each }.o" ),
    packetin_filter_config_utils_o,
    libtrema
  ] do | t |
    sys "gcc -L#{ Trema.lib } -o #{ t.name } #{ t.source } #{ packetin_filter_config_utils_o } -ltrema -lsqlite3 -ldl -lrt"
  end
end


################################################################################
# Unit tests.
################################################################################

def libtrema_unit_tests
  {
    :byteorder_test => [ :log, :utility, :wrapper, :trema_wrapper ],
    :daemon_test => [],
    :ether_test => [ :buffer, :log, :utility, :wrapper, :trema_wrapper ],
    :messenger_test => [ :doubly_linked_list, :hash_table, :event_handler, :linked_list, :utility, :wrapper, :timer, :log, :trema_wrapper ],
    :openflow_application_interface_test => [ :buffer, :byteorder, :hash_table, :doubly_linked_list, :linked_list, :log, :openflow_message, :packet_info, :stat, :trema_wrapper, :utility, :wrapper ],
    :openflow_message_test => [ :buffer, :byteorder, :linked_list, :log, :packet_info, :utility, :wrapper, :trema_wrapper ],
    :packet_info_test => [ :buffer, :log, :utility, :wrapper, :trema_wrapper ],
    :stat_test => [ :hash_table, :doubly_linked_list, :log, :utility, :wrapper, :trema_wrapper ],
    :timer_test => [ :log, :utility, :wrapper, :doubly_linked_list, :trema_wrapper ],
    :trema_test => [ :utility, :log, :wrapper, :doubly_linked_list, :trema_private, :trema_wrapper ],
  }
end


def test_object_files test
  names = [ test.to_s.gsub( /_test$/, "" ) ] + libtrema_unit_tests[ test ]
  names.collect do | each |
    if each == :buffer
      [ "unittests/objects/buffer.o", "unittests/objects/buffer_stubs.o" ]
    elsif each == :wrapper
      [ "unittests/objects/wrapper.o", "unittests/objects/wrapper_stubs.o" ]
    else
      "unittests/objects/#{ each }.o"
    end
  end.flatten
end


gen C::Dependencies, dependency( "unittests" ),
  :search => [ Trema.include, "unittests" ], :sources => sys[ "unittests/lib/*.c", "src/lib/*.c" ]

gen Action do
  source dependency( "unittests" )
end


gen Directory, "unittests/objects"
gen Directory, "objects/unittests"

gen DirectedRule, "unittests/objects" => [ "unittests", "unittests/lib", "src/lib" ], :o => :c do | t |
  sys "gcc -I#{ Trema.include } -I#{ Trema.openflow } -I#{ File.dirname Trema.cmockery_h } -Iunittests -DUNIT_TESTING --coverage #{ var :CFLAGS } -c -o #{ t.name } #{ t.source }"
end


libtrema_unit_tests.keys.each do | each |
  target = "unittests/objects/#{ each }"

  task :build_old_unittests => target
  task target => "vendor:cmockery"
  file target => test_object_files( each ) + [ "#{ target }.o" ] do | t |
    sys "gcc -L#{ File.dirname Trema.libcmockery_a } -o #{ t.name } #{ sys.sp t.prerequisites } -DUNIT_TESTING -lrt -lcmockery -lsqlite3 -ldl -lpthread --coverage --static"
  end
end


# new unittest
tests = [
  "objects/unittests/buffer_test",
  "objects/unittests/doubly_linked_list_test",
  "objects/unittests/ether_test",
  "objects/unittests/hash_table_test",
  "objects/unittests/linked_list_test",
  "objects/unittests/log_test",
  "objects/unittests/packetin_filter_interface_test",
  "objects/unittests/packet_info_test",
  "objects/unittests/packet_parser_test",
  "objects/unittests/persistent_storage_test",
  "objects/unittests/trema_private_test",
  "objects/unittests/utility_test",
  "objects/unittests/wrapper_test",
  "objects/unittests/match_table_test",
  "objects/unittests/message_queue_test",
]


file "objects/unittests/cmockery_trema.o" do | t |
  sys "gcc --coverage -c unittests/#{ File.basename t.name, ".o" }.c -o #{ t.name } #{ var :CFLAGS } -I#{ Trema.include } -I#{ File.dirname Trema.cmockery_h } -Iunittests"
end


tests.each do | each |
  task :build_unittests => [ "coverage:libtrema", each ]
  task each => [ "coverage:libtrema", "vendor:cmockery", "objects/unittests/cmockery_trema.o", "#{ Trema.home }/objects/unittests" ]
  file each => "unittests/lib/#{ File.basename each }.c" do | t |
    sys "gcc --coverage -c unittests/lib/#{ File.basename t.name }.c -o #{ each }.o #{ var :CFLAGS } -I#{ Trema.include } -I#{ Trema.openflow } -I#{ File.dirname Trema.cmockery_h } -Iunittests"
    sys "gcc --coverage -o #{ t.name } #{ each }.o objects/unittests/cmockery_trema.o -Lobjects/unittests -L#{ File.dirname Trema.libcmockery_a } -ltrema -lrt -lcmockery -lsqlite3 -ldl -lpthread --static"
  end
end


desc "Run unittests"
task :unittests => [ :build_old_unittests, :build_unittests ] do
  ( sys[ "unittests/objects/*_test" ] + tests ).each do | each |
    puts "Running #{ each }..."
    sys each
  end
end


################################################################################
# TODO, FIXME etc.
################################################################################

desc "Print list of notes."
task :notes do
  keywords = [ "TODO", "FIXME", "XXX" ]
  keywords.each do | key |
    system "find src unittests -name '*.c' | xargs grep -n #{ key }"
    system "find ruby spec features -name '*.rb' | xargs grep -n #{ key }"
  end
end


### Local variables:
### mode: Ruby
### coding: utf-8-unix
### indent-tabs-mode: nil
### End: