view scripts/gen.rb @ 20:6255d355d752

Made it compile with dmd 1.056
author Jacob Carlborg <doob@me.com>
date Wed, 03 Feb 2010 18:28:01 +0100
parents d0162d8ca0f2
children
line wrap: on
line source

#!/usr/bin/env ruby

##
# Copyright:: Copyright (c) 2009 Jacob Carlborg.
# Author:: Jacob Carlborg
# Version:: Initial created: 2009
# License:: [Boost Software License 1.0]http://www.boost.org/LICENSE_1_0.txt
#

require "rubygems"
gem "xml-simple"
require "xmlsimple"
require "optparse"
require "date"

# Extensions to String
class String
	
	# Returns the index of the given character or length of the string if not found
	# char:: the character to look for
	# start:: the index where to start the search
	# 
	# === Example:
	# "012345789".index_of("1")		#=> 1
	# "0123 0123".index_of("3", 6)	#=> 8
	# 
	def index_of (char, start = 0)
		return self.length if start >= self.length
		
		i = 0
		
		if start == 0
			self.each_char do |c|
				return i if char == c
				i += 1			
			end
		else
			self[start + 1 .. -1].each_char do |c|
				return i + start + 1 if char == c
				i += 1			
			end
		end
		
		return self.length
	end
end

class Generator
	VERSION = 1.0
	
	attr_accessor :dependencies_switch, :out_dir, :private
	
	def initialize
		@frameworks = []
		@do_64bit = false
		@dependencies_switch = false
		@dependencies = {}
		@private = false
	end
	
	def framework_path (val)
		return val if File.exist?(val)
		
		val += ".framework" unless /\.framework$/.match(val)
		paths = ["/System/Library/Frameworks", "/Library/Frameworks", "#{ENV['HOME']}/Library/Frameworks"]
		paths << "/System/Library/PrivateFrameworks" if @private
		
		paths.each do |dir|
			path = File.join(dir, val)
			return path if File.exist?(path)
		end
		
		return nil
	end
	
 	def add_framework (framework)
 		@frameworks << framework_path(framework)
 	end
	 
	def collect_dependencies (framework)
		result = `./dstepgen.rb -f #{framework} -d`
		@dependencies[framework] = {}
		
		result.each_line do |path|
			path = path[0 .. -2] # remove the newline
			@dependencies[framework][path] = true
			collect_dependencies(path) unless @dependencies.key?(path)
		end
	end
	
	def write_dependencies
		@frameworks.each do |framework|
			collect_dependencies(framework) 
		end		
		
		file = STDOUT
		
		@dependencies.each do |key, value|
			file << "#{key}\n"
		end
		
		exit
	end
	
	def generate
		dstep_file = "Frameworks.dstep"
		
		@frameworks.each do |framework|
			collect_dependencies(framework)
		end
		
		str = StringIO.new
		
		frameworks = []
		
		@dependencies.each do |framework, value|
			frameworks << get_umbrella_framework(framework)
		end
		
		frameworks.uniq!
		
		frameworks.each do |framework|
			str << " -f "
			str << framework
		end
		
		`./dstepgen.rb -o #{@out_dir}/#{dstep_file} #{str.string}`
		`./dgen.rb -o #{@out_dir} #{@out_dir}/#{dstep_file}`
	end
	
	def get_framework_name (framework)
		i = framework.rindex(".framework")
		return framework if i.nil?
		x = framework.rindex("/", i)
		framework[x + 1 ... i]
	end
	
	def get_umbrella_framework (framework)
		str = ".framework"
		i = framework.index(str)
		return framework[0 ... i + str.length] unless i.nil?
		framework
	end
end

# Prints the message to stderr, exits
def die (*msg)
	$stderr.puts msg
	exit 1
end

if __FILE__ == $0
	gen = Generator.new
	
	OptionParser.new do |opts|
		opts.banner = "Usage: #{File.basename(__FILE__)} [options] <frameworks...>"
		opts.separator ""
		opts.separator "Options:"
		
		opts.on("-u", "--umbrella FRAMEWORK", "Link againts the given umbrella framework.") do |opt|
			gen.umbrella_framework(opt)
		end
		
		opts.on(nil, "--64-bit", "Write 64-bit annotations.") do
			gen.do_64bit = true
		end
		
		opts.on("-p", "--private", "Include private frameworks.") do |opt|
			gen.private = true
		end
		
		opts.on("-o", "--output DIRECTORY", "Place the output file(s) in this directory.") do |opt|
			die "The specified directory \"#{opt}\" does not exists" if File.exist?(opt) == false
			die "Output directory cannot be specified more than once" if gen.out_dir
			gen.out_dir = opt
		end
		
		opts.on("-c", "--code CODE", "Inject CODE in the type file.") do |opt|
			gen.code_to_inject = opt
		end
		
		opts.on("-d", "--dependencies", "Write dependencies to stdout and exit.") do |opt|
			gen.dependencies_switch = true
		end
		
		help_msg = "Use the `-h' flag or for help."	
			
		opts.on("-h", "--help", "Show this message and exit.") do
			puts opts, help_msg
			exit
		end
		
		opts.on('-v', '--version', 'Show version and exit.') do
			puts Generator::VERSION
			exit
		end
		
		opts.separator ""
		
		if ARGV.empty?			
			die opts.banner
		else
			begin
				opts.parse!(ARGV)
				
				ARGV.each do |framework|
					gen.add_framework(framework)
				end
				
				gen.write_dependencies if gen.dependencies_switch
				
				die "No output directory given" if gen.out_dir.nil?
				
				gen.generate
			rescue => e
				msg = e.message
				msg = "Internal error" if msg.empty?
				
				die msg, opts.banner, help_msg
			end
		end
	end
end