rake-builder 0.0.16 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Joe Yates
1
+ Copyright (c) 2010-2012 Joe Yates
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -18,3 +18,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.md ADDED
@@ -0,0 +1,178 @@
1
+ rake-builder
2
+ ============
3
+
4
+ *Rake for C, C++, Objective-C and Objective-C++ Projects*
5
+
6
+ * [Source code]
7
+ * [Documentation]
8
+ * [Rubygem]
9
+
10
+ [Source code]: http://github.com/joeyates/rake-builder "Source code at GitHub"
11
+ [Documentation]: http://rdoc.info/projects/joeyates/rake-builder "Documentation at Rubydoc.info"
12
+ [Rubygem]: http://rubygems.org/gems/rake-builder "Ruby gem at rubygems.org"
13
+
14
+ Hello World! Example
15
+ ====================
16
+
17
+ (See the 'examples' directory for source).
18
+
19
+ Rakefile:
20
+ ```ruby
21
+ require 'rubygems' if RUBY_VERSION < '1.9'
22
+ require 'rake'
23
+ require 'rake/builder'
24
+
25
+ Rake::Builder.new do |builder|
26
+ builder.target = 'hello_world_cpp'
27
+ end
28
+ ```
29
+
30
+ main.cpp
31
+ ```cpp
32
+ #include <iostream>
33
+
34
+ int main(int argc, char *argv[]) {
35
+ std::cout << "Hello World!\n";
36
+
37
+ return 0;
38
+ }
39
+ ```
40
+
41
+ The Hello World! project should build and run:
42
+
43
+ ```shell
44
+ $ rake run
45
+ Hello World!
46
+ ```
47
+
48
+ Installation
49
+ ============
50
+
51
+ Dependencies
52
+ ------------
53
+
54
+ * makedepend
55
+ * linux: package 'xutils-dev'
56
+ * OS X: already installed
57
+
58
+ Gem
59
+ ---
60
+
61
+ ```shell
62
+ $ (sudo) gem install rake-builder
63
+ ```
64
+
65
+ Usage
66
+ =====
67
+
68
+ Examples
69
+ --------
70
+ See the 'examples' directory.
71
+
72
+ If you've installed the gem system-wide, type the following to go to
73
+ the correct directory:
74
+
75
+ ```shell
76
+ $ cd `gem environment gemdir`/gems/rake-builder-nnn
77
+ $ cd examples
78
+ ```
79
+
80
+ Project Configuration
81
+ ---------------------
82
+
83
+ In order to build on a specific computer, you will need
84
+ to indicate information like non-standard
85
+ include paths.
86
+
87
+ Rake::Builder collects all such information in one file:
88
+ '.rake-builder'
89
+
90
+ This file should be created in the same directory as the Rakefile.
91
+
92
+ The file should be a YAML structure, and must include a version.
93
+
94
+ Currently, the following can be configured:
95
+ * extra include paths: :include_paths
96
+ * extra compilation options (e.g. defines): :compilation_options
97
+
98
+ ### Example '.rake-builder'
99
+
100
+ ```yaml
101
+ ---
102
+ :rake_builder:
103
+ :config_file:
104
+ :version: "1.0"
105
+ :include_paths:
106
+ - /opt/local/include
107
+ - /usr/include/c++/4.2.1
108
+ ```
109
+
110
+ Default Tasks
111
+ -------------
112
+
113
+ * compile
114
+ * build
115
+ * run - executables only
116
+ * install
117
+ * clean
118
+
119
+ Installing Headers
120
+ ------------------
121
+
122
+ If you install a static library, your headers will also be installed.
123
+ Ensure that you use file globs, e.g. './include/**/*.h',
124
+ as these will ensure that your headers are installed in the correct subdirectories.
125
+
126
+ Project
127
+ =======
128
+
129
+ Status
130
+ ------
131
+
132
+ * Builds C, C++ and Objective-C projects using [GCC](http://gcc.gnu.org/).
133
+
134
+ Dependency Resolution
135
+ ---------------------
136
+
137
+ Task dependencies must ensure that out of date files are recreated as needed.
138
+
139
+ ![rake-builder Dependency Resolution](http://github.com/downloads/joeyates/rake-builder/RakeBuilderDependencyStructure.png "rake-builder Dependency Resolution")
140
+
141
+ Limitations
142
+ -----------
143
+
144
+ ### File Modification Times
145
+
146
+ Rake's FileTask decides whether a file needs rebuilding by comparing on disk file
147
+ modification times (see the private method *out_of_date?*, which returns true if the
148
+ dependency was modified *after* the dependent).
149
+ Unfortunately, most modern file systems hold modification times in whole
150
+ seconds. If a dependency and a dependent were modificed during the same second,
151
+ **even if the dependency were modified later**, *out_of_date?* returns *false*
152
+ which is not the correct answer.
153
+
154
+ This problem is mostly felt in testing, where file modification times are temporarily
155
+ modified to test dependencies. Also, tests wait for second to complete after building.
156
+
157
+ #### File Modification Time Resolutions
158
+
159
+ * [Ext3](http://en.wikipedia.org/wiki/Ext3) - resolution: 1s
160
+ * [Ext4](http://en.wikipedia.org/wiki/Ext4) - resolution: 1 microsecond
161
+ * [Hierarchical_File_System](http://en.wikipedia.org/wiki/Hierarchical_File_System) - resolution: 1s
162
+ * [HFS_Plus](http://en.wikipedia.org/wiki/HFS_Plus) - resolution: 1s
163
+
164
+ ### Source Files with the Same Name
165
+
166
+ Currently, object files from all source files are placed in the same directory.
167
+ So, if there are two source files with the same name, they will overwrite each other.
168
+
169
+ Alternatives
170
+ ------------
171
+
172
+ * GNU build system, a.k.a. Autotools: autoconf, configure, make, etc.
173
+ * [Boost.Build](http://www.boost.org/boost-build2/)
174
+ * [CMake](http://www.cmake.org/)
175
+ * [SCons](http://www.scons.org/)
176
+ * [waf](http://code.google.com/p/waf/)
177
+ * [fbuild](https://github.com/felix-lang/fbuild)
178
+
@@ -0,0 +1,16 @@
1
+ require 'rubygems' if RUBY_VERSION < '1.9'
2
+ require 'rake'
3
+ require 'rake/builder'
4
+
5
+ Rake::Builder.new do |builder|
6
+ builder.target = 'foo/target_1'
7
+ builder.objects_path = 'foo/objects'
8
+ builder.programming_language = 'c'
9
+ end
10
+
11
+ Rake::Builder.new do |builder|
12
+ builder.target = 'bar/target_2'
13
+ builder.objects_path = 'bar/objects'
14
+ builder.programming_language = 'c'
15
+ end
16
+
@@ -0,0 +1,7 @@
1
+ #include <stdio.h>
2
+
3
+ int main(int argc, char *argv[]) {
4
+ printf( "Hello World!\n" );
5
+
6
+ return 0;
7
+ }
@@ -6,7 +6,7 @@ module Rake
6
6
  module VERSION #:nodoc:
7
7
  MAJOR = 0
8
8
  MINOR = 0
9
- TINY = 16
9
+ TINY = 17
10
10
 
11
11
  STRING = [ MAJOR, MINOR, TINY ].join('.')
12
12
  end
data/lib/rake/builder.rb CHANGED
@@ -64,17 +64,23 @@ module Rake
64
64
  'c' => {
65
65
  :source_file_extension => 'c',
66
66
  :compiler => 'gcc',
67
- :linker => 'gcc'
67
+ :linker => 'gcc',
68
+ :ar => 'ar',
69
+ :ranlib => 'ranlib'
68
70
  },
69
71
  'c++' => {
70
72
  :source_file_extension => 'cpp',
71
73
  :compiler => 'g++',
72
- :linker => 'g++'
74
+ :linker => 'g++',
75
+ :ar => 'ar',
76
+ :ranlib => 'ranlib'
73
77
  },
74
78
  'objective-c' => {
75
79
  :source_file_extension => 'm',
76
80
  :compiler => 'gcc',
77
- :linker => 'gcc'
81
+ :linker => 'gcc',
82
+ :ar => 'ar',
83
+ :ranlib => 'ranlib'
78
84
  },
79
85
  }
80
86
 
@@ -84,6 +90,12 @@ module Rake
84
90
  # The linker that will be used
85
91
  attr_accessor :linker
86
92
 
93
+ # Toolchain setting - ar
94
+ attr_accessor :ar
95
+
96
+ # Toolchain setting - ranlib
97
+ attr_accessor :ranlib
98
+
87
99
  # Extension of source files (default 'cpp' for C++ and 'c' for C)
88
100
  attr_accessor :source_file_extension
89
101
 
@@ -173,29 +185,20 @@ module Rake
173
185
  task :autoconf, [:project_title, :version] => [] do | task, args |
174
186
  project_title = args.project_title or raise "Please supply a project_title parameter"
175
187
  version = decide_version( args.version )
176
- if File.exist?( 'configure.ac' )
188
+ if File.exist?('configure.ac')
177
189
  raise "The file 'configure.ac' already exists"
178
190
  end
179
- if File.exist?( 'Makefile.am' )
191
+ if File.exist?('Makefile.am')
180
192
  raise "The file 'Makefile.am' already exists"
181
193
  end
182
194
  create_configure_ac project_title, version
183
195
  create_makefile_am
184
196
  end
185
-
186
- desc "A file containing the major.minor.revision version information"
187
- file 'VERSION' do
188
- raise <<-EOT
189
- In order to create autoconf files, you need to create a file called VERSION in the root directory of the project.
190
- The file should contain the version of the project, like this:
191
- 1.2.3
192
- EOT
193
- end
194
197
  end
195
198
 
196
199
  def self.create_configure_ac( project_title, version )
197
200
  source = Rake::Path.relative_path( instances[ 0 ].source_files[ 0 ], instances[ 0 ].rakefile_path )
198
- File.open( 'configure.ac', 'w' ) do | f |
201
+ File.open('configure.ac', 'w') do | f |
199
202
  f.write <<EOT
200
203
  AC_PREREQ(2.61)
201
204
  AC_INIT(#{project_title}, #{ version })
@@ -262,8 +265,10 @@ EOT
262
265
  f.write "bin_PROGRAMS = #{ names }\n\n"
263
266
  binaries.each do | bin |
264
267
  f.write <<EOT
265
- #{ bin[ :label ] }_SOURCES = #{ bin[ :sources ] }
268
+ #{ bin[ :label ] }_SOURCES = #{ bin[ :sources ] }
266
269
  #{ bin[ :label ] }_CPPFLAGS = #{ bin[ :compiler_flags ] }
270
+ #{ bin[ :label ] }_LDFLAGS = -L.
271
+ #{ bin[ :label ] }_LDADD = #{ bin[ :libraries ] }
267
272
 
268
273
  EOT
269
274
  end
@@ -282,7 +287,8 @@ EOT
282
287
  :name => primary_name,
283
288
  :label => sources_label,
284
289
  :sources => sources,
285
- :compiler_flags => compiler_flags
290
+ :compiler_flags => compiler_flags,
291
+ :libraries => library_dependencies_list,
286
292
  }
287
293
  end
288
294
 
@@ -292,11 +298,11 @@ EOT
292
298
  def self.decide_version( parameter_version )
293
299
  acceptable_version_string = %r(^(\d+)\.(\d+)\.(\d+)$)
294
300
  if parameter_version && parameter_version !~ acceptable_version_string
295
- raise "The supplied version number '#{ parameter_version }' is badly formatted. It should consist of three numbers separated by ."
301
+ raise "The supplied version number '#{parameter_version}' is badly formatted. It should consist of three numbers separated by ."
296
302
  end
297
303
  file_version = load_file_version
298
304
  if file_version && file_version !~ acceptable_version_string
299
- raise "Your VERSION file contains a version number '#{ parameter_version }' which is badly formatted. It should consist of three numbers separated by ."
305
+ raise "Your VERSION file contains a version number '#{file_version}' which is badly formatted. It should consist of three numbers separated by ."
300
306
  end
301
307
  case
302
308
  when parameter_version.nil? && file_version.nil?
@@ -321,16 +327,13 @@ EOT
321
327
  end
322
328
 
323
329
  def self.load_file_version
324
- if File.exist?( 'VERSION' )
325
- version = File.read( 'VERSION' )
326
- version.strip!
327
- else
328
- nil
329
- end
330
+ return nil unless File.exist?('VERSION')
331
+ version = File.read('VERSION')
332
+ version.strip
330
333
  end
331
334
 
332
335
  def self.save_file_version( version )
333
- File.open( 'VERSION', 'w' ) { | f | f.write "#{ version }/n" }
336
+ File.open('VERSION', 'w') { |f| f.write "#{version}\n" }
334
337
  end
335
338
 
336
339
  self.define_global
@@ -348,7 +351,7 @@ EOT
348
351
  # Source files found in source_search_paths
349
352
  def source_files
350
353
  return @source_files if @source_files
351
- @source_files = find_files( @source_search_paths, @source_file_extension ).uniq
354
+ @source_files = find_files( @source_search_paths, @source_file_extension ).uniq.sort
352
355
  end
353
356
 
354
357
  # Header files found in header_search_paths
@@ -387,6 +390,8 @@ EOT
387
390
  raise BuilderError.new( "Don't know how to build '#{ @programming_language }' programs", task_namespace ) if KNOWN_LANGUAGES[ @programming_language ].nil?
388
391
  @compiler ||= KNOWN_LANGUAGES[ @programming_language ][ :compiler ]
389
392
  @linker ||= KNOWN_LANGUAGES[ @programming_language ][ :linker ]
393
+ @ar ||= KNOWN_LANGUAGES[ @programming_language ][ :ar ]
394
+ @ranlib ||= KNOWN_LANGUAGES[ @programming_language ][ :ranlib ]
390
395
  @source_file_extension ||= KNOWN_LANGUAGES[ @programming_language ][ :source_file_extension ]
391
396
 
392
397
  @source_search_paths = Rake::Path.expand_all_with_root( @source_search_paths, @rakefile_path )
@@ -458,9 +463,10 @@ EOT
458
463
  *@target_prerequisites ] do | t |
459
464
  shell "rm -f #{ t.name }"
460
465
  build_commands.each do | command |
461
- shell command
466
+ stdout, stderr = shell(command)
467
+ raise BuildFailure.new("Error: command '#{command}' failed: #{stderr} #{stdout}") if not $?.success?
462
468
  end
463
- raise BuildFailure.new( "The build command failed" ) if ! File.exist?( t.name )
469
+ raise BuildFailure.new("'#{@target}' not created") if not File.exist?(@target)
464
470
  end
465
471
 
466
472
  desc "Compile all sources"
@@ -485,10 +491,12 @@ EOT
485
491
  config.save
486
492
  end
487
493
 
488
- microsecond_file @makedepend_file => [ scoped_task( :load_local_config ),
489
- scoped_task( :missing_headers ),
490
- @objects_path,
491
- *project_files ] do
494
+ microsecond_file @makedepend_file => [
495
+ scoped_task( :load_local_config ),
496
+ scoped_task( :missing_headers ),
497
+ @objects_path,
498
+ *project_files
499
+ ] do
492
500
  system('which makedepend >/dev/null')
493
501
  raise 'makedepend not found' unless $?.success?
494
502
  @logger.add( Logger::DEBUG, "Analysing dependencies" )
@@ -520,13 +528,13 @@ EOT
520
528
  File.open( @makedepend_file ).each_line do |line|
521
529
  next if line !~ /:\s/
522
530
  mapped_object_file = $`
523
- header_file = $'.gsub( "\n", '' )
531
+ header_files = $'.chomp
524
532
  # TODO: Why does it work,
525
533
  # if I make the object (not the source) depend on the header?
526
534
  source_file = object_to_source[ mapped_object_file ]
527
535
  object_file = object_path( source_file )
528
536
  object_file_task = Rake.application[ object_file ]
529
- object_file_task.enhance( [ header_file ] )
537
+ object_file_task.enhance(header_files.split(' '))
530
538
  end
531
539
  end
532
540
 
@@ -661,8 +669,8 @@ EOT
661
669
  when :executable
662
670
  [ "#{ @linker } -o #{ @target } #{ file_list( object_files ) } #{ link_flags }" ]
663
671
  when :static_library
664
- [ "ar -cq #{ @target } #{ file_list( object_files ) }",
665
- "ranlib #{ @target }" ]
672
+ [ "#{ @ar } -cq #{ @target } #{ file_list( object_files ) }",
673
+ "#{ @ranlib } #{ @target }" ]
666
674
  when :shared_library
667
675
  [ "#{ @linker } -shared -o #{ @target } #{ file_list( object_files ) } #{ link_flags }" ]
668
676
  end
@@ -696,8 +704,10 @@ EOT
696
704
  end
697
705
 
698
706
  def compiler_flags
699
- flags = include_path + ' ' + compilation_options.join( ' ' )
700
- flags << ' ' << architecture_option if RUBY_PLATFORM =~ /darwin/i
707
+ flags = include_path
708
+ options = compilation_options.join( ' ' )
709
+ flags << ' ' + options if options != ''
710
+ flags << ' ' + architecture_option if RUBY_PLATFORM =~ /darwin/i
701
711
  flags
702
712
  end
703
713
 
@@ -841,9 +851,14 @@ EOT
841
851
  end
842
852
  end
843
853
 
844
- def shell( command, log_level = Logger::DEBUG )
854
+ def shell(command, log_level = Logger::DEBUG)
845
855
  @logger.add(log_level, command)
846
- system command, {:out => '/dev/null', :err => '/dev/null'}
856
+ originals = $stdout, $stderr
857
+ stdout, stderr = StringIO.new, StringIO.new
858
+ $stdout, $stderr = stdout, stderr
859
+ system command, {:out => :out, :err => :err}
860
+ $stdout, $stderr = *originals
861
+ [stdout.read, stderr.read]
847
862
  end
848
863
 
849
864
  end
@@ -35,21 +35,25 @@ module Rake
35
35
  include FileUtils
36
36
 
37
37
  attr_accessor :timestamp
38
+ attr_accessor :path
38
39
 
39
40
  def self.define_task( *args, &block )
40
- task = super( *args, &block )
41
+ task = super(*args, &block)
42
+ task.path = args[0]
41
43
  task.timestamp = nil
42
44
  task
43
45
  end
44
46
 
45
47
  def needed?
46
- exists = File.directory?( self.name )
47
- @timestamp = File.stat( self.name ).mtime if exists
48
+ exists = File.directory?(self.path)
49
+ if exists && @timestamp.nil?
50
+ @timestamp = File.stat(self.path).mtime
51
+ end
48
52
  ! exists
49
53
  end
50
54
 
51
55
  def execute(*args)
52
- mkdir_p self.name, :verbose => false
56
+ mkdir_p self.path, :verbose => false
53
57
  @timestamp = Time.now
54
58
  super(*args)
55
59
  end
@@ -0,0 +1,191 @@
1
+ load File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe 'autoconf' do
4
+
5
+ include RakeBuilderHelper
6
+
7
+ before :each do
8
+ Rake::Task.clear
9
+ Rake::Builder.define_global
10
+
11
+ @project = cpp_task(:executable)
12
+
13
+ @args = Rake::TaskArguments.new(
14
+ [:project_title, :version],
15
+ ['my_title', '1.0.0'],
16
+ )
17
+ File.stub!(:exist?).and_return(false)
18
+ @files = {
19
+ 'VERSION' => stub('File', :write => nil),
20
+ 'configure.ac' => stub('File', :write => nil),
21
+ 'Makefile.am' => stub('File', :write => nil),
22
+ }
23
+ # Capture text saved to files
24
+ @output = {}
25
+ File.stub!(:open) do |(filename, perms), &block|
26
+ file = @files[filename]
27
+ file.stub!(:write) do |s|
28
+ @output[filename] = s
29
+ end
30
+ block.call file
31
+ end
32
+ end
33
+
34
+ context 'invocation' do
35
+
36
+ it "has an 'autoconf' task" do
37
+ task_names.include?('autoconf').
38
+ should be_true
39
+ end
40
+
41
+ it 'requires a project_title parameter' do
42
+ @args = Rake::TaskArguments.new([], [])
43
+
44
+ expect do
45
+ Rake::Task['autoconf'].execute(@args)
46
+ end. to raise_error(RuntimeError, /supply a project_title/)
47
+ end
48
+
49
+ context 'version parameter' do
50
+
51
+ it 'should be nn.nn.nn' do
52
+ @args = Rake::TaskArguments.new(
53
+ [:project_title, :version],
54
+ ['my_title', 'foo'],
55
+ )
56
+
57
+ expect do
58
+ Rake::Task['autoconf'].execute(@args)
59
+ end. to raise_error(RuntimeError, /The supplied version number 'foo' is badly formatted/)
60
+ end
61
+
62
+ context 'when missing' do
63
+
64
+ before :each do
65
+ @args = Rake::TaskArguments.new(
66
+ [:project_title],
67
+ ['my_title', ],
68
+ )
69
+ File.stub(:read).with('VERSION').and_return('2.3.444')
70
+ end
71
+
72
+ it 'checks for a VERSION file' do
73
+ File.should_receive(:exist?).with('VERSION').and_return(true)
74
+
75
+ Rake::Task['autoconf'].execute(@args)
76
+ end
77
+
78
+ it 'fails without a VERSION file' do
79
+ expect do
80
+ Rake::Task['autoconf'].execute(@args)
81
+ end. to raise_error(RuntimeError, /This task requires a project version/)
82
+ end
83
+
84
+ context 'with a VERSION file' do
85
+
86
+ before :each do
87
+ File.stub(:exist?).with('VERSION').and_return(true)
88
+ end
89
+
90
+ it 'reads the file' do
91
+ File.should_receive(:read).with('VERSION').and_return('2.3.444')
92
+
93
+ Rake::Task['autoconf'].execute(@args)
94
+ end
95
+
96
+ it 'uses the version' do
97
+ Rake::Task['autoconf'].execute(@args)
98
+
99
+ @output['configure.ac']. should =~ /AC_INIT\(.*?, 2\.3\.444\)/
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
110
+ it "fails if 'configure.ac' exists" do
111
+ File.should_receive(:exist?).with('configure.ac').and_return(true)
112
+
113
+ expect do
114
+ Rake::Task['autoconf'].execute(@args)
115
+ end. to raise_error(RuntimeError, /'configure.ac' already exists/)
116
+ end
117
+
118
+ it "fails if 'Makefile.am' exists" do
119
+ File.should_receive(:exist?).with('Makefile.am').and_return(true)
120
+
121
+ expect do
122
+ Rake::Task['autoconf'].execute(@args)
123
+ end. to raise_error(RuntimeError, /'Makefile.am' already exists/)
124
+ end
125
+
126
+ context 'configure.ac' do
127
+
128
+ it 'is created' do
129
+ File. should_receive(:open).
130
+ with('configure.ac', 'w')
131
+
132
+ Rake::Task['autoconf'].execute(@args)
133
+ end
134
+
135
+ it 'has the title' do
136
+ Rake::Task['autoconf'].execute(@args)
137
+
138
+ @output['configure.ac']. should =~ /AC_INIT\(my_title, /
139
+ end
140
+
141
+ it 'has the version' do
142
+ Rake::Task['autoconf'].execute(@args)
143
+
144
+ @output['configure.ac']. should =~ /AC_INIT\(.*?, 1\.0\.0\)/
145
+ end
146
+
147
+ it 'checks for a source file' do
148
+ Rake::Task['autoconf'].execute(@args)
149
+
150
+ @output['configure.ac']. should =~ /AC_CONFIG_SRCDIR\(\[cpp_project\/main\.cpp\]\)/
151
+ end
152
+
153
+ it 'references the Makefile' do
154
+ Rake::Task['autoconf'].execute(@args)
155
+
156
+ @output['configure.ac']. should =~ /AC_CONFIG_FILES\(\[Makefile\]\)/
157
+ end
158
+
159
+ end
160
+
161
+ context 'Makefile.am' do
162
+
163
+ it 'is created' do
164
+ File. should_receive(:open).
165
+ with('Makefile.am', 'w')
166
+
167
+ Rake::Task['autoconf'].execute(@args)
168
+ end
169
+
170
+ it 'has sources' do
171
+ Rake::Task['autoconf'].execute(@args)
172
+
173
+ @output['Makefile.am']. should =~ /the_executable_SOURCES\s*=\s+cpp_project\/main\.cpp/
174
+ end
175
+
176
+ it 'has flags' do
177
+ Rake::Task['autoconf'].execute(@args)
178
+
179
+ @output['Makefile.am']. should =~ /the_executable_CPPFLAGS\s*=/
180
+ end
181
+
182
+ it 'has libraries' do
183
+ Rake::Task['autoconf'].execute(@args)
184
+
185
+ @output['Makefile.am']. should =~ /the_executable_LDADD\s*=/
186
+ end
187
+
188
+ end
189
+
190
+ end
191
+
@@ -1,5 +1,30 @@
1
1
  load File.dirname(__FILE__) + '/spec_helper.rb'
2
2
 
3
+ describe '#source_files' do
4
+
5
+ include RakeBuilderHelper
6
+
7
+ before( :each ) do
8
+ Rake::Path.stub!(:find_files).with(anything, 'h').and_return(['a.h'])
9
+ Rake::Path.stub!(:find_files).with(anything, 'cpp').and_return(['a.cpp'])
10
+
11
+ Rake::Task.clear
12
+ end
13
+
14
+ it 'should find files with the .cpp extension' do
15
+ Rake::Path.should_receive(:find_files).with(anything, 'cpp').and_return(['a.cpp'])
16
+
17
+ cpp_task(:executable)
18
+ end
19
+
20
+ it 'should allow configuration of source extension' do
21
+ Rake::Path.should_receive(:find_files).with(anything, 'cc').and_return(['a.cc'])
22
+
23
+ cpp_task(:executable) { |p| p.source_file_extension = 'cc' }
24
+ end
25
+
26
+ end
27
+
3
28
  describe 'when building an executable' do
4
29
 
5
30
  include RakeBuilderHelper
@@ -48,7 +73,7 @@ describe 'when building an executable' do
48
73
  end
49
74
 
50
75
  it 'has a \'run\' task' do
51
- Rake::Task[ 'run' ].should_not be_nil
76
+ task_names.include?('run'). should be_true
52
77
  end
53
78
 
54
79
  it 'builds the program with \'run\'' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rake-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.17
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-15 00:00:00.000000000 Z
12
+ date: 2013-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -60,23 +60,7 @@ dependencies:
60
60
  - !ruby/object:Gem::Version
61
61
  version: 2.3.0
62
62
  - !ruby/object:Gem::Dependency
63
- name: pry
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- - !ruby/object:Gem::Dependency
79
- name: pry-doc
63
+ name: pry-plus
80
64
  requirement: !ruby/object:Gem::Requirement
81
65
  none: false
82
66
  requirements:
@@ -101,53 +85,56 @@ files:
101
85
  - CHANGES
102
86
  - COPYING
103
87
  - Rakefile
104
- - README.rdoc
88
+ - README.md
105
89
  - lib/compiler.rb
106
- - lib/rake/path.rb
107
90
  - lib/rake/once_task.rb
91
+ - lib/rake/microsecond.rb
92
+ - lib/rake/file_task_alias.rb
108
93
  - lib/rake/builder/qt_builder.rb
109
94
  - lib/rake/builder/version.rb
110
95
  - lib/rake/local_config.rb
111
- - lib/rake/file_task_alias.rb
96
+ - lib/rake/path.rb
112
97
  - lib/rake/builder.rb
113
- - lib/rake/microsecond.rb
114
- - examples/04_zlib/include/main.h
115
- - examples/05_tests/include/units.h
116
98
  - examples/05_tests/include/main.h
99
+ - examples/05_tests/include/units.h
117
100
  - examples/03_search_paths/include/main.h
118
- - examples/02_hello_world_c/main.c
101
+ - examples/04_zlib/include/main.h
102
+ - examples/07_multiple_targets/main.c
119
103
  - examples/04_zlib/src/main.c
120
- - examples/05_tests/src/main.cpp
121
- - examples/05_tests/src/units.cpp
104
+ - examples/02_hello_world_c/main.c
105
+ - examples/01_hello_world_cpp/main.cpp
122
106
  - examples/05_tests/test/test_unit.cpp
107
+ - examples/05_tests/src/units.cpp
108
+ - examples/05_tests/src/main.cpp
123
109
  - examples/03_search_paths/src/main.cpp
124
- - examples/01_hello_world_cpp/main.cpp
125
110
  - examples/06_hello_world_objective_c/main.m
126
111
  - examples/README.rdoc
127
- - examples/02_hello_world_c/Rakefile
128
- - examples/04_zlib/Rakefile
129
- - examples/05_tests/Rakefile
130
- - examples/03_search_paths/Rakefile
131
112
  - examples/01_hello_world_cpp/Rakefile
113
+ - examples/05_tests/Rakefile
132
114
  - examples/06_hello_world_objective_c/Rakefile
133
- - spec/logger_spec.rb
134
- - spec/objective_c_project/main.m
115
+ - examples/07_multiple_targets/Rakefile
116
+ - examples/03_search_paths/Rakefile
117
+ - examples/04_zlib/Rakefile
118
+ - examples/02_hello_world_c/Rakefile
119
+ - spec/spec_helper.rb
120
+ - spec/cpp_project/main.h
121
+ - spec/cpp_project/main.cpp
122
+ - spec/generated_files_spec.rb
123
+ - spec/c_project/main.c
124
+ - spec/c_project/main.h
125
+ - spec/c_project_spec.rb
135
126
  - spec/objective_c_project/main.h
136
- - spec/paths_spec.rb
137
- - spec/local_config_spec.rb
127
+ - spec/objective_c_project/main.m
128
+ - spec/target_spec.rb
129
+ - spec/microsecond_task_spec.rb
138
130
  - spec/cpp_project_spec.rb
131
+ - spec/logger_spec.rb
139
132
  - spec/dependencies_spec.rb
140
133
  - spec/objective_c_project_spec.rb
141
- - spec/c_project_spec.rb
142
- - spec/generated_files_spec.rb
143
- - spec/target_spec.rb
134
+ - spec/paths_spec.rb
135
+ - spec/local_config_spec.rb
144
136
  - spec/libraries_spec.rb
145
- - spec/microsecond_task_spec.rb
146
- - spec/cpp_project/main.h
147
- - spec/cpp_project/main.cpp
148
- - spec/spec_helper.rb
149
- - spec/c_project/main.c
150
- - spec/c_project/main.h
137
+ - spec/autoconf_spec.rb
151
138
  homepage: http://github.com/joeyates/rake-builder
152
139
  licenses: []
153
140
  post_install_message:
@@ -162,7 +149,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
162
149
  version: '0'
163
150
  segments:
164
151
  - 0
165
- hash: 3351991107247363695
152
+ hash: 4353605042528954080
166
153
  required_rubygems_version: !ruby/object:Gem::Requirement
167
154
  none: false
168
155
  requirements:
@@ -171,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
158
  version: '0'
172
159
  segments:
173
160
  - 0
174
- hash: 3351991107247363695
161
+ hash: 4353605042528954080
175
162
  requirements: []
176
163
  rubyforge_project: nowarning
177
164
  rubygems_version: 1.8.23
@@ -179,22 +166,23 @@ signing_key:
179
166
  specification_version: 3
180
167
  summary: Rake for C/C++ Projects
181
168
  test_files:
182
- - spec/logger_spec.rb
183
- - spec/objective_c_project/main.m
169
+ - spec/spec_helper.rb
170
+ - spec/cpp_project/main.h
171
+ - spec/cpp_project/main.cpp
172
+ - spec/generated_files_spec.rb
173
+ - spec/c_project/main.c
174
+ - spec/c_project/main.h
175
+ - spec/c_project_spec.rb
184
176
  - spec/objective_c_project/main.h
185
- - spec/paths_spec.rb
186
- - spec/local_config_spec.rb
177
+ - spec/objective_c_project/main.m
178
+ - spec/target_spec.rb
179
+ - spec/microsecond_task_spec.rb
187
180
  - spec/cpp_project_spec.rb
181
+ - spec/logger_spec.rb
188
182
  - spec/dependencies_spec.rb
189
183
  - spec/objective_c_project_spec.rb
190
- - spec/c_project_spec.rb
191
- - spec/generated_files_spec.rb
192
- - spec/target_spec.rb
184
+ - spec/paths_spec.rb
185
+ - spec/local_config_spec.rb
193
186
  - spec/libraries_spec.rb
194
- - spec/microsecond_task_spec.rb
195
- - spec/cpp_project/main.h
196
- - spec/cpp_project/main.cpp
197
- - spec/spec_helper.rb
198
- - spec/c_project/main.c
199
- - spec/c_project/main.h
187
+ - spec/autoconf_spec.rb
200
188
  has_rdoc:
data/README.rdoc DELETED
@@ -1,143 +0,0 @@
1
- = rake-builder - Rake for C, C++, Objective-C and Objective-C++ Projects
2
-
3
- rake-builder builds C, C++, Objective-C and Objective-C++
4
- projects.
5
-
6
- Here is a typical example:
7
-
8
- require 'rubygems' if RUBY_VERSION < '1.9'
9
- require 'rake'
10
- require 'rake/builder'
11
-
12
- Rake::Builder.new do |builder|
13
- builder.target = 'my_program'
14
- builder.source_search_paths = [ 'src' ]
15
- builder.header_search_paths = [ 'include' ]
16
- end
17
-
18
- = Dependencies
19
-
20
- * makedepend
21
- ** linux: package 'xutils-dev'
22
- ** OS X: already installed
23
-
24
- = Installation
25
-
26
- $ sudo gem install rake-builder
27
-
28
- = Hello World! Example
29
-
30
- See the 'examples' directory.
31
-
32
- The Hello World! project should build and run:
33
-
34
- $ cd examples/01_hello_world_cpp
35
- $ rake run
36
- Hello World!
37
-
38
- = Usage
39
-
40
- See the 'examples' directory.
41
-
42
- If you've installed the gem system-wide, type the following to go to
43
- the correct directory:
44
-
45
- $ cd `gem environment gemdir`/gems/rake-builder-nnn
46
- $ cd examples
47
-
48
- == Project Configuration
49
-
50
- In order to build on a specific computer, you will need
51
- to indicate information like non-standard
52
- include paths.
53
-
54
- Rake::Builder collects all such information in one file:
55
- '.rake-builder'
56
-
57
- For namespaced tasks, e.g. 'test:build', the file is '.rake-builer.test'
58
-
59
- This file should be created in the same
60
- directory as the Rakefile.
61
-
62
- The file should be a YAML structure, and must include a version.
63
-
64
- Currently, the following can be configured:
65
- * extra include paths: :include_paths
66
- * extra compilation options (e.g. defines): :compilation_options
67
-
68
- === Example '.rake-builder'
69
-
70
- ---
71
- :rake_builder:
72
- :config_file:
73
- :version: "1.0"
74
- :include_paths:
75
- - /opt/local/include
76
- - /usr/include/c++/4.2.1
77
-
78
- = Default Tasks
79
-
80
- * compile
81
- * build
82
- * run - executables only
83
- * install
84
- * clean
85
-
86
- = Installing Headers
87
-
88
- If you install a static library, your headers will also be installed.
89
- Ensure that you use file globs, e.g. './include/**/*.h',
90
- as these will ensure that your headers are installed in the correct subdirectories.
91
-
92
- = Online
93
-
94
- * {Source code}[http://github.com/joeyates/rake-builder]
95
- * Documentation[http://rdoc.info/projects/joeyates/rake-builder]
96
- * Gem[http://rubygems.org/gems/rake-builder]
97
-
98
- = Dependencies
99
-
100
- Task dependencies must ensure that out of date files are recreated as needed.
101
-
102
- http://github.com/downloads/joeyates/rake-builder/RakeBuilderDependencyStructure.png
103
-
104
- = Limitations
105
-
106
- == File Modification Times
107
-
108
- Rake's FileTask decides whether a file needs rebuilding by comparing on disk file
109
- modification times (see the private method <em>out_of_date?</em>, which returns true if the
110
- dependency was modified *after* the dependent).
111
- Unfortunately, most modern file systems hold modification times in whole
112
- seconds. If a dependency and a dependent were modificed during the same second,
113
- <b>even if the dependency were modified later</b>, <em>out_of_date?</em> returns *false*
114
- which is not the correct answer.
115
-
116
- This problem is mostly felt in testing, where file modification times are temporarily
117
- modified to test dependencies. Also, tests wait for second to complete after building.
118
-
119
- === File Modification Time Resolutions
120
-
121
- * Ext3[http://en.wikipedia.org/wiki/Ext3] - resolution: 1s
122
- * Ext4[http://en.wikipedia.org/wiki/Ext4] - resolution: 1 microsecond
123
- * Hierarchical_File_System[http://en.wikipedia.org/wiki/Hierarchical_File_System] - resolution: 1s
124
- * HFS_Plus[http://en.wikipedia.org/wiki/HFS_Plus] - resolution: 1s
125
-
126
- == Source Files with the Same Name
127
-
128
- Currently, object files from all source files are placed in the same directory.
129
- So, if there are two source files with the same name, they will overwrite each other.
130
-
131
- = Status
132
-
133
- * Builds C, C++ and Objective-C projects using GCC[http://gcc.gnu.org/].
134
-
135
- = Alternatives
136
-
137
- * GNU build system, a.k.a. Autotools: autoconf, configure, make, etc.
138
- * Boost.Build
139
- * CMake
140
- * rakepp - another customisation of Rake for C++ projects
141
- * Scons
142
- * waf[http://code.google.com/p/waf/]
143
- * http://felix-lang.org/blog/2010/aug/30/fbuild-0-2/