The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'rbconfig'
require 'rake/clean' 

CLOWNFISH_RUBY_DIR      = File.absolute_path('.')
CLOWNFISH_INCLUDE_DIR   = File.join('..','include')
CLOWNFISH_SRC_DIR       = File.join('..','src')
LEMON_SRC_DIR           = File.join('..','..','lemon')

desc "Build lemon"
task :build_lemon do
  puts "Building lemon"
  run_make(LEMON_SRC_DIR,[])
end

desc "Build Clownfish"
task :clownfish => [:parse_y_files] do
  Dir.glob("../src/*.c").each do|c_file|
    obj_file = c_file.gsub(/\.c$/,'.o')
    command = "#{cc_command} #{includes} #{extra_ccflags} -o #{obj_file} -c #{c_file}"
    puts command
    if system(command).nil?
      abort "Failed cc compile"
    end
  end
end

desc "Lemonize the y file"
task :parse_y_files => [:build_lemon] do
  puts "Parsing y files"
  Dir.glob("#{CLOWNFISH_SRC_DIR}/*.y").each do |y_file|
    c_file = y_file.gsub(/\.y$/,'.c')
    h_file = y_file.gsub(/\.y$/,'.h')
    report_file = y_file.gsub(/\.y$/,'.out')
    command = File.join(LEMON_SRC_DIR,'lemon') + ' -c ' + File.join(y_file)    
    puts command
    if system(command).nil?
      abort "Problem parsing y file with lemon"
    end
  end
end

task :default => [:clownfish]

def cc_command
  RbConfig::CONFIG["CC"]
end

def extra_ccflags 
  ccflags  = '-std=gnu99 -fno-common -fno-strict-aliasing -pipe -fstack-protector -O3 '
  ccflags += ENV['CFLAGS'] if ENV['CFLAGS']
  
  if !defined?(cc_command)
    abort "Invalid GCC version: gcc_version"
  end
  
  if ENV.has_key?('LUCY_VALGRIND')
    ccflags += "-fno-inline-functions "
  end
  
  if cc_command =~ /^cl\b/ 
    ccflags += '/TP -D_CRT_SECURE_NO_WARNINGS '
  end
  
  if ccflags !~ /-std=/
    ccflags += "-std=gnu99 "
  end
  
  if ccflags !~ /-D_GNU_SOURCE/ 
    ccflags += "-D_GNU_SOURCE "
  end
  
  return ccflags
end

def includes
  return "-I#{CLOWNFISH_INCLUDE_DIR} -I#{CLOWNFISH_SRC_DIR}"
end

def make_command
  command = RbConfig::CONFIG["make-prog"]
  if !command
    if RUBY_PLATFORM =~ /mswin/i
      cc = cc_command
      if cc =~ /^cl\b/
        command = "nmake"
      else
        command = "dmake"
      end
    else
      command = "make"
    end
  end
  return command
end

def run_make(dir, params)
  current_dir = Dir.pwd
  chdir(dir) if dir
  command = params.clone
  command.unshift("CC=#{cc_command}")
  if RUBY_PLATFORM =~ /mswin/i
    if cc_command =~ /^cl\b/ 
      command.unshift("-f", "Makefile.MSVC")
    else
      command.unshift("-f", "Makefile.MinGW")
    end
  end
  command.unshift(make_command)
  success = system(*command)
  if !success
    raise "Make failed"
  end
  chdir(current_dir) if dir
end

CLEAN.include(CLOWNFISH_SRC_DIR + '/CFCParseHeader.out')
CLEAN.include(CLOWNFISH_SRC_DIR + '/CFCParseHeader.c')
CLEAN.include(CLOWNFISH_SRC_DIR + '/CFCParseHeader.h')