support passing multiple targets to Cache#up_to_date? and #register_build
This commit is contained in:
parent
f7b7a4fefa
commit
1d47db3144
@ -85,16 +85,17 @@ module Rscons
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check if a target is up to date
|
# Check if target(s) are up to date
|
||||||
# @param target [String] The name of the target file.
|
# @param targets [String, Array] The name(s) of the target file(s).
|
||||||
# @param command [Array] The command used to build the target.
|
# @param command [String, Array] The command used to build the target.
|
||||||
# @param deps [Array] List of the target's dependency files.
|
# @param deps [Array] List of the target's dependency files.
|
||||||
# @param env [Environment] The Rscons::Environment.
|
# @param env [Environment] The Rscons::Environment.
|
||||||
# @param options [Hash] Optional options. Can contain the following keys:
|
# @param options [Hash] Optional options. Can contain the following keys:
|
||||||
# :strict_deps::
|
# :strict_deps::
|
||||||
# Only consider a target up to date if its list of dependencies is
|
# Only consider a target up to date if its list of dependencies is
|
||||||
# exactly equal (including order) to the cached list of dependencies
|
# exactly equal (including order) to the cached list of dependencies
|
||||||
# @return true value if the target is up to date, meaning that:
|
# @return true if the targets are all up to date, meaning that,
|
||||||
|
# for each target:
|
||||||
# - the target exists on disk
|
# - the target exists on disk
|
||||||
# - the cache has information for the target
|
# - the cache has information for the target
|
||||||
# - the target's checksum matches its checksum when it was last built
|
# - the target's checksum matches its checksum when it was last built
|
||||||
@ -104,65 +105,69 @@ module Rscons
|
|||||||
# exactly equal to those cached
|
# exactly equal to those cached
|
||||||
# - each cached dependency file's current checksum matches the checksum
|
# - each cached dependency file's current checksum matches the checksum
|
||||||
# stored in the cache file
|
# stored in the cache file
|
||||||
def up_to_date?(target, command, deps, env, options = {})
|
def up_to_date?(targets, command, deps, env, options = {})
|
||||||
# target file must exist on disk
|
Array(targets).each do |target|
|
||||||
return false unless File.exists?(target)
|
# target file must exist on disk
|
||||||
|
return false unless File.exists?(target)
|
||||||
|
|
||||||
# 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?(target)
|
||||||
|
|
||||||
# target must have the same checksum as when it was built last
|
# target must have the same checksum as when it was built last
|
||||||
return false unless @cache[:targets][target][:checksum] == lookup_checksum(target)
|
return false unless @cache[:targets][target][:checksum] == lookup_checksum(target)
|
||||||
|
|
||||||
# command used to build target must be identical
|
# command used to build target must be identical
|
||||||
return false unless @cache[:targets][target][:command] == command
|
return false unless @cache[:targets][target][:command] == command
|
||||||
|
|
||||||
cached_deps = @cache[:targets][target][:deps] || []
|
cached_deps = @cache[:targets][target][: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
|
||||||
return false unless deps == cached_deps_fnames
|
return false unless deps == cached_deps_fnames
|
||||||
else
|
else
|
||||||
# all dependencies passed in must exist in cache (but cache may have more)
|
# all dependencies passed in must exist in cache (but cache may have more)
|
||||||
return false unless (Set.new(deps) - Set.new(cached_deps_fnames)).empty?
|
return false unless (Set.new(deps) - Set.new(cached_deps_fnames)).empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
# 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][target][: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
|
||||||
|
|
||||||
# all cached dependencies must have their checksums match
|
# all cached dependencies must have their checksums match
|
||||||
(cached_deps + cached_user_deps).each do |dep_cache|
|
(cached_deps + cached_user_deps).each do |dep_cache|
|
||||||
return false unless dep_cache[:checksum] == lookup_checksum(dep_cache[:fname])
|
return false unless dep_cache[:checksum] == lookup_checksum(dep_cache[:fname])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Store cache information about a target built by a builder
|
# Store cache information about target(s) built by a builder
|
||||||
# @param target [String] The name of the target.
|
# @param targets [String, Array] The name of the target(s) built.
|
||||||
# @param command [Array] The command used to build the target.
|
# @param command [String, Array] The command used to build the target.
|
||||||
# @param deps [Array] List of dependencies for the target.
|
# @param deps [Array] List of dependencies for the target.
|
||||||
# @param env [Environment] The Rscons::Environment.
|
# @param env [Environment] The Rscons::Environment.
|
||||||
def register_build(target, command, deps, env)
|
def register_build(targets, command, deps, env)
|
||||||
@cache[:targets][target.encode(__ENCODING__)] = {
|
Array(targets).each do |target|
|
||||||
command: command,
|
@cache[:targets][target.encode(__ENCODING__)] = {
|
||||||
checksum: calculate_checksum(target),
|
command: command,
|
||||||
deps: deps.map do |dep|
|
checksum: calculate_checksum(target),
|
||||||
{
|
deps: deps.map do |dep|
|
||||||
fname: dep.encode(__ENCODING__),
|
{
|
||||||
checksum: lookup_checksum(dep),
|
fname: dep.encode(__ENCODING__),
|
||||||
}
|
checksum: lookup_checksum(dep),
|
||||||
end,
|
}
|
||||||
user_deps: (env.get_user_deps(target) || []).map do |dep|
|
end,
|
||||||
{
|
user_deps: (env.get_user_deps(target) || []).map do |dep|
|
||||||
fname: dep.encode(__ENCODING__),
|
{
|
||||||
checksum: lookup_checksum(dep),
|
fname: dep.encode(__ENCODING__),
|
||||||
}
|
checksum: lookup_checksum(dep),
|
||||||
end,
|
}
|
||||||
}
|
end,
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return a list of targets that have been built
|
# Return a list of targets that have been built
|
||||||
|
@ -218,9 +218,9 @@ describe Rscons do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'allows Ruby classes as custom builders to be used to construct files' do
|
it 'allows Ruby classes as custom builders to be used to construct files' do
|
||||||
test_dir('custom_builder')
|
test_dir('custom_builder')
|
||||||
class MySource < Rscons::Builder
|
class MySource < Rscons::Builder
|
||||||
def run(target, sources, user_deps, cache, env, vars = {})
|
def run(target, sources, cache, env, vars)
|
||||||
File.open(target, 'w') do |fh|
|
File.open(target, 'w') do |fh|
|
||||||
fh.puts <<EOF
|
fh.puts <<EOF
|
||||||
#define THE_VALUE 5678
|
#define THE_VALUE 5678
|
||||||
@ -241,6 +241,39 @@ EOF
|
|||||||
`./program`.should == "The value is 5678\n"
|
`./program`.should == "The value is 5678\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'supports custom builders with multiple targets' do
|
||||||
|
test_dir('custom_builder')
|
||||||
|
class CHGen < Rscons::Builder
|
||||||
|
def run(target, sources, cache, env, vars)
|
||||||
|
c_fname = target
|
||||||
|
h_fname = target.sub(/\.c$/, ".h")
|
||||||
|
unless cache.up_to_date?([c_fname, h_fname], "", sources, env)
|
||||||
|
puts "CHGen #{c_fname}"
|
||||||
|
File.open(c_fname, "w") {|fh| fh.puts "int THE_VALUE = 42;"}
|
||||||
|
File.open(h_fname, "w") {|fh| fh.puts "extern int THE_VALUE;"}
|
||||||
|
cache.register_build([c_fname, h_fname], "", sources, env)
|
||||||
|
end
|
||||||
|
target
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
env = Rscons::Environment.new do |env|
|
||||||
|
env.add_builder(CHGen.new)
|
||||||
|
env.CHGen("inc.c", ["program.c"])
|
||||||
|
env.Program("program", Dir["*.c"] + ["inc.c"])
|
||||||
|
end
|
||||||
|
|
||||||
|
lines.should == ["CHGen inc.c", "CC program.o", "CC inc.o", "LD program"]
|
||||||
|
File.exists?("inc.c").should be_true
|
||||||
|
File.exists?("inc.h").should be_true
|
||||||
|
`./program`.should == "The value is 42\n"
|
||||||
|
|
||||||
|
File.open("inc.c", "w") {|fh| fh.puts "int THE_VALUE = 33;"}
|
||||||
|
env.process
|
||||||
|
lines.should == ["CHGen inc.c"]
|
||||||
|
`./program`.should == "The value is 42\n"
|
||||||
|
end
|
||||||
|
|
||||||
it 'allows cloning Environment objects' do
|
it 'allows cloning Environment objects' do
|
||||||
test_dir('clone_env')
|
test_dir('clone_env')
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user