--- /dev/null
+ChangeLog
+doc
+pkg
+*.so
+*.eet
+.configure_state.yaml
--- /dev/null
+Tilman Sauerbeck (tilman at code-monkey de)
--- /dev/null
+Copyright (c) 2007 Tilman Sauerbeck (tilman at code-monkey de)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+= ruby-discid
+
+ruby-discid is a set of Ruby bindings to MusicBrainz' libdiscid.
+
+ruby-discid is maintained by:
+
+:include: AUTHORS
+
+== License
+
+ruby-discid is available under an MIT-style license.
+
+:include: COPYING
+
+== Download
+
+The latest version of ruby-discid can be found at
+http://code-monkey.de/pages/ruby-discid
+
+Online documentation is available at
+http://docs.code-monkey.de/ruby-discid
+
+== Dependencies
+
+ruby-discid depends on Rake[http://rake.rubyforge.org] 0.5.0
+or greater and libdiscid[http://musicbrainz.org/doc/libdiscid].
+
+== Installation
+
+Run "rake install" to install ruby-discid.
+
+== Usage
+
+Have a look at this example:
+
+ require "discid"
+
+ discid = DiscID::DiscID.read("/dev/hdc")
+
+ puts discid.id
+ puts discid.submission_url
+
+That's basically all you need.
--- /dev/null
+require "rake/clean"
+require "rake/testtask"
+require "spec/rake/spectask"
+require "rake/rdoctask"
+require "rake/packagetask"
+require "rake/contrib/compositepublisher"
+require "rake/contrib/sshpublisher"
+
+require "rake/configuretask"
+require "rake/extensiontask"
+
+PKG_NAME = "ruby-discid"
+PKG_VERSION = File.read("lib/discid.rb").
+ match(/^\s*VERSION = \"(.*)\"$/).captures.first
+PKG_FILES = FileList[
+ "AUTHORS", "COPYING", "README", "Rakefile",
+ "rake/configuretask.rb", "rake/extensiontask.rb",
+ "ext/ext.c", "lib/discid.rb"
+]
+
+ext_objs = [:ext]
+
+task :default => [:ext]
+task :extension => [:install, :clobber]
+
+config = Rake::ConfigureTask.new do |t|
+ t.tests << Rake::ConfigureTask::
+ PkgConfigTest.new("libdiscid", :is_critical => true)
+end
+
+task :ext => [:pre_ext]
+
+ext = Rake::ExtensionTask.new :ext => ext_objs do |t|
+ t.dir = "ext"
+ t.lib_name = "#{t.dir}/discid_ext.so"
+end
+
+task :pre_ext => [:configure] do
+ ext.link_libs << config.libdiscid.libs
+
+ cflags = [
+ ext.env[:cflags],
+ config.libdiscid.cflags
+ ]
+
+ ext.env.update(:cflags => cflags)
+end
+
+task :install => [:ext] do |t|
+ destdir = ENV["DESTDIR"] || ""
+
+ tmp = ENV["RUBYARCHDIR"] || Config::CONFIG["sitearchdir"]
+ ddir = File.join(destdir, tmp)
+
+ unless File.expand_path(ext.lib_name) ==
+ File.join(ddir, File.basename(ext.lib_name))
+ FileUtils::Verbose.mkdir_p(ddir) unless File.directory?(ddir)
+ FileUtils::Verbose.install(ext.lib_name, ddir, :mode => 0755)
+ end
+
+ tmp = ENV["RUBYLIBDIR"] || Config::CONFIG["sitelibdir"]
+ ddir = File.join(destdir, tmp)
+
+ PKG_FILES.each do |file|
+ next unless file.pathmap("%1d") == "lib"
+
+ dest_file = file.pathmap("%{^lib,#{ddir}}p")
+
+ next if File.expand_path(file) == dest_file
+
+ FileUtils::Verbose.mkdir_p(File.dirname(dest_file))
+ FileUtils::Verbose.install(file, dest_file, :mode => 0644)
+ end
+end
+
+task :test => [:ext]
+
+test = Rake::TestTask.new do |t|
+ t.libs = ["lib", "ext"]
+ t.warning = true
+end
+
+rdoc = Rake::RDocTask.new do |t|
+ t.rdoc_dir = "doc"
+ t.title = PKG_NAME
+ t.options = ["--line-numbers", "--inline-source", "--main", "README"]
+ t.rdoc_files = FileList[
+ "README", "COPYING", "AUTHORS",
+ "ext/ext.c", "lib/discid.rb"
+ ]
+end
+
+Rake::PackageTask.new(PKG_NAME, PKG_VERSION) do |t|
+ t.need_tar_gz = true
+ t.package_files = PKG_FILES
+end
+
+task :publish => [:rdoc, :package] do
+ p = Rake::CompositePublisher.new
+ p.add(Rake::SshFreshDirPublisher.new("code-monkey.de",
+ "public_docs/" +
+ PKG_NAME, "doc"))
+
+ p.add(Rake::SshFilePublisher.new("code-monkey.de",
+ ".", "pkg",
+ "#{PKG_NAME}-#{PKG_VERSION}.tar.gz"))
+ p.upload
+end
+
--- /dev/null
+/*
+ * Copyright (c) 2007 Tilman Sauerbeck (tilman at code-monkey de)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <ruby.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <discid/discid.h>
+
+static VALUE eReadError;
+
+typedef struct {
+ DiscId *real;
+} RbDiscID;
+
+static void
+c_free (RbDiscID *o)
+{
+ discid_free (o->real);
+
+ ruby_xfree (o);
+}
+
+static VALUE
+c_alloc (VALUE klass)
+{
+ RbDiscID *o;
+
+ return Data_Make_Struct (klass, RbDiscID, NULL, c_free, o);
+}
+
+/*
+ * call-seq:
+ * DiscID.default_device -> string
+ *
+ * Returns the default device that's used in DiscID::DiscID.read if
+ * the device isn't specified explicitly.
+ */
+static VALUE
+m_default_device (VALUE self)
+{
+ return rb_str_new2 (discid_get_default_device ());
+}
+
+/*
+ * call-seq:
+ * DiscID::DiscID.read([device]) -> object
+ *
+ * Read the disc id from the medium in the given device.
+ * If the argument is ommitted, DiscID.default_device is used instead.
+ */
+static VALUE
+c_read (int argc, VALUE *argv, VALUE klass)
+{
+ VALUE self, device;
+ RbDiscID *o;
+ char *cdev = NULL;
+ int s;
+
+ rb_scan_args (argc, argv, "01", &device);
+
+ if (!NIL_P (device))
+ cdev = StringValuePtr (device);
+
+ self = rb_class_new_instance (0, NULL, klass);
+
+ Data_Get_Struct (self, RbDiscID, o);
+
+ s = discid_read (o->real, cdev);
+ if (!s)
+ rb_raise (eReadError, discid_get_error_msg (o->real));
+
+ return self;
+}
+
+static VALUE
+c_init (VALUE self)
+{
+ RbDiscID *o;
+
+ Data_Get_Struct (self, RbDiscID, o);
+
+ o->real = discid_new ();
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * discid.id -> string
+ *
+ * Returns the MusicBrainz disc id.
+ */
+static VALUE
+c_id (VALUE self)
+{
+ RbDiscID *o;
+ char *s;
+
+ Data_Get_Struct (self, RbDiscID, o);
+
+ s = discid_get_id (o->real);
+
+ return rb_str_new2 (s);
+}
+
+/*
+ * call-seq:
+ * discid.submission_url -> string
+ *
+ * Returns the submission url for the disc id.
+ */
+static VALUE
+c_submission_url (VALUE self)
+{
+ RbDiscID *o;
+ char *s;
+
+ Data_Get_Struct (self, RbDiscID, o);
+
+ s = discid_get_submission_url (o->real);
+
+ return rb_str_new2 (s);
+}
+
+/*
+ * call-seq:
+ * discid.freedb_id -> string
+ *
+ * Returns the FreeDB disc id.
+ */
+static VALUE
+c_freedb_id (VALUE self)
+{
+ RbDiscID *o;
+ char *s;
+
+ Data_Get_Struct (self, RbDiscID, o);
+
+ s = discid_get_freedb_id (o->real);
+
+ return rb_str_new2 (s);
+}
+
+void
+Init_discid_ext (void)
+{
+ VALUE m, c;
+ VALUE eDiscIDError;
+
+ m = rb_define_module ("DiscID");
+ c = rb_define_class_under (m, "DiscID", rb_cObject);
+
+ rb_define_alloc_func (c, c_alloc);
+
+ rb_define_module_function (m, "default_device", m_default_device, 0);
+ rb_define_singleton_method (c, "read", c_read, -1);
+ rb_define_method (c, "initialize", c_init, 0);
+ rb_define_method (c, "id", c_id, 0);
+ rb_define_method (c, "submission_url", c_submission_url, 0);
+ rb_define_method (c, "freedb_id", c_freedb_id, 0);
+
+ eDiscIDError = rb_define_class_under (m, "DiscIDError", rb_eStandardError);
+ eReadError = rb_define_class_under (m, "ReadError", eDiscIDError);
+}
--- /dev/null
+#--
+# Copyright (c) 2007 Tilman Sauerbeck (tilman at code-monkey de)
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require "discid_ext"
+
+module DiscID
+ VERSION = "0.1.0"
+end
--- /dev/null
+#
+# Copyright (c) 2005, 2006 Tilman Sauerbeck (tilman at code-monkey de)
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require "rake/tasklib"
+require "rake/clean"
+require "yaml"
+require "fileutils"
+
+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 = YAML.load(File.read(CACHE_FILE)) rescue nil
+
+ 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
+ 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
+ @opts = opts
+
+ @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
+ STDOUT.reopen("/dev/null")
+ STDERR.reopen("/dev/null")
+
+ begin
+ exec(bin)
+ rescue SystemCallError
+ exit 255
+ end
+ end
+
+ Process.wait
+
+ $?.exitstatus != 255
+ end
+ end
+
+ class FooConfigTest < Test
+ def initialize(name, opts = {})
+ super
+
+ @result = {}
+ @command = "#{name}-config"
+
+ @on_checking << lambda do
+ print "checking for #{name}... "
+ STDOUT.flush
+ end
+
+ @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?
+
+ begin
+ [:version, :cflags, :libs].each do |f|
+ @result[f] = lookup_flags(f)
+ end
+ rescue Exception
+ @result.clear
+ end
+
+ !@result.empty?
+ end
+
+ protected
+ def lookup_flags(f)
+ tmp = `#{@command} --#{f}`.strip
+
+ raise unless $?.exitstatus.zero?
+ tmp
+ end
+
+ private
+ def can_exec_command?
+ can_exec_binary?(@command)
+ end
+ end
+
+ class PkgConfigTest < FooConfigTest
+ def initialize(name, opts = {})
+ super
+
+ @command = "pkg-config"
+ end
+
+ protected
+ def lookup_flags(f)
+ f = :modversion if f == :version
+
+ tmp = `#{@command} --silence-errors --#{f} #{@name}`.
+ strip.tr("\n", "/")
+
+ raise unless $?.exitstatus.zero?
+ tmp
+ end
+ end
+
+ class CompileTest < Test
+ TMP_FILE = ".compile_test"
+
+ def CompileTest.cflags
+ @@cflags
+ end
+
+ def CompileTest.cflags=(f)
+ @@cflags = f
+ end
+
+ def initialize(name, code, opts = {})
+ super(name, opts)
+
+ @code = code
+ end
+
+ def invoke
+ @result = false
+
+ cc = ENV["CC"] || "cc"
+ flags = (ENV["CFLAGS"] || "").dup
+ flags << " -I" + Config::CONFIG["archdir"]
+
+ unless @opts[:try_link]
+ flags << " -c"
+ end
+
+ File.open(TMP_FILE + ".c", "w") do |f|
+ f << @code << "\n"
+ end
+
+ `#{cc} #{flags} #{TMP_FILE}.c -o #{TMP_FILE}.o > /dev/null 2>&1`
+ @result = $?.exitstatus.zero?
+ ensure
+ FileUtils.rm_f("#{TMP_FILE}.c")
+ FileUtils.rm_f("#{TMP_FILE}.o")
+ end
+ end
+
+ class HaveFuncTest < CompileTest
+ def initialize(name, includes = [], opts = {})
+ super(name, assemble_code(name, includes), opts)
+
+ @on_checking << lambda do
+ print "checking for #{name}... "
+ STDOUT.flush
+ end
+
+ @on_success << lambda { puts "yes" }
+ @on_failure << lambda { puts "no" }
+ end
+
+ private
+ def assemble_code(func, includes)
+ header = includes.inject("") do |a, h|
+ a << "#include <#{h}>\n"
+ end
+
+ body =<<EOF
+int main () {
+ void *foo = (void *) #{func};
+ foo = (void *) 0;
+ return 0;
+}
+EOF
+
+ header + body
+ end
+ end
+ end
+end
--- /dev/null
+require 'rake'
+require 'rake/clean'
+require 'rake/tasklib'
+
+module Rake
+
+ # Create a build task that will generate a Ruby extension (e.g. .so) from one or more
+ # C (.c) or C++ (.cc, .cpp, .cxx) files, and is intended as a replcaement for mkmf.
+ # It determines platform-specific settings (e.g. file extensions, compiler flags, etc.)
+ # from rbconfig (note: examples assume *nix file extensions).
+ #
+ # *Note*: Strings vs Symbols
+ # In places where filenames are expected (e.g. lib_name and objs), Strings are used
+ # as verbatim filenames, while, Symbols have the platform-dependant extension
+ # appended (e.g. '.so' for libraries and '.o' for objects). Also, only Symbols
+ # have #dir prepended to them.
+ #
+ # Example:
+ # desc "build sample extension"
+ # # build sample.so (from foo.{c,cc,cxx,cpp}, through foo.o)
+ # Rake::ExtensionTask.new :sample => :foo do |t|
+ # # all extension files under this directory
+ # t.dir = 'ext'
+ # # link libraries (libbar.so)
+ # t.link_libs << 'bar'
+ # end
+ #
+ # Author:: Steve Sloan (mailto:steve@finagle.org)
+ # Copyright:: Copyright (c) 2006 Steve Sloan
+ # License:: GPL
+
+ class ExtensionTask < Rake::TaskLib
+ # The name of the extension
+ attr_accessor :name
+
+ # The filename of the extension library file (e.g. 'extension.so')
+ attr_accessor :lib_name
+
+ # Object files to build and link into the extension.
+ attr_accessor :objs
+
+ # The directory where the extension files (source, output, and
+ # intermediate) are stored.
+ attr_accessor :dir
+
+ # Environment configuration -- i.e. CONFIG from rbconfig, with a few other
+ # settings, and converted to lowercase-symbols.
+ attr_accessor :env
+
+ # Additional link libraries
+ attr_accessor :link_libs
+
+ # Same arguments as Rake::define_task
+ def initialize( args, &blk )
+ @env = @@DefaultEnv.dup
+ @name, @objs = resolve_args(args)
+ set_defaults
+ yield self if block_given?
+ define_tasks
+ end
+
+ # Generate default values. This is called from initialize _before_ the
+ # yield block.
+ #
+ # Defaults:
+ # - lib_name: name.so
+ # - objs: name.o (<- name.{c,cxx,cpp,cc})
+ # - dir: .
+ # - link_libs: <none>
+ def set_defaults
+ @lib_name ||= name.to_sym
+ @objs ||= [name.to_sym]
+ @dir ||= '.'
+ @link_libs ||= []
+ end
+
+ # Defines the library task.
+ def define_tasks
+ output_objs = @objs.collect { |obj| filepath obj, :objext }
+ output_lib = filepath lib_name, :dlext
+
+ task name => output_lib
+
+ file output_lib => output_objs do |t|
+ sh_cmd :ldshared, :dldflags, :ldflags,
+ {'-L' => :libdirs}, '-o', output_lib,
+ output_objs.join(' '),
+ link_libs.join(' '),
+ :libs, :dldlibs, :librubyarg_shared
+ end
+
+ CLEAN.include output_objs
+ CLOBBER.include output_lib
+ define_rules
+ end
+
+ # Defines C and C++ source-to-object rules, using the source extensions from env.
+ def define_rules
+ for ext in env[:c_exts]
+ Rake::Task.create_rule '.'+env[:objext] => '.'+ext do |r|
+ sh_cmd :cc, :cflags, :cppflags, {'-D' => :defines}, {'-I' => :includedirs}, {'-I' => :topdir},
+ '-c', '-o', r.name, r.sources
+ end
+ end
+
+ for ext in env[:cpp_exts]
+ Rake::Task.create_rule '.'+env[:objext] => '.'+ext do |r|
+ sh_cmd :cxx, :cxxflags, :cppflags, {'-D' => :defines}, {'-I' => :includedirs}, {'-I' => :topdir},
+ '-o', r.name, '-c', r.sources
+ end
+ end
+ end
+
+ class << self
+ # The default environment for all extensions.
+ @@DefaultEnv = {}
+ def env
+ @@DefaultEnv
+ end
+ def env=(e)
+ @@DefaultEnv = e
+ end
+
+ Config::CONFIG.merge(ENV).each { |k, v| @@DefaultEnv[k.downcase.to_sym] = v }
+ @@DefaultEnv = {
+ :cxx => 'c++',
+ :cxxflags => '',
+ :c_exts => ['c'],
+ :cpp_exts => ['cc', 'cxx', 'cpp'],
+ :includedirs => [],
+ :libdirs => [],
+ }.update(@@DefaultEnv)
+ end
+
+ protected
+
+ # Handles convenience filenames:
+ # * f (String) => f
+ # * f (Symbol) => dir/f.ext
+ def filepath( f, ext )
+ ext = env[ext] if Symbol === ext
+ Symbol === f ? File.join( dir, "#{f}.#{ext}" ) : f
+ end
+
+ # Convenience function for cnstructing command lines for build tools.
+ def optify( *opts )
+ return optify(*opts.first) if opts.size == 1 and opts.first.kind_of? Array
+ opts.collect do |opt|
+ case opt
+ when String then opt
+ when Symbol then optify env[opt]
+ when Hash
+ opt.collect do |k, v|
+ v = env[v] if v.kind_of? Symbol
+ if v.kind_of? Array
+ optify v.collect { |w| k.to_s + w.to_s }
+ elsif v
+ k.to_s + v.to_s
+ end
+ end
+ else
+ opt.to_s
+ end
+ end.join(' ').squeeze(' ')
+ end
+
+ def sh_cmd( cmd, *opts )
+ sh optify( cmd, *opts )
+ end
+
+ # For some reason, Rake::TaskManager.resolve_args can't be found, so snarf it.
+ def resolve_args(args)
+ case args
+ when Hash
+ fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1
+ fail "No Task Name Given" if args.size < 1
+ task_name = args.keys[0]
+ deps = args[task_name]
+ deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps)
+ else
+ task_name = args
+ deps = []
+ end
+ [task_name, deps]
+ end
+
+ end
+
+end