BuildSourceBuildRule

class Rule

A rule is a function with a specific set of input and output parameters, which can match against a given set of specific arguments. For example, there might be several rules for compiling, but the specific rules depend on the language being compiled.

Nested

Definitions

def self.build(name, &block)

Build a frozen rule from a name and a definition block.

Signature

parameter name String

The rule name in "process.type" format.

returns Build::Rule

The constructed and frozen rule.

Implementation

def self.build(name, &block)
	rule = self.new(*name.split(".", 2))
	
	rule.instance_eval(&block)
	
	return rule.freeze
end

def initialize(process_name, type)

Initialize a rule with a process name and type.

Signature

parameter process_name String

The process name, e.g. "compile".

parameter type String

The file type, e.g. "cpp".

Implementation

def initialize(process_name, type)
	@name = process_name + "." + type
	@full_name = @name.gsub(/[^\w]/, "_")
	
	@process_name = process_name.gsub("-", "_").to_sym
	@type = type
	
	@apply = nil
	
	@parameters = []
	@primary_output = nil
end

attr :name

compile.cpp

attr :process_name

compile

attr :full_name

compile_cpp

def freeze

Freeze the rule and all its components.

Signature

returns Build::Rule

The frozen rule.

Implementation

def freeze
	return self if frozen?
	
	@name.freeze
	@full_name.freeze
	@process_name.freeze
	@type.freeze
	
	@apply.freeze
	@parameters.freeze
	@primary_output.freeze
	
	super
end

def input(name, options = {}, &block)

Add an input parameter to the rule.

Signature

parameter name Symbol

The parameter name.

parameter options Hash

Parameter options.

Implementation

def input(name, options = {}, &block)
	self << Parameter.new(:input, name, options, &block)
end

def parameter(name, options = {}, &block)

Add a generic argument parameter to the rule.

Signature

parameter name Symbol

The parameter name.

parameter options Hash

Parameter options.

Implementation

def parameter(name, options = {}, &block)
	self << Parameter.new(:argument, name, options, &block)
end

def output(name, options = {}, &block)

Add an output parameter to the rule.

Signature

parameter name Symbol

The parameter name.

parameter options Hash

Parameter options.

Implementation

def output(name, options = {}, &block)
	self << Parameter.new(:output, name, options, &block)
end

def <<(parameter)

Append a parameter to the rule.

Signature

parameter parameter Build::Rule::Parameter

The parameter to add.

Implementation

def << parameter
	@parameters << parameter
	
	if parameter.output?
		@primary_output ||= parameter
	end
end

def applicable?(arguments)

Check if this rule can process these parameters

Implementation

def applicable?(arguments)
	@parameters.each do |parameter|
		next if parameter.implicit?
		
		return false unless parameter.applicable?(arguments)
	end
	
	return true
end

def normalize(arguments, scope)

The scope is the context in which the dynamic rule computation is done, usually an instance of Task.

Implementation

def normalize(arguments, scope)
	Hash[
		@parameters.collect do |parameter|
			[parameter.name, parameter.compute(arguments, scope)]
		end
	]
end

def files(arguments)

Derive the input and output file lists from the given arguments.

Signature

parameter arguments Hash

The argument set.

returns Array(Build::Files::Composite, Build::Files::Composite)

Input and output file composites.

Implementation

def files(arguments)
	input_files = []
	output_files = []
	
	@parameters.each do |parameter|
		# This could probably be improved a bit, we are assuming all parameters are file based:
		value = arguments[parameter.name]
		
		next unless value
		
		case parameter.direction
		when :input
			input_files << value
		when :output
			output_files << value
		end
	end
	
	return Build::Files::Composite.new(input_files), Build::Files::Composite.new(output_files)
end

def apply(&block)

Set the apply block that is executed when the rule is invoked.

Implementation

def apply(&block)
	@apply = Proc.new(&block)
end

def apply!(scope, arguments)

Apply the rule in the given scope with the provided arguments.

Signature

parameter scope Object

The task scope.

parameter arguments Hash

The normalised arguments.

Implementation

def apply!(scope, arguments)
	scope.instance_exec(arguments, &@apply) if @apply
end

def result(arguments)

Signature

returns Object | Nil

The primary output value from the given arguments, if any.

Implementation

def result(arguments)
	if @primary_output
		arguments[@primary_output.name]
	end
end

def hash

Signature

returns Integer

A hash value for this rule.

Implementation

def hash
	[self.class, @name, @parameters].hash
end

def eql?(other)

Signature

returns Boolean

Whether this rule is equal to another by name and parameters.

Implementation

def eql?(other)
	other.kind_of?(self.class) and @name.eql?(other.name) and @parameters.eql?(other.parameters)
end

def to_s

Signature

returns String

A human-readable representation of the rule.

Implementation

def to_s
	"#<#{self.class} #{@name.dump}>"
end