class Buildr::CCTask

Attributes

delay[RW]
project[R]

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/buildr/core/cc.rb, line 21
def initialize(*args)
  super
  @delay = 0.2
  enhance do
    monitor_and_compile
  end
end

Private Instance Methods

associate_with(project) click to toggle source
# File lib/buildr/core/cc.rb, line 40
def associate_with(project)
  @project = project
end
build_completed(project) click to toggle source
# File lib/buildr/core/cc.rb, line 121
def build_completed(project)
  Buildr.application.build_completed('Compilation successful', project.path_to)
end
build_failed(project, ex = nil) click to toggle source
# File lib/buildr/core/cc.rb, line 125
def build_failed(project, ex = nil)
  Buildr.application.build_failed('Compilation failed', project.path_to, ex)
end
changed(new_times, old_times) click to toggle source
# File lib/buildr/core/cc.rb, line 129
def changed(new_times, old_times)
  changed = []
  new_times.each do |(fname,newtime)|
    if old_times[fname].nil? || old_times[fname] < newtime
      changed << fname
    end
  end

  # detect deletion (slower than it could be)
  old_times.each_key do |fname|
    changed << fname unless new_times.has_key? fname
  end

  changed
end
each_project(&block) click to toggle source

run block on sub-projects depth-first, then on this project

# File lib/buildr/core/cc.rb, line 32
def each_project(&block)
  depth_first = lambda do |p|
    p.projects.each { |c| depth_first.call(c, &block) }
    block.call(p)
  end
  depth_first.call(@project)
end
monitor_and_compile() click to toggle source
# File lib/buildr/core/cc.rb, line 44
def monitor_and_compile
  # we don't want to actually fail if our dependencies don't succeed
  begin
    each_project { |p| p.test.compile.invoke }
    build_completed(project)
  rescue Exception => ex
    $stderr.puts Buildr::Console.color(ex.message, :red)
    $stderr.puts

    build_failed(project, ex)
  end

  srcs = []
  each_project do |p|
    srcs += p.compile.sources.map(&:to_s)
    srcs += p.test.compile.sources.map(&:to_s)
    srcs += p.resources.sources.map(&:to_s)
  end
  if srcs.length == 1
    info "Monitoring directory: #{srcs.first}"
  else
    info "Monitoring directories: [#{srcs.join ', '}]"
  end

  timestamps = lambda do
    times = {}
    srcs.each do |a|
      if File.directory? a
        Dir.glob("#{a}/**/*").map { |f| times[f] = File.mtime f }
      elsif File.exist? a
        times[a] = File.mtime a
      end
    end
    times
  end

  old_times = timestamps.call()

  while true
    sleep delay

    new_times = timestamps.call()
    changed = changed(new_times, old_times)
    old_times = new_times

    unless changed.empty?
      info ''    # better spacing

      changed.each do |file|
        info "Detected changes in #{file}"
      end

      each_project do |p|
        # transitively reenable prerequisites
        reenable = lambda do |t|
          t = task(t)
          t.reenable
          t.prerequisites.each { |c| reenable.call(c) }
        end
        reenable.call(p.test.compile)
      end

      successful = true
      begin
        each_project { |p| p.test.compile.invoke }
        build_completed(project)
      rescue Exception => ex
        $stderr.puts Buildr::Console.color(ex.message, :red)
        build_failed(project, ex)
        successful = false
      end

      puts Buildr::Console.color("Build complete", :green) if successful
    end
  end
end