Create builder features

Pass desired features to Builder#produces?
Allow features to be passed in to Environment#register_builds.
Use features in Environment#get_build_fname to determine build file name.
This commit is contained in:
Josh Holtrop 2017-05-30 15:30:15 -04:00
parent c7e4e1ad9b
commit 19a23c2aa9
2 changed files with 81 additions and 16 deletions

View File

@ -47,14 +47,35 @@ module Rscons
# Return whether this builder object is capable of producing a given target # Return whether this builder object is capable of producing a given target
# file name from a given source file name. # file name from a given source file name.
# #
# @param target [String] The target file name. # @overload produces?(target, source, env)
# @param source [String] The source file name. #
# @param env [Environment] The Environment. # @param target [String]
# The target file name.
# @param source [String]
# The source file name.
# @param env [Environment]
# The Environment.
#
# @overload produces?(options)
#
# @since 1.10.0
#
# @param options [Hash]
# Options.
# @option options [String] :target
# Target file name.
# @option options [String] :source
# Source file name.
# @option options [Environment] :env
# The Environment.
# @option options [Hash] :features
# Features that this builder must satisfy.
# See {Environment#register_builds}.
# #
# @return [Boolean] # @return [Boolean]
# Whether this builder object is capable of producing a given target # Whether this builder object is capable of producing a given target
# file name from a given source file name. # file name from a given source file name.
def produces?(target, source, env) def produces?(options)
false false
end end

View File

@ -230,29 +230,37 @@ module Rscons
# #
# This method takes into account the Environment's build directories. # This method takes into account the Environment's build directories.
# #
# @param source_fname [String] Source file name. # @param source_fname [String]
# @param suffix [String] Suffix, including "." if desired. # Source file name.
# @param suffix [String]
# Suffix, including "." if desired.
# @param options [Hash]
# Extra options.
# @option options [Hash] :features
# Builder features to be used for this build. See {#register_builds}.
# #
# @return [String] # @return [String]
# The file name to be built from +source_fname+ with suffix +suffix+. # The file name to be built from +source_fname+ with suffix +suffix+.
def get_build_fname(source_fname, suffix) def get_build_fname(source_fname, suffix, options = {})
build_fname = Rscons.set_suffix(source_fname, suffix).gsub('\\', '/') build_fname = Rscons.set_suffix(source_fname, suffix).gsub('\\', '/')
options[:features] ||= {}
extra_path = options[:features][:shared] ? "/_shared" : ""
found_match = @build_dirs.find do |src_dir, obj_dir| found_match = @build_dirs.find do |src_dir, obj_dir|
if src_dir.is_a?(Regexp) if src_dir.is_a?(Regexp)
build_fname.sub!(src_dir, obj_dir) build_fname.sub!(src_dir, "#{obj_dir}#{extra_path}")
else else
build_fname.sub!(%r{^#{src_dir}/}, "#{obj_dir}/") build_fname.sub!(%r{^#{src_dir}/}, "#{obj_dir}#{extra_path}/")
end end
end end
unless found_match unless found_match
if Rscons.absolute_path?(build_fname) if Rscons.absolute_path?(build_fname)
if build_fname =~ %r{^(\w):(.*)$} if build_fname =~ %r{^(\w):(.*)$}
build_fname = "#{@build_root}/_#{$1}#{$2}" build_fname = "#{@build_root}#{extra_path}/_#{$1}#{$2}"
else else
build_fname = "#{@build_root}/_#{build_fname}" build_fname = "#{@build_root}#{extra_path}/_#{build_fname}"
end end
elsif !build_fname.start_with?("#{@build_root}/") elsif !build_fname.start_with?("#{@build_root}/")
build_fname = "#{@build_root}/#{build_fname}" build_fname = "#{@build_root}#{extra_path}/#{build_fname}"
end end
end end
build_fname.gsub('\\', '/') build_fname.gsub('\\', '/')
@ -533,7 +541,9 @@ module Rscons
converted = nil converted = nil
suffixes.each do |suffix| suffixes.each do |suffix|
converted_fname = get_build_fname(source, suffix) converted_fname = get_build_fname(source, suffix)
builder = @builders.values.find { |b| b.produces?(converted_fname, source, self) } builder = @builders.values.find do |builder|
builder_produces?(builder, target: converted_fname, source: source)
end
if builder if builder
converted = run_builder(builder, converted_fname, [source], cache, vars) converted = run_builder(builder, converted_fname, [source], cache, vars)
return nil unless converted return nil unless converted
@ -561,10 +571,15 @@ module Rscons
# List of suffixes to try to convert source files into. # List of suffixes to try to convert source files into.
# @param vars [Hash] # @param vars [Hash]
# Extra variables to pass to the builders. # Extra variables to pass to the builders.
# @param options [Hash]
# Extra options.
# @option options [Hash] :features
# Set of features the builder must provide.
# * :shared - builder builds a shared object/library
# #
# @return [Array<String>] # @return [Array<String>]
# List of the output file name(s). # List of the output file name(s).
def register_builds(target, sources, suffixes, vars) def register_builds(target, sources, suffixes, vars, options = {})
@registered_build_dependencies[target] ||= Set.new @registered_build_dependencies[target] ||= Set.new
sources.map do |source| sources.map do |source|
if source.end_with?(*suffixes) if source.end_with?(*suffixes)
@ -572,9 +587,13 @@ module Rscons
else else
output_fname = nil output_fname = nil
suffixes.each do |suffix| suffixes.each do |suffix|
attempt_output_fname = get_build_fname(source, suffix) attempt_output_fname = get_build_fname(source, suffix, features: options[:features])
builder = @builders.values.find do |builder| builder = @builders.values.find do |builder|
builder.produces?(attempt_output_fname, source, self) builder_produces?(
builder,
target: attempt_output_fname,
source: source,
features: options[:features])
end end
if builder if builder
output_fname = attempt_output_fname output_fname = attempt_output_fname
@ -932,6 +951,31 @@ module Rscons
tc: tc)) tc: tc))
end end
# Determine if a builder produces an output file of a given name with
# requested features.
#
# @param builder [Builder]
# The builder.
# @param options [Hash]
# Options for {Builder#produces?}.
# @option options [String] :target
# Target file name.
# @option options [String] :source
# Source file name.
# @option options [Hash] :features
# Builder features. See {#register_builds}.
#
# @return [Boolean]
# Whether the builder produces a file of the given name from the source
# given with the features given.
def builder_produces?(builder, options)
if builder.method(:produces?).arity == 3
builder.produces?(options[:target], options[:source], self)
else
builder.produces?(options.merge(env: self))
end
end
# Parse dependencies for a given target from a Makefile. # Parse dependencies for a given target from a Makefile.
# #
# This method is used internally by Rscons builders. # This method is used internally by Rscons builders.