[Rake-devel] Rake Configuretask
Tilman Sauerbeck
tilman at code-monkey.de
Mon May 23 14:16:19 EDT 2005
Hi guys,
I started work on a configuretask recently, which is to provide the
functionality of autoconf/mkmf, somewhat.
So far there is very little functionality, but before implementing more
tests etc I'd like to get some input from other Rake users.
What do you think about the API in general, any other ideas on the
design? :)
Regards,
Tilman
--
learn to quote: http://www.netmeister.org/news/learn2quote.html
-------------- next part --------------
require "rake/tasklib"
require "rake/clean"
require "yaml"
require "tempfile"
module Rake
class ConfigureTask < TaskLib
CACHE_FILE = ".configure_state.yaml"
attr_reader :tests
def initialize # :yield: self
@tests = TestList.new(load_tests || [])
yield self if block_given?
define
end
# returns the test with the specified name
def [](name)
@tests.find { |t| t.name == name }
end
def method_missing(m)
self[m.to_s]
end
private
def load_tests
r = nil
if File.exist?(CACHE_FILE)
File.open(CACHE_FILE, "r") { |f| r = YAML.load(f) }
end
r.is_a?(TestList) ? r : nil
end
def define
desc "Remove configure results"
task :clobber_configure do
FileUtils::Verbose.rm_f(CACHE_FILE)
end
task :clobber => :clobber_configure
desc "Configure this package"
task :configure => [CACHE_FILE]
file CACHE_FILE do
@tests.each do |t|
t.on_checking.reverse.each { |b| b.call }
if t.invoke
t.on_success.reverse.each { |b| b.call }
else
t.on_failure.reverse.each { |b| b.call }
end
end
# store the test results in CACHE_FILE
File.open(CACHE_FILE, "w") { |f| YAML.dump(@tests, f) }
end
end
class TestList < Array
# stored_tests needs to be optional because of a bug in
# Ruby 1.8's YAML implementation.
def initialize(stored_tests = [])
@stored_tests = stored_tests
end
def <<(arg)
assign_result(arg)
super
end
def push(*args)
args.each { |a| assign_result(a) }
super
end
def unshift(arg)
assign_result(arg)
super
end
private
def assign_result(test)
st = @stored_tests.find { |st| st.name == test.name }
test.result = st.result unless st.nil?
end
end
class Test
attr_reader :name, :on_checking, :on_success, :on_failure
attr_accessor :result
def initialize(name, opts = {}) # :yield: self
@name = name.to_str.strip.dup
@result = nil
@on_checking = []
@on_success = []
@on_failure = []
if opts[:is_critical]
@on_failure << lambda { raise }
end
yield self if block_given?
end
def to_yaml_properties
["@name", "@result"]
end
def invoke
end
protected
def can_exec_binary?(bin)
fork do
tf = Tempfile.open("configuretask")
STDOUT.reopen(tf)
STDERR.reopen(tf)
begin
exec(bin)
rescue SystemCallError
exit 0xb00bface
end
end
Process.wait
$?.exitstatus != 0xb00bface
end
end
class FooConfigTest < Test
def initialize(name, opts = {})
super
@result = {}
@command = "#{name}-config"
@on_checking << lambda { print "Checking for #{name}... " }
@on_success << lambda { puts "yes (#{version})" }
@on_failure << lambda { puts "no" }
end
def method_missing(m)
@result[m]
end
def invoke
return false unless can_exec_command?
[:version, :cflags, :libs].each do |f|
@result[f] = lookup_flags(f)
end
true
end
protected
def lookup_flags(f)
tmp = `#{@command} --#{f}`.strip
$?.exitstatus.zero? ? tmp : nil
end
private
def can_exec_command?
can_exec_binary?(@command)
end
end
class PkgConfigTest < FooConfigTest
def initialize(name, opts = {})
super
@command = "pkg-config --silence-errors"
end
protected
def lookup_flags(f)
f = :modversion if f == :version
tmp = `#{@command} --#{f} #{@name}`.strip
$?.exitstatus.zero? ? tmp : nil
end
end
end
end
More information about the Rake-devel
mailing list