Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base: b4fe5b3f00
...
compare: b77a10a7ce
Checking mergeability… Don't worry, you can still create the pull request.
  • 13 commits
  • 14 files changed
  • 0 commit comments
  • 1 contributor
View
14 Rakefile
@@ -1,9 +1,9 @@
require 'rubygems' if RUBY_VERSION < '1.9'
require 'rake'
require 'rake/rdoctask'
-require 'spec/rake/spectask'
+require 'rspec/core/rake_task'
$:.unshift( File.dirname( __FILE__ ) + '/lib' )
-require 'rake/builder/version'
+require 'rake/builder'
RDOC_FILES = FileList[ 'COPYING', 'README.rdoc' ] +
FileList[ 'lib/**/*.rb' ] +
@@ -11,13 +11,13 @@ RDOC_FILES = FileList[ 'COPYING', 'README.rdoc' ] +
FileList[ 'examples/**/Rakefile' ]
RDOC_OPTS = [ '--quiet', '--main', 'README.rdoc', '--inline-source' ]
-Spec::Rake::SpecTask.new do |t|
- t.spec_files = FileList[ 'spec/**/*_spec.rb' ]
- t.spec_opts += [ '--color', '--format specdoc' ]
+RSpec::Core::RakeTask.new do |t|
+ t.pattern = 'spec/**/*_spec.rb'
+ t.rspec_opts = [ '--color', '--format documentation' ]
end
-Spec::Rake::SpecTask.new( 'spec:rcov' ) do |t|
- t.spec_files = FileList[ 'spec/**/*_spec.rb' ]
+RSpec::Core::RakeTask.new( 'spec:rcov' ) do |t|
+ t.pattern = 'spec/**/*_spec.rb'
t.rcov = true
t.rcov_opts = [ '--exclude spec' ]
end
View
52 lib/rake/builder.rb
@@ -5,6 +5,8 @@
require 'rake/path'
require 'rake/local_config'
require 'rake/file_task_alias'
+require 'rake/microsecond'
+require 'rake/once_task'
require 'compiler'
module Rake
@@ -20,7 +22,7 @@ class Builder < TaskLib
module VERSION #:nodoc:
MAJOR = 0
MINOR = 0
- TINY = 13
+ TINY = 14
STRING = [ MAJOR, MINOR, TINY ].join('.')
end
@@ -154,6 +156,9 @@ class BuildFailure < BuilderError
# Name of the generated file containing source - header dependencies
attr_reader :makedepend_file
+ # The file containing local settings such as include paths
+ attr_reader :local_config
+
# Temporary files generated during compilation and linking
attr_accessor :generated_files
@@ -319,14 +324,14 @@ def initialize( &block )
# Source files found in source_search_paths
def source_files
- @source_files ||= find_files( @source_search_paths, @source_file_extension ).uniq
- @source_files
+ return @source_files if @source_files
+ @source_files = find_files( @source_search_paths, @source_file_extension ).uniq
end
# Header files found in header_search_paths
def header_files
- @header_files ||= find_files( @header_search_paths, @header_file_extension ).uniq
- @header_files
+ return @header_files if @header_files
+ @header_files = find_files( @header_search_paths, @header_file_extension ).uniq
end
def initialize_attributes
@@ -379,6 +384,7 @@ def configure
@default_task ||= :build
@target_prerequisites << @rakefile
+ @local_config = Rake::Path.expand_with_root( '.rake-builder', @rakefile_path )
@makedepend_file = @objects_path + '/.' + target_basename + '.depend.mf'
@@ -406,7 +412,7 @@ def define_default
end
def define
- task :environment do
+ once_task :environment do
logger.level = Logger::DEBUG if ENV[ 'DEBUG' ]
end
@@ -422,7 +428,7 @@ def define
FileTaskAlias.define_task( :build, @target )
desc "Build '#{ target_basename }'"
- file @target => [ scoped_task( :environment ),
+ microsecond_file @target => [ scoped_task( :environment ),
scoped_task( :compile ),
*@target_prerequisites ] do | t |
shell "rm -f #{ t.name }"
@@ -435,7 +441,7 @@ def define
desc "Compile all sources"
# Only import dependencies when we're compiling
# otherwise makedepend gets run on e.g. 'rake -T'
- task :compile => [ scoped_task( :environment ),
+ once_task :compile => [ scoped_task( :environment ),
@makedepend_file,
scoped_task( :load_makedepend ),
*object_files ]
@@ -444,19 +450,17 @@ def define
define_compile_task( src )
end
- directory @objects_path
+ microsecond_directory @objects_path
- task :local_config do
- if ! File.exist?( local_config )
- @logger.add( Logger::DEBUG, "Creating file '#{ local_config }'" )
- added_includes = @compiler_data.include_paths( missing_headers )
- config = Rake::LocalConfig.new( local_config )
- config.include_paths = added_includes
- config.save
- end
+ file scoped_task( local_config ) do
+ @logger.add( Logger::DEBUG, "Creating file '#{ local_config }'" )
+ added_includes = @compiler_data.include_paths( missing_headers )
+ config = Rake::LocalConfig.new( local_config )
+ config.include_paths = added_includes
+ config.save
end
- file @makedepend_file => [ scoped_task( :load_local_config ),
+ microsecond_file @makedepend_file => [ scoped_task( :load_local_config ),
scoped_task( :missing_headers ),
@objects_path,
*project_files ] do
@@ -465,13 +469,13 @@ def define
shell command
end
- task :load_local_config => scoped_task( :local_config ) do
+ once_task scoped_task( :load_local_config ) => scoped_task( local_config ) do
config = LocalConfig.new( local_config )
config.load
@include_paths += Rake::Path.expand_all_with_root( config.include_paths, @rakefile_path )
end
- task :missing_headers => [ *generated_headers ] do
+ once_task scoped_task( :missing_headers ) => [ *generated_headers ] do
missing_headers
end
@@ -684,11 +688,6 @@ def link_flags
# Paths
- def local_config
- filename = '.rake-builder'
- Rake::Path.expand_with_root( filename, @rakefile_path )
- end
-
def save_rakefile_info( block )
if RUBY_VERSION < '1.9'
# Hack the path from the block String representation
@@ -751,6 +750,7 @@ def object_files
def project_files
source_files + header_files
end
+ public :project_files
def file_list( files, delimiter = ' ' )
files.join( delimiter )
@@ -797,7 +797,7 @@ def project_headers
FileList[ search ].each do | pathname |
full_path = Rake::Path.expand_with_root( pathname, @rakefile_path )
directory = File.dirname( full_path )
- relative = Rake::Path.subtract_prefix( non_glob_search, directory )
+ relative = Rake::Path.relative_path( non_glob_search, directory )
memo << { :source_file => pathname, :relative_path => relative }
end
else
View
15 lib/rake/builder/version.rb
@@ -1,15 +0,0 @@
-module Rake
-
- class Builder
-
- module VERSION #:nodoc:
- MAJOR = 0
- MINOR = 0
- TINY = 14
-
- STRING = [ MAJOR, MINOR, TINY ].join('.')
- end
-
- end
-
-end
View
70 lib/rake/microsecond.rb
@@ -0,0 +1,70 @@
+require 'rubygems' if RUBY_VERSION < '1.9'
+require 'rake/tasklib'
+require 'fileutils'
+
+module Rake
+
+ module Microsecond
+ # Compensate for file systems with 1s resolution
+
+ class FileTask < Task
+
+ attr_accessor :timestamp
+
+ def self.define_task( *args, &block )
+ task = super( *args, &block )
+ task.timestamp = nil
+ task
+ end
+
+ def needed?
+ return true if ! File.exist?( self.name )
+ @timestamp = File.stat( self.name ).mtime if @timestamp.nil?
+ return self.prerequisites.any? { | n | ! application[n].timestamp.nil? && application[n].timestamp > @timestamp }
+ end
+
+ def execute(*args)
+ @timestamp = Time.now
+ super(*args)
+ end
+
+ end
+
+ class DirectoryTask < Task
+
+ include FileUtils
+
+ attr_accessor :timestamp
+
+ def self.define_task( *args, &block )
+ task = super( *args, &block )
+ task.timestamp = nil
+ task
+ end
+
+ def needed?
+ exists = File.directory?( self.name )
+ @timestamp = File.stat( self.name ).mtime if exists
+ ! exists
+ end
+
+ def execute(*args)
+ mkdir_p self.name, :verbose => false
+ @timestamp = Time.now
+ super(*args)
+ end
+
+ end
+
+ end
+
+end
+
+def microsecond_file(*args, &block)
+ Rake::Microsecond::FileTask.define_task(*args, &block)
+end
+
+def microsecond_directory(*args, &block)
+ Rake::Microsecond::DirectoryTask.define_task(*args, &block)
+end
+
View
36 lib/rake/once_task.rb
@@ -0,0 +1,36 @@
+require 'rubygems' if RUBY_VERSION < '1.9'
+require 'rake/tasklib'
+
+module Rake
+
+ # A task whick is no longer needed after its first invocation
+ class OnceTask < Task
+
+ attr_accessor :invoked
+ attr_accessor :timestamp
+
+ def self.define_task( *args, &block )
+ task = super( *args, &block )
+ task.timestamp = nil
+ task.invoked = false
+ task
+ end
+
+ def execute(*args)
+ @timestamp = Time.now
+ @invoked = true
+ super(*args)
+ end
+
+ def needed?
+ ! @invoked
+ end
+
+ end
+
+end
+
+def once_task(*args, &block)
+ Rake::OnceTask.define_task(*args, &block)
+end
+
View
9 lib/rake/path.rb
@@ -32,8 +32,13 @@ def self.expand_all_with_root( paths, root )
paths.map{ |path| expand_with_root( path, root ) }
end
- def self.subtract_prefix( prefix, path )
- path[ prefix.size .. -1 ]
+ def self.relative_path( prefix, path )
+ m = path.match( /^#{prefix}/ )
+ if ! m.nil?
+ m.post_match
+ else
+ path
+ end
end
end
View
4 rake-builder.gemspec
@@ -1,6 +1,6 @@
require 'rake'
$:.unshift( File.dirname( __FILE__ ) + '/lib' )
-require 'rake/builder/version'
+require 'rake/builder'
spec = Gem::Specification.new do |s|
s.name = 'rake-builder'
@@ -25,7 +25,7 @@ spec = Gem::Specification.new do |s|
s.add_runtime_dependency 'rake', '0.8.7'
- s.add_development_dependency 'rspec', '1.3.1'
+ s.add_development_dependency 'rspec', '>= 2.3.0'
s.test_files = FileList[ 'spec/**/*' ]
end
View
2  spec/c_project_spec.rb
@@ -19,10 +19,10 @@
after( :each ) do
Rake::Task[ 'clean' ].invoke
`rm -f #{ @test_output_file }`
+ `rm -f '#{ @project.local_config }'`
end
it "builds the program with 'build'" do
- chdir @project.rakefile_path
Rake::Task[ 'build' ].invoke
exist?( @project.target ).should be_true
end
View
8 spec/cpp_project_spec.rb
@@ -6,10 +6,10 @@
before( :all ) do
@test_output_file = Rake::Path.expand_with_root(
- 'rake-builder-testfile.txt', SPEC_PATH )
+ 'rake-builder-testfile.txt', RakeBuilderHelper::SPEC_PATH )
@expected_target = Rake::Path.expand_with_root(
RakeBuilderHelper::TARGET[ :executable ],
- SPEC_PATH )
+ RakeBuilderHelper::SPEC_PATH )
end
before( :each ) do
@@ -77,8 +77,8 @@
end
it 'creates the correct tasks' do
- expected_tasks = expected_tasks( [ @project.target ], 'my_namespace' )
- missing_tasks = expected_tasks - task_names
+ expected = expected_tasks( scoped_tasks( [ @project.target ], 'my_namespace' ), 'my_namespace' )
+ missing_tasks = expected - task_names
missing_tasks.should == []
end
View
138 spec/dependencies_spec.rb
@@ -1,27 +1,141 @@
load File.dirname(__FILE__) + '/spec_helper.rb'
+require 'fileutils'
describe 'the dependencies system' do
include RakeBuilderHelper
+ include FileUtils
before( :each ) do
Rake::Task.clear
@project = cpp_task( :executable )
Rake::Task[ 'clean' ].execute
+ rm_f @project.local_config, :verbose => false
end
after( :each ) do
Rake::Task[ 'clean' ].execute
end
- it 'says the target is up to date, if nothing changes' do
- Rake::Task[ 'build' ].invoke
- Rake::Task[ @project.target ].needed?.should_not be_true
+ context 'objects_path' do
+
+ it 'should not be needed after being called' do
+ Rake::Task[ @project.objects_path ].invoke
+
+ Rake::Task[ @project.objects_path ].needed?.should be_false
+ end
+
end
- it 'says the build is up to date, if nothing changes' do
- Rake::Task[ 'build' ].invoke
- Rake::Task[ 'build' ].needed?.should be_false
+ context 'missing_headers' do
+
+ it 'should not be needed after being invoked' do
+ Rake::Task[ 'missing_headers' ].needed?.should be_true
+
+ Rake::Task[ 'missing_headers' ].invoke
+
+ Rake::Task[ 'missing_headers' ].needed?.should be_false
+ end
+
+ end
+
+ context 'makedepend_file' do
+
+ it 'should create the makedepend_file' do
+ exist?( @project.makedepend_file ).should be_false
+
+ Rake::Task[ @project.makedepend_file ].invoke
+
+ exist?( @project.makedepend_file ).should be_true
+ end
+
+ it 'should not be older than its prerequisites' do
+ t = Rake::Task[ @project.makedepend_file ]
+
+ t.invoke
+
+ stamp = t.timestamp
+ t.prerequisites.any? { |n| t.application[n].timestamp > stamp }.should be_false
+ end
+
+ it 'should have all prerequisites satisfied' do
+ t = Rake::Task[ @project.makedepend_file ]
+
+ t.invoke
+
+ t.prerequisites.any? { |n| t.application[n].needed? }.should be_false
+ end
+
+ it 'should not say the makedepend_file is needed' do
+ t = Rake::Task[ @project.makedepend_file ]
+
+ t.needed?.should be_true
+
+ t.invoke
+
+ t.needed?.should be_false
+ end
+
+ end
+
+ context 'build' do
+
+ before :each do
+ @task = Rake::Task[ 'build' ]
+ end
+
+ it 'should have all prerequisites satisfied' do
+ @task.invoke
+
+ @task.prerequisites.any? { |n| @task.application[n].needed? }.should be_false
+ end
+
+ it 'should create the makedepend_file' do
+ exist?( @project.makedepend_file ).should be_false
+
+ Rake::Task[ 'build' ].invoke
+
+ exist?( @project.makedepend_file ).should be_true
+ end
+
+ it 'should create the target' do
+ Rake::Task[ 'build' ].invoke
+
+ exist?( @project.target ).should be_true
+ end
+
+ it 'should say the compile task is up to date' do
+ Rake::Task[ 'build' ].invoke
+
+ Rake::Task[ 'compile' ].needed?.should be_false
+ end
+
+ it 'should say the build is up to date' do
+ Rake::Task[ 'build' ].invoke
+
+ Rake::Task[ 'build' ].needed?.should be_false
+ end
+
+ it 'should say the makedepend_file is up to date' do
+ exist?( @project.makedepend_file ).should be_false
+
+ isolating_seconds do
+ Rake::Task[ 'build' ].invoke
+ end
+
+ Rake::Task[ @project.makedepend_file ].needed?.should be_false
+ end
+
+ it 'should say the target is up to date' do
+ Rake::Task[ 'build' ].invoke
+
+ target_mtime = File.stat( @project.target ).mtime
+ @project.target_prerequisites.each do | prerequisite |
+ File.stat( prerequisite ).mtime.should be < target_mtime
+ end
+ Rake::Task[ @project.target ].needed?.should be_false
+ end
+
end
it 'doesn\'t recompile objects, if nothing changes' do
@@ -47,7 +161,7 @@
end
end
- it 'recompiles source files, if header dependencies' do
+ it 'recompiles source files, if header dependencies are more recent' do
header_file_path = Rake::Path.expand_with_root( 'cpp_project/main.h', SPEC_PATH )
object_file_path = Rake::Path.expand_with_root( 'main.o', SPEC_PATH )
isolating_seconds do
@@ -82,11 +196,13 @@
Rake::Task[ @project.target ].prerequisites.include?( @project.rakefile ).should be_true
end
- # In our case this spec file is the spec_helper
- # i.e., the file that calls Rake::Builder.new
it 'should indicate the target is out of date, if the Rakefile is newer' do
Rake::Task[ 'build' ].invoke
+
Rake::Task[ @project.target ].needed?.should be_false
+
+ Rake::Task.clear
+ @project = cpp_task( :executable )
touching_temporarily( @project.target, File.mtime( @project.rakefile ) - 1 ) do
Rake::Task[ @project.target ].needed?.should be_true
end
@@ -94,7 +210,11 @@
it 'should indicate that a build is needed if the Rakefile changes' do
Rake::Task[ 'build' ].invoke
+
Rake::Task[ 'build' ].needed?.should be_false
+
+ Rake::Task.clear
+ @project = cpp_task( :executable )
touching_temporarily( @project.target, File.mtime( @project.rakefile ) - 1 ) do
Rake::Task[ 'build' ].needed?.should be_true
end
View
48 spec/local_config_spec.rb
@@ -10,6 +10,9 @@
@local_config_file = Rake::Path.expand_with_root( '.rake-builder', LOCAL_CONFIG_SPEC_PATH )
@expected_path = "/some/special/path"
@config = {:rake_builder=>{:config_file=>{:version=>"1.0"}}, :include_paths=>[ @expected_path ]}
+ end
+
+ after( :each ) do
`rm -f '#{ @local_config_file }'`
end
@@ -36,6 +39,51 @@
end.should raise_error( Rake::Builder::BuilderError, 'Config file version missing' )
end
+ context 'dependencies' do
+
+ before( :each ) do
+ Rake::Task.clear
+ @project = cpp_task( :executable )
+ Rake::Task[ 'clean' ].execute
+ `rm -f #{ @project.local_config }`
+ end
+
+ context 'when local_config is invoked' do
+
+ it 'should no longer be needed' do
+ exist?( @project.local_config ).should be_false
+ Rake::Task[ @project.local_config ].needed?.should be_true
+
+ Rake::Task[ @project.local_config ].invoke
+
+ exist?( @project.local_config ).should be_true
+ Rake::Task[ @project.local_config ].needed?.should be_false
+ end
+
+ end
+
+ context 'when load_local_config is invoked' do
+
+ it 'should no longer be needed' do
+ Rake::Task[ 'load_local_config' ].needed?.should be_true
+
+ Rake::Task[ 'load_local_config' ].invoke
+
+ Rake::Task[ 'load_local_config' ].needed?.should be_false
+ end
+
+ it 'local_config should no longer be needed' do
+ Rake::Task[ @project.local_config ].needed?.should be_true
+
+ Rake::Task[ 'load_local_config' ].invoke
+
+ Rake::Task[ @project.local_config ].needed?.should be_false
+ end
+
+ end
+
+ end
+
private
def save_config( config = @config, filename = @local_config_file )
View
32 spec/microsecond_task_spec.rb
@@ -0,0 +1,32 @@
+load File.dirname(__FILE__) + '/spec_helper.rb'
+require 'fileutils'
+
+describe Rake::Microsecond::DirectoryTask do
+
+ include RakeBuilderHelper
+ include FileUtils
+
+ before :all do
+ @path = File.join(File.dirname(__FILE__), 'microsecond_directory')
+ end
+
+ before :each do
+ rm_rf @path, :verbose => false
+ end
+
+ it 'should memorize the directory creation time including fractional seconds' do
+ File.directory?( @path ).should be_false
+
+ t = Rake::Microsecond::DirectoryTask.define_task( @path )
+
+ isolating_seconds do
+ sleep 0.01
+ t.invoke
+ end
+
+ File.directory?( @path ).should be_true
+ t.timestamp.usec.should_not == 0
+ end
+
+end
+
View
7 spec/spec_helper.rb
@@ -1,11 +1,10 @@
-require 'spec'
+require 'rspec'
require File.expand_path( File.dirname(__FILE__) + '/../lib/rake/builder' )
-SPEC_PATH = File.expand_path( File.dirname(__FILE__) )
-
module RakeBuilderHelper
- TARGET = {
+ SPEC_PATH ||= File.expand_path( File.dirname(__FILE__) )
+ TARGET ||= {
:executable => 'the_executable',
:static_library => 'libthe_static_library.a',
:shared_library => 'libthe_dynamic_library.so',
View
2  spec/target_spec.rb
@@ -32,7 +32,7 @@
builder = Rake::Builder.new do |builder|
builder.source_search_paths = [ 'cpp_project' ]
end
- builder.target.should == Rake::Path.expand_with_root( 'a.out', SPEC_PATH )
+ builder.target.should == Rake::Path.expand_with_root( 'a.out', RakeBuilderHelper::SPEC_PATH )
end
it 'raises an error when the supplied target_type is unknown' do

No commit comments for this range

Something went wrong with that request. Please try again.