add/update YARD documentation

This commit is contained in:
Josh Holtrop 2013-08-04 15:39:01 -04:00
parent c0a69a5055
commit 8d4be1b51a
10 changed files with 160 additions and 35 deletions

View File

@ -11,6 +11,7 @@ require "rscons/monkey/string"
require "rscons/builders/object"
require "rscons/builders/program"
# Namespace module for rscons classes
module Rscons
DEFAULT_BUILDERS = [
Object,

View File

@ -1,8 +1,18 @@
module Rscons
# Class to hold an object that knows how to build a certain type of file.
class Builder
# Return a set of default variable values for the Environment to use
# unless the user overrides any.
# @param env [Environment] The Environment.
def default_variables(env)
{}
end
# Return whether this builder object is capable of producing a given target
# file name from a given source file name.
# @param target [String] The target file name.
# @param source [String, Array] The source file name(s).
# @param env [Environment] The Environment.
def produces?(target, source, env)
false
end

View File

@ -1,4 +1,6 @@
module Rscons
# A default RScons builder which knows how to produce an object file from
# various types of source files.
class Object < Builder
def default_variables(env)
{

View File

@ -1,4 +1,6 @@
module Rscons
# A default RScons builder that knows how to link object files into an
# executable program.
class Program < Builder
def default_variables(env)
{

View File

@ -5,46 +5,55 @@ require 'set'
require 'rscons/version'
module Rscons
# The Cache class keeps track of file checksums, build target commands and
# dependencies in a YAML file which persists from one invocation to the next.
# Example cache:
# {
# version: '1.2.3',
# targets: {
# 'program' => {
# 'checksum' => 'A1B2C3D4',
# 'command' => ['gcc', '-o', 'program', 'program.o'],
# 'deps' => [
# {
# 'fname' => 'program.o',
# 'checksum' => '87654321',
# }
# ],
# }
# 'program.o' => {
# 'checksum' => '87654321',
# 'command' => ['gcc', '-c', '-o', 'program.o', 'program.c'],
# 'deps' => [
# {
# 'fname' => 'program.c',
# 'checksum' => '456789ABC',
# },
# {
# 'fname' => 'program.h',
# 'checksum' => '7979764643',
# }
# ]
# {
# version: '1.2.3',
# targets: {
# 'program' => {
# 'checksum' => 'A1B2C3D4',
# 'command' => ['gcc', '-o', 'program', 'program.o'],
# 'deps' => [
# {
# 'fname' => 'program.o',
# 'checksum' => '87654321',
# }
# ],
# }
# 'program.o' => {
# 'checksum' => '87654321',
# 'command' => ['gcc', '-c', '-o', 'program.o', 'program.c'],
# 'deps' => [
# {
# 'fname' => 'program.c',
# 'checksum' => '456789ABC',
# },
# {
# 'fname' => 'program.h',
# 'checksum' => '7979764643',
# }
# ]
# }
# }
# }
# }
class Cache
# Constants
#### Constants
# Name of the file to store cache information in
CACHE_FILE = '.rsconscache'
# Class Methods
#### Class Methods
# Remove the cache file
def self.clear
FileUtils.rm_f(CACHE_FILE)
end
# Instance Methods
#### Instance Methods
# Create a Cache object and load in the previous contents from the cache
# file.
def initialize
@cache = YAML.load(File.read(CACHE_FILE)) rescue {
targets: {},
@ -53,12 +62,30 @@ module Rscons
@lookup_checksums = {}
end
# Write the cache to disk to be loaded next time.
def write
File.open(CACHE_FILE, 'w') do |fh|
fh.puts(YAML.dump(@cache))
end
end
# Check if a target is up to date
# @param target [String] The name of the target file.
# @param command [Array] The command used to build the target.
# @param deps [Array] List of the target's dependency files.
# @param options [Hash] Optional options. Can contain the following keys:
# :strict_deps::
# Only consider a target up to date if its list of dependencies is
# exactly equal (including order) to the cached list of dependencies
# @return true value if the target is up to date, meaning that:
# - the target exists on disk
# - the cache has information for the target
# - the command used to build the target is the same as last time
# - all dependencies listed are also listed in the cache, or, if
# :strict_deps was given in options, the list of dependencies is
# exactly equal to those cached
# - each cached dependency file's current checksum matches the checksum
# stored in the cache file
def up_to_date?(target, command, deps, options = {})
# target file must exist on disk
return false unless File.exists?(target)
@ -84,6 +111,10 @@ module Rscons
end.all?
end
# Store cache information about a target built by a builder
# @param target [String] The name of the target.
# @param command [Array] The command used to build the target.
# @param deps [Array] List of dependencies for the target.
def register_build(target, command, deps)
@cache[:targets][target] = {
command: command,
@ -100,10 +131,15 @@ module Rscons
# Private Instance Methods
private
# Return a file's checksum, or the previously calculated checksum for
# the same file
# @param file [String] The file name.
def lookup_checksum(file)
@lookup_checksums[file] || calculate_checksum(file)
end
# Calculate and return a file's checksum
# @param file [String] The file name.
def calculate_checksum(file)
@lookup_checksums[file] = Digest::MD5.hexdigest(File.read(file)).encode(__ENCODING__) rescue ''
end

View File

@ -2,14 +2,17 @@ require 'set'
require 'fileutils'
module Rscons
# The Environment class is the main programmatic interface to RScons. It
# contains a collection of construction variables, options, builders, and
# rules for building targets.
class Environment
# [Array] of {Builder} objects.
attr_reader :builders
# Initialize a newly constructed Environment object
# === Arguments
# +variables+ _Hash_ ::
# the variables hash can contain both construction variables, which are
# uppercase strings (such as "CC" or "LDFLAGS"), and rscons options,
# Create an Environment object.
# @param variables [Hash]
# The variables hash can contain both construction variables, which are
# uppercase strings (such as "CC" or "LDFLAGS"), and RScons options,
# which are lowercase symbols (such as :echo).
def initialize(variables = {})
@varset = VarSet.new(variables)
@ -36,6 +39,10 @@ module Rscons
end
end
# Make a copy of the Environment object.
# The cloned environment will contain a copy of all environment options,
# construction variables, builders, and build directories. It will not
# contain a copy of the targets.
def clone(variables = {})
env = Environment.new()
@builders.each do |builder_name, builder|
@ -54,6 +61,7 @@ module Rscons
env
end
# Add a {Builder} object to the Environment.
def add_builder(builder)
@builders[builder.class.short_name] = builder
var_defs = builder.default_variables(self)
@ -64,10 +72,16 @@ module Rscons
end
end
# Specify a build directory for this Environment.
# Source files from src_dir will produce object files under obj_dir.
def build_dir(src_dir, obj_dir)
@build_dirs[src_dir.gsub('\\', '/')] = obj_dir.gsub('\\', '/')
end
# Return the file name to be built from source_fname with suffix suffix.
# This method takes into account the Environment's build directories.
# It also creates any parent directories needed to be able to open and
# write to the output file.
def get_build_fname(source_fname, suffix)
build_fname = source_fname.set_suffix(suffix).gsub('\\', '/')
@build_dirs.each do |src_dir, obj_dir|
@ -77,26 +91,37 @@ module Rscons
build_fname
end
# Access a construction variable or environment option.
# @see VarSet#[]
def [](*args)
@varset.send(:[], *args)
end
# Set a construction variable or environment option.
# @see VarSet#[]=
def []=(*args)
@varset.send(:[]=, *args)
end
# Add a set of construction variables or environment options.
# @see VarSet#append
def append(*args)
@varset.send(:append, *args)
end
# Return a list of target file names
def targets
@targets.keys
end
# Return a list of sources needed to build target target.
def target_sources(target)
@targets[target][:source] rescue nil
end
# Build all target specified in the Environment.
# When a block is passed to Environment.new, this method is automatically
# called after the block returns.
def process
cache = Cache.new
targets_processed = Set.new
@ -123,10 +148,23 @@ module Rscons
cache.write
end
# Build a command line from the given template, resolving references to
# variables using the Environment's construction variables and any extra
# variables specified.
# @param command_template [Array] template for the command with variable
# references
# @param extra_vars [Hash, VarSet] extra variables to use in addition to
# (or replace) the Environment's construction variables when building
# the command
def build_command(command_template, extra_vars)
@varset.merge(extra_vars).expand_varref(command_template)
end
# Execute a builder command
# @param short_desc [String] Message to print if the Environment's :echo
# mode is set to :short
# @param command [Array] The command to execute.
# @param options [Hash] Optional options to pass to {Kernel#system}.
def execute(short_desc, command, options = {})
print_command = proc do
puts command.map { |c| c =~ /\s/ ? "'#{c}'" : c }.join(' ')
@ -159,6 +197,10 @@ module Rscons
end
end
# Parse dependencies for a given target from a Makefile.
# This method is used internally by RScons builders.
# @param mf_fname [String] File name of the Makefile to read.
# @param target [String] Name of the target to gather dependencies for.
def parse_makefile_deps(mf_fname, target)
deps = []
buildup = ''

View File

@ -1,4 +1,6 @@
# Standard Ruby Module class.
class Module
# @return the base module name (not the fully qualified name)
def short_name
name.split(':').last
end

View File

@ -1,4 +1,8 @@
# Standard Ruby String class.
class String
# Check if the given string ends with any of the supplied suffixes
# @param suffix [String, Array] The suffix to look for.
# @return a true value if the string ends with one of the suffixes given.
def has_suffix?(suffix)
if suffix
suffix = [suffix] if suffix.is_a?(String)
@ -6,6 +10,9 @@ class String
end
end
# Return a new string with the suffix (dot character and extension) changed
# to the given suffix.
# @param suffix [String] The new suffix.
def set_suffix(suffix = '')
sub(/\.[^.]*$/, suffix)
end

View File

@ -1,11 +1,23 @@
module Rscons
# This class represents a collection of variables which can be accessed
# as certain types
class VarSet
# The underlying hash
attr_reader :vars
# Create a VarSet
# @param vars [Hash] Optional initial variables.
def initialize(vars = {})
@vars = vars
end
# Access the value of variable as a particular type
# @param key [String, Symbol] The variable name.
# @param type [Symbol, nil] Optional specification of the type desired.
# If the variable is a String and type is :array, a 1-element array with
# the variable value will be returned. If the variable is an Array and
# type is :string, the first element from the variable value will be
# returned.
def [](key, type = nil)
val = @vars[key]
if type == :array and val.is_a?(String)
@ -17,21 +29,31 @@ module Rscons
end
end
# Assign a value to a variable.
# @param key [String, Symbol] The variable name.
# @param val [Object] The value.
def []=(key, val)
@vars[key] = val
end
# Add or overwrite a set of variables
# @param values [VarSet, Hash] New set of variables.
def append(values)
values = values.vars if values.is_a?(VarSet)
@vars.merge!(values)
self
end
# Create a new VarSet object based on the first merged with other.
# @param other [VarSet, Hash] Other variables to add or overwrite.
def merge(other = {})
VarSet.new(Marshal.load(Marshal.dump(@vars))).append(other)
end
alias_method :clone, :merge
# Replace "$" variable references in varref with the variables values,
# recursively.
# @param varref [String, Array] Value containing references to variables.
def expand_varref(varref)
if varref.is_a?(Array)
varref.map do |ent|

View File

@ -1,3 +1,4 @@
module Rscons
# gem version
VERSION = "0.0.1"
end