support phony targets - close #25
This commit is contained in:
parent
7698fbf618
commit
7a04bec2ff
@ -65,6 +65,15 @@ module Rscons
|
|||||||
path =~ %r{^(/|\w:[\\/])}
|
path =~ %r{^(/|\w:[\\/])}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return whether the given target is a phony target.
|
||||||
|
#
|
||||||
|
# @param target [Symbol, String] Target name.
|
||||||
|
#
|
||||||
|
# @return [Boolean] Whether the given target is a phony target.
|
||||||
|
def self.phony_target?(target)
|
||||||
|
target.is_a?(Symbol)
|
||||||
|
end
|
||||||
|
|
||||||
# Return a new path by changing the suffix in path to suffix.
|
# Return a new path by changing the suffix in path to suffix.
|
||||||
#
|
#
|
||||||
# @param path [String] The path to alter.
|
# @param path [String] The path to alter.
|
||||||
|
@ -87,8 +87,10 @@ module Rscons
|
|||||||
# The name of the target on success or false on failure.
|
# The name of the target on success or false on failure.
|
||||||
def standard_build(short_cmd_string, target, command, sources, env, cache)
|
def standard_build(short_cmd_string, target, command, sources, env, cache)
|
||||||
unless cache.up_to_date?(target, command, sources, env)
|
unless cache.up_to_date?(target, command, sources, env)
|
||||||
cache.mkdir_p(File.dirname(target))
|
unless Rscons.phony_target?(target)
|
||||||
FileUtils.rm_f(target)
|
cache.mkdir_p(File.dirname(target))
|
||||||
|
FileUtils.rm_f(target)
|
||||||
|
end
|
||||||
return false unless env.execute(short_cmd_string, command)
|
return false unless env.execute(short_cmd_string, command)
|
||||||
cache.register_build(target, command, sources, env)
|
cache.register_build(target, command, sources, env)
|
||||||
end
|
end
|
||||||
|
@ -56,6 +56,9 @@ module Rscons
|
|||||||
# Name of the file to store cache information in
|
# Name of the file to store cache information in
|
||||||
CACHE_FILE = ".rsconscache"
|
CACHE_FILE = ".rsconscache"
|
||||||
|
|
||||||
|
# Prefix for phony cache entries.
|
||||||
|
PHONY_PREFIX = ":PHONY:"
|
||||||
|
|
||||||
# Create a Cache object and load in the previous contents from the cache
|
# Create a Cache object and load in the previous contents from the cache
|
||||||
# file.
|
# file.
|
||||||
def initialize
|
def initialize
|
||||||
@ -92,7 +95,8 @@ module Rscons
|
|||||||
|
|
||||||
# Check if target(s) are up to date.
|
# Check if target(s) are up to date.
|
||||||
#
|
#
|
||||||
# @param targets [String, Array<String>] The name(s) of the target file(s).
|
# @param targets [Symbol, String, Array<String>]
|
||||||
|
# The name(s) of the target file(s).
|
||||||
# @param command [String, Array, Hash]
|
# @param command [String, Array, Hash]
|
||||||
# The command used to build the target. The command parameter can
|
# The command used to build the target. The command parameter can
|
||||||
# actually be a String, Array, or Hash and could contain information
|
# actually be a String, Array, or Hash and could contain information
|
||||||
@ -120,19 +124,25 @@ module Rscons
|
|||||||
# stored in the cache file
|
# stored in the cache file
|
||||||
def up_to_date?(targets, command, deps, env, options = {})
|
def up_to_date?(targets, command, deps, env, options = {})
|
||||||
Array(targets).each do |target|
|
Array(targets).each do |target|
|
||||||
# target file must exist on disk
|
cache_key = get_cache_key(target)
|
||||||
return false unless File.exists?(target)
|
|
||||||
|
unless Rscons.phony_target?(target)
|
||||||
|
# target file must exist on disk
|
||||||
|
return false unless File.exists?(target)
|
||||||
|
end
|
||||||
|
|
||||||
# target must be registered in the cache
|
# target must be registered in the cache
|
||||||
return false unless @cache["targets"].has_key?(target)
|
return false unless @cache["targets"].has_key?(cache_key)
|
||||||
|
|
||||||
# target must have the same checksum as when it was built last
|
unless Rscons.phony_target?(target)
|
||||||
return false unless @cache["targets"][target]["checksum"] == lookup_checksum(target)
|
# target must have the same checksum as when it was built last
|
||||||
|
return false unless @cache["targets"][cache_key]["checksum"] == lookup_checksum(target)
|
||||||
|
end
|
||||||
|
|
||||||
# command used to build target must be identical
|
# command used to build target must be identical
|
||||||
return false unless @cache["targets"][target]["command"] == Digest::MD5.hexdigest(command.inspect)
|
return false unless @cache["targets"][cache_key]["command"] == Digest::MD5.hexdigest(command.inspect)
|
||||||
|
|
||||||
cached_deps = @cache["targets"][target]["deps"] || []
|
cached_deps = @cache["targets"][cache_key]["deps"] || []
|
||||||
cached_deps_fnames = cached_deps.map { |dc| dc["fname"] }
|
cached_deps_fnames = cached_deps.map { |dc| dc["fname"] }
|
||||||
if options[:strict_deps]
|
if options[:strict_deps]
|
||||||
# depedencies passed in must exactly equal those in the cache
|
# depedencies passed in must exactly equal those in the cache
|
||||||
@ -144,7 +154,7 @@ module Rscons
|
|||||||
|
|
||||||
# set of user dependencies must match
|
# set of user dependencies must match
|
||||||
user_deps = env.get_user_deps(target) || []
|
user_deps = env.get_user_deps(target) || []
|
||||||
cached_user_deps = @cache["targets"][target]["user_deps"] || []
|
cached_user_deps = @cache["targets"][cache_key]["user_deps"] || []
|
||||||
cached_user_deps_fnames = cached_user_deps.map { |dc| dc["fname"] }
|
cached_user_deps_fnames = cached_user_deps.map { |dc| dc["fname"] }
|
||||||
return false unless user_deps == cached_user_deps_fnames
|
return false unless user_deps == cached_user_deps_fnames
|
||||||
|
|
||||||
@ -159,7 +169,8 @@ module Rscons
|
|||||||
|
|
||||||
# Store cache information about target(s) built by a builder.
|
# Store cache information about target(s) built by a builder.
|
||||||
#
|
#
|
||||||
# @param targets [String, Array<String>] The name of the target(s) built.
|
# @param targets [Symbol, String, Array<String>]
|
||||||
|
# The name of the target(s) built.
|
||||||
# @param command [String, Array, Hash]
|
# @param command [String, Array, Hash]
|
||||||
# The command used to build the target. The command parameter can
|
# The command used to build the target. The command parameter can
|
||||||
# actually be a String, Array, or Hash and could contain information
|
# actually be a String, Array, or Hash and could contain information
|
||||||
@ -172,9 +183,10 @@ module Rscons
|
|||||||
# @return [void]
|
# @return [void]
|
||||||
def register_build(targets, command, deps, env)
|
def register_build(targets, command, deps, env)
|
||||||
Array(targets).each do |target|
|
Array(targets).each do |target|
|
||||||
@cache["targets"][target] = {
|
target_checksum = Rscons.phony_target?(target) ? "" : calculate_checksum(target)
|
||||||
|
@cache["targets"][get_cache_key(target)] = {
|
||||||
"command" => Digest::MD5.hexdigest(command.inspect),
|
"command" => Digest::MD5.hexdigest(command.inspect),
|
||||||
"checksum" => calculate_checksum(target),
|
"checksum" => target_checksum,
|
||||||
"deps" => deps.map do |dep|
|
"deps" => deps.map do |dep|
|
||||||
{
|
{
|
||||||
"fname" => dep,
|
"fname" => dep,
|
||||||
@ -228,6 +240,21 @@ module Rscons
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Return a String key based on the target name to use in the on-disk cache.
|
||||||
|
#
|
||||||
|
# @param target_name [Symbol, String]
|
||||||
|
# Target name.
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
# Key name.
|
||||||
|
def get_cache_key(target_name)
|
||||||
|
if Rscons.phony_target?(target_name)
|
||||||
|
PHONY_PREFIX + target_name.to_s
|
||||||
|
else
|
||||||
|
target_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Create a Cache object and load in the previous contents from the cache
|
# Create a Cache object and load in the previous contents from the cache
|
||||||
# file.
|
# file.
|
||||||
def initialize!
|
def initialize!
|
||||||
|
@ -116,6 +116,8 @@ module Rscons
|
|||||||
expand_varref(varref[*lambda_args], lambda_args)
|
expand_varref(varref[*lambda_args], lambda_args)
|
||||||
elsif varref.nil?
|
elsif varref.nil?
|
||||||
nil
|
nil
|
||||||
|
elsif varref.is_a?(Symbol)
|
||||||
|
varref
|
||||||
else
|
else
|
||||||
raise "Unknown varref type: #{varref.class} (#{varref.inspect})"
|
raise "Unknown varref type: #{varref.class} (#{varref.inspect})"
|
||||||
end
|
end
|
||||||
|
@ -932,4 +932,35 @@ EOF
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "phony targets" do
|
||||||
|
it "allows specifying a Symbol as a target name and reruns the builder if the sources or command have changed" do
|
||||||
|
test_dir("simple")
|
||||||
|
env = Rscons::Environment.new do |env|
|
||||||
|
env.add_builder(:Checker) do |target, sources, cache, env, vars|
|
||||||
|
unless cache.up_to_date?(target, :Checker, sources, env)
|
||||||
|
puts "Checker #{sources.first}" if env.echo != :off
|
||||||
|
cache.register_build(target, :Checker, sources, env)
|
||||||
|
end
|
||||||
|
target
|
||||||
|
end
|
||||||
|
env.Program("simple.exe", "simple.c")
|
||||||
|
env.Checker(:checker, "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq(["CC simple.o", "LD simple.exe", "Checker simple.exe"])
|
||||||
|
|
||||||
|
env.clone do |env|
|
||||||
|
env.Checker(:checker, "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq([])
|
||||||
|
|
||||||
|
File.open("simple.exe", "w") do |fh|
|
||||||
|
fh.puts "Changed simple.exe"
|
||||||
|
end
|
||||||
|
env.clone do |env|
|
||||||
|
env.Checker(:checker, "simple.exe")
|
||||||
|
end
|
||||||
|
expect(lines).to eq(["Checker simple.exe"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user