blackwinter-rake-compiler 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/History.txt +308 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.rdoc +415 -0
  6. data/Rakefile +15 -0
  7. data/bin/rake-compiler +24 -0
  8. data/cucumber.yml +4 -0
  9. data/features/compile.feature +79 -0
  10. data/features/cross-compile.feature +23 -0
  11. data/features/cross-package-multi.feature +15 -0
  12. data/features/cross-package.feature +14 -0
  13. data/features/java-compile.feature +22 -0
  14. data/features/java-no-native-compile.feature +33 -0
  15. data/features/java-package.feature +24 -0
  16. data/features/package.feature +40 -0
  17. data/features/step_definitions/compilation.rb +70 -0
  18. data/features/step_definitions/cross_compilation.rb +27 -0
  19. data/features/step_definitions/execution.rb +52 -0
  20. data/features/step_definitions/folders.rb +32 -0
  21. data/features/step_definitions/gem.rb +46 -0
  22. data/features/step_definitions/java_compilation.rb +7 -0
  23. data/features/support/env.rb +10 -0
  24. data/features/support/file_template_helpers.rb +137 -0
  25. data/features/support/generator_helpers.rb +123 -0
  26. data/features/support/platform_extension_helpers.rb +27 -0
  27. data/lib/rake/baseextensiontask.rb +90 -0
  28. data/lib/rake/extensioncompiler.rb +53 -0
  29. data/lib/rake/extensiontask.rb +513 -0
  30. data/lib/rake/javaextensiontask.rb +226 -0
  31. data/spec/lib/rake/extensiontask_spec.rb +501 -0
  32. data/spec/lib/rake/javaextensiontask_spec.rb +182 -0
  33. data/spec/spec.opts +3 -0
  34. data/spec/spec_helper.rb +15 -0
  35. data/spec/support/capture_output_helper.rb +22 -0
  36. data/tasks/bin/cross-ruby.rake +213 -0
  37. data/tasks/bootstrap.rake +11 -0
  38. data/tasks/common.rake +10 -0
  39. data/tasks/cucumber.rake +23 -0
  40. data/tasks/gem.rake +52 -0
  41. data/tasks/news.rake +39 -0
  42. data/tasks/release.rake +26 -0
  43. data/tasks/rspec.rake +9 -0
  44. metadata +138 -0
@@ -0,0 +1,226 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rake/baseextensiontask'
4
+
5
+ # Define a series of tasks to aid in the compilation of Java extensions for
6
+ # gem developer/creators.
7
+
8
+ module Rake
9
+ class JavaExtensionTask < BaseExtensionTask
10
+
11
+ attr_accessor :classpath
12
+ attr_accessor :debug
13
+
14
+ # Provide source compatibility with specified release
15
+ attr_accessor :source_version
16
+
17
+ # Generate class files for specific VM version
18
+ attr_accessor :target_version
19
+
20
+ def platform
21
+ @platform ||= 'java'
22
+ end
23
+
24
+ def java_compiling(&block)
25
+ @java_compiling = block if block_given?
26
+ end
27
+
28
+ def init(name = nil, gem_spec = nil)
29
+ super
30
+ @source_pattern = '**/*.java'
31
+ @classpath = nil
32
+ @java_compiling = nil
33
+ @debug = false
34
+ @source_version = '1.5'
35
+ @target_version = '1.5'
36
+ end
37
+
38
+ def define
39
+ super
40
+
41
+ define_java_platform_tasks
42
+ end
43
+
44
+ private
45
+ def define_compile_tasks(for_platform = nil, ruby_ver = RUBY_VERSION)
46
+ # platform usage
47
+ platf = for_platform || platform
48
+
49
+ # lib_path
50
+ lib_path = lib_dir
51
+
52
+ # tmp_path
53
+ tmp_path = "#{@tmp_dir}/#{platf}/#{@name}"
54
+
55
+ # cleanup and clobbering
56
+ CLEAN.include(tmp_path)
57
+ CLOBBER.include("#{lib_path}/#{binary(platf)}")
58
+ CLOBBER.include("#{@tmp_dir}")
59
+
60
+ # directories we need
61
+ directory tmp_path
62
+ directory lib_dir
63
+
64
+ # copy binary from temporary location to final lib
65
+ # tmp/extension_name/extension_name.{so,bundle} => lib/
66
+ task "copy:#{@name}:#{platf}" => [lib_path, "#{tmp_path}/#{binary(platf)}"] do
67
+ install "#{tmp_path}/#{binary(platf)}", "#{lib_path}/#{binary(platf)}"
68
+ end
69
+
70
+ file "#{tmp_path}/#{binary(platf)}" => "#{tmp_path}/.build" do
71
+
72
+ class_files = FileList["#{tmp_path}/**/*.class"].
73
+ gsub("#{tmp_path}/", '')
74
+
75
+ # avoid environment variable expansion using backslash
76
+ class_files.gsub!('$', '\$') unless windows?
77
+
78
+ args = class_files.map { |path|
79
+ ["-C #{tmp_path}", path]
80
+ }.flatten
81
+
82
+ sh "jar cf #{tmp_path}/#{binary(platf)} #{args.join(' ')}"
83
+ end
84
+
85
+ file "#{tmp_path}/.build" => [tmp_path] + source_files do
86
+ not_jruby_compile_msg = <<-EOF
87
+ WARNING: You're cross-compiling a binary extension for JRuby, but are using
88
+ another interpreter. If your Java classpath or extension dir settings are not
89
+ correctly detected, then either check the appropriate environment variables or
90
+ execute the Rake compilation task using the JRuby interpreter.
91
+ (e.g. `jruby -S rake compile:java`)
92
+ EOF
93
+ warn_once(not_jruby_compile_msg) unless defined?(JRUBY_VERSION)
94
+
95
+ classpath_arg = java_classpath_arg(@classpath)
96
+ debug_arg = @debug ? '-g' : ''
97
+
98
+ sh "javac #{java_extdirs_arg} -target #{@target_version} -source #{@source_version} -Xlint:unchecked #{debug_arg} #{classpath_arg} -d #{tmp_path} #{source_files.join(' ')}"
99
+
100
+ # Checkpoint file
101
+ touch "#{tmp_path}/.build"
102
+ end
103
+
104
+ # compile tasks
105
+ unless Rake::Task.task_defined?('compile') then
106
+ desc "Compile all the extensions"
107
+ task "compile"
108
+ end
109
+
110
+ # compile:name
111
+ unless Rake::Task.task_defined?("compile:#{@name}") then
112
+ desc "Compile #{@name}"
113
+ task "compile:#{@name}"
114
+ end
115
+
116
+ # Allow segmented compilation by platform (open door for 'cross compile')
117
+ task "compile:#{@name}:#{platf}" => ["copy:#{@name}:#{platf}"]
118
+ task "compile:#{platf}" => ["compile:#{@name}:#{platf}"]
119
+
120
+ # Only add this extension to the compile chain if current
121
+ # platform matches the indicated one.
122
+ if platf == RUBY_PLATFORM then
123
+ # ensure file is always copied
124
+ file "#{lib_path}/#{binary(platf)}" => ["copy:#{name}:#{platf}"]
125
+
126
+ task "compile:#{@name}" => ["compile:#{@name}:#{platf}"]
127
+ task "compile" => ["compile:#{platf}"]
128
+ end
129
+ end
130
+
131
+ def define_java_platform_tasks
132
+ # lib_path
133
+ lib_path = lib_dir
134
+
135
+ if @gem_spec && !Rake::Task.task_defined?("java:#{@gem_spec.name}")
136
+ task "java:#{@gem_spec.name}" do |t|
137
+ # FIXME: workaround Gem::Specification limitation around cache_file:
138
+ # http://github.com/rubygems/rubygems/issues/78
139
+ spec = gem_spec.dup
140
+ spec.instance_variable_set(:"@cache_file", nil) if spec.respond_to?(:cache_file)
141
+
142
+ # adjust to specified platform
143
+ spec.platform = Gem::Platform.new('java')
144
+
145
+ # clear the extensions defined in the specs
146
+ spec.extensions.clear
147
+
148
+ # add the binaries that this task depends on
149
+ ext_files = []
150
+
151
+ # go through native prerequisites and grab the real extension files from there
152
+ t.prerequisites.each do |ext|
153
+ ext_files << ext
154
+ end
155
+
156
+ # include the files in the gem specification
157
+ spec.files += ext_files
158
+
159
+ # expose gem specification for customization
160
+ if @java_compiling
161
+ @java_compiling.call(spec)
162
+ end
163
+
164
+ # Generate a package for this gem
165
+ Gem::PackageTask.new(spec) do |pkg|
166
+ pkg.need_zip = false
167
+ pkg.need_tar = false
168
+ end
169
+ end
170
+
171
+ # add binaries to the dependency chain
172
+ task "java:#{@gem_spec.name}" => ["#{lib_path}/#{binary(platform)}"]
173
+
174
+ # ensure the extension get copied
175
+ unless Rake::Task.task_defined?("#{lib_path}/#{binary(platform)}") then
176
+ file "#{lib_path}/#{binary(platform)}" => ["copy:#{name}:#{platform}"]
177
+ end
178
+
179
+ task 'java' => ["java:#{@gem_spec.name}"]
180
+ end
181
+
182
+ task 'java' do
183
+ task 'compile' => 'compile:java'
184
+ end
185
+ end
186
+
187
+ #
188
+ # Discover Java Extension Directories and build an extdirs argument
189
+ #
190
+ def java_extdirs_arg
191
+ extdirs = Java::java.lang.System.getProperty('java.ext.dirs') rescue nil
192
+ extdirs = ENV['JAVA_EXT_DIR'] unless extdirs
193
+ java_extdir = extdirs.nil? ? "" : "-extdirs \"#{extdirs}\""
194
+ end
195
+
196
+ #
197
+ # Discover the Java/JRuby classpath and build a classpath argument
198
+ #
199
+ # @params
200
+ # *args:: Additional classpath arguments to append
201
+ #
202
+ # Copied verbatim from the ActiveRecord-JDBC project. There are a small myriad
203
+ # of ways to discover the Java classpath correctly.
204
+ #
205
+ def java_classpath_arg(*args)
206
+ jruby_cpath = nil
207
+ if RUBY_PLATFORM =~ /java/
208
+ begin
209
+ cpath = Java::java.lang.System.getProperty('java.class.path').split(File::PATH_SEPARATOR)
210
+ cpath += Java::java.lang.System.getProperty('sun.boot.class.path').split(File::PATH_SEPARATOR)
211
+ jruby_cpath = cpath.compact.join(File::PATH_SEPARATOR)
212
+ rescue => e
213
+ end
214
+ end
215
+ unless jruby_cpath
216
+ jruby_cpath = ENV['JRUBY_PARENT_CLASSPATH'] || ENV['JRUBY_HOME'] &&
217
+ Dir.glob("#{File.expand_path(ENV['JRUBY_HOME'])}/lib/*.jar").
218
+ join(File::PATH_SEPARATOR)
219
+ end
220
+ raise "JRUBY_HOME or JRUBY_PARENT_CLASSPATH are not set" unless jruby_cpath
221
+ jruby_cpath += File::PATH_SEPARATOR + args.join(File::PATH_SEPARATOR) unless args.empty?
222
+ jruby_cpath ? "-cp \"#{jruby_cpath}\"" : ""
223
+ end
224
+
225
+ end
226
+ end
@@ -0,0 +1,501 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ require 'rake/extensiontask'
4
+ require 'rbconfig'
5
+
6
+ describe Rake::ExtensionTask do
7
+ context '#new' do
8
+ context '(basic)' do
9
+ it 'should raise an error if no name is provided' do
10
+ lambda {
11
+ Rake::ExtensionTask.new
12
+ }.should raise_error(RuntimeError, /Extension name must be provided/)
13
+ end
14
+
15
+ it 'should allow string as extension name assignation' do
16
+ ext = Rake::ExtensionTask.new('extension_one')
17
+ ext.name.should == 'extension_one'
18
+ end
19
+
20
+ it 'should allow string as extension name using block assignation' do
21
+ ext = Rake::ExtensionTask.new do |ext|
22
+ ext.name = 'extension_two'
23
+ end
24
+ ext.name.should == 'extension_two'
25
+ end
26
+
27
+ it 'should return itself for the block' do
28
+ from_block = nil
29
+ from_lasgn = Rake::ExtensionTask.new('extension_three') do |ext|
30
+ from_block = ext
31
+ end
32
+ from_block.should == from_lasgn
33
+ end
34
+
35
+ it 'should accept a gem specification as parameter' do
36
+ spec = mock_gem_spec
37
+ ext = Rake::ExtensionTask.new('extension_three', spec)
38
+ ext.gem_spec.should == spec
39
+ end
40
+
41
+ it 'should allow gem specification be defined using block assignation' do
42
+ spec = mock_gem_spec
43
+ ext = Rake::ExtensionTask.new('extension_four') do |ext|
44
+ ext.gem_spec = spec
45
+ end
46
+ ext.gem_spec.should == spec
47
+ end
48
+
49
+ it 'should allow forcing of platform' do
50
+ ext = Rake::ExtensionTask.new('weird_extension') do |ext|
51
+ ext.platform = 'universal-foo-bar-10.5'
52
+ end
53
+ ext.platform.should == 'universal-foo-bar-10.5'
54
+ end
55
+ end
56
+ end
57
+
58
+ context '(defaults)' do
59
+ before :each do
60
+ @ext = Rake::ExtensionTask.new('extension_one')
61
+ end
62
+
63
+ it 'should look for extconf script' do
64
+ @ext.config_script.should == 'extconf.rb'
65
+ end
66
+
67
+ it 'should dump intermediate files to tmp/' do
68
+ @ext.tmp_dir.should == 'tmp'
69
+ end
70
+
71
+ it 'should copy build extension into lib/' do
72
+ @ext.lib_dir.should == 'lib'
73
+ end
74
+
75
+ it 'should look for C files pattern (.c)' do
76
+ @ext.source_pattern.should == "*.c"
77
+ end
78
+
79
+ it 'should have no configuration options preset to delegate' do
80
+ @ext.config_options.should be_empty
81
+ end
82
+
83
+ it "should have no includes preset to delegate" do
84
+ @ext.config_includes.should be_empty
85
+ end
86
+
87
+ it 'should default to current platform' do
88
+ @ext.platform.should == RUBY_PLATFORM
89
+ end
90
+
91
+ it 'should default to no cross compilation' do
92
+ @ext.cross_compile.should be_false
93
+ end
94
+
95
+ it 'should have no configuration options for cross compilation' do
96
+ @ext.cross_config_options.should be_empty
97
+ end
98
+
99
+ it "should have cross platform defined to 'i386-mingw32'" do
100
+ @ext.cross_platform.should == 'i386-mingw32'
101
+ end
102
+ end
103
+
104
+ context '(tasks)' do
105
+ before :each do
106
+ Rake.application.clear
107
+ CLEAN.clear
108
+ CLOBBER.clear
109
+ end
110
+
111
+ context '(one extension)' do
112
+ before :each do
113
+ Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], [])
114
+ @ext = Rake::ExtensionTask.new('extension_one')
115
+ @ext_bin = ext_bin('extension_one')
116
+ @platform = RUBY_PLATFORM
117
+ @ruby_ver = RUBY_VERSION
118
+ end
119
+
120
+ context 'compile' do
121
+ it 'should define as task' do
122
+ Rake::Task.task_defined?('compile').should be_true
123
+ end
124
+
125
+ it "should depend on 'compile:{platform}'" do
126
+ Rake::Task['compile'].prerequisites.should include("compile:#{@platform}")
127
+ end
128
+ end
129
+
130
+ context 'compile:extension_one' do
131
+ it 'should define as task' do
132
+ Rake::Task.task_defined?('compile:extension_one').should be_true
133
+ end
134
+
135
+ it "should depend on 'compile:extension_one:{platform}'" do
136
+ Rake::Task['compile:extension_one'].prerequisites.should include("compile:extension_one:#{@platform}")
137
+ end
138
+ end
139
+
140
+ context 'lib/extension_one.{so,bundle}' do
141
+ it 'should define as task' do
142
+ Rake::Task.task_defined?("lib/#{@ext_bin}").should be_true
143
+ end
144
+
145
+ it "should depend on 'copy:extension_one:{platform}:{ruby_ver}'" do
146
+ Rake::Task["lib/#{@ext_bin}"].prerequisites.should include("copy:extension_one:#{@platform}:#{@ruby_ver}")
147
+ end
148
+ end
149
+
150
+ context 'tmp/{platform}/extension_one/{ruby_ver}/extension_one.{so,bundle}' do
151
+ it 'should define as task' do
152
+ Rake::Task.task_defined?("tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}").should be_true
153
+ end
154
+
155
+ it "should depend on 'tmp/{platform}/extension_one/{ruby_ver}/Makefile'" do
156
+ Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}"].prerequisites.should include("tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile")
157
+ end
158
+
159
+ it "should depend on 'ext/extension_one/source.c'" do
160
+ Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}"].prerequisites.should include("ext/extension_one/source.c")
161
+ end
162
+
163
+ it "should not depend on 'ext/extension_one/source.h'" do
164
+ Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}"].prerequisites.should_not include("ext/extension_one/source.h")
165
+ end
166
+ end
167
+
168
+ context 'tmp/{platform}/extension_one/{ruby_ver}/Makefile' do
169
+ it 'should define as task' do
170
+ Rake::Task.task_defined?("tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile").should be_true
171
+ end
172
+
173
+ it "should depend on 'tmp/{platform}/extension_one/{ruby_ver}'" do
174
+ Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/#{@platform}/extension_one/#{@ruby_ver}")
175
+ end
176
+
177
+ it "should depend on 'ext/extension_one/extconf.rb'" do
178
+ Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("ext/extension_one/extconf.rb")
179
+ end
180
+ end
181
+
182
+ context 'clean' do
183
+ it "should include 'tmp/{platform}/extension_one/{ruby_ver}' in the pattern" do
184
+ CLEAN.should include("tmp/#{@platform}/extension_one/#{@ruby_ver}")
185
+ end
186
+ end
187
+
188
+ context 'clobber' do
189
+ it "should include 'lib/extension_one.{so,bundle}'" do
190
+ CLOBBER.should include("lib/#{@ext_bin}")
191
+ end
192
+
193
+ it "should include 'tmp'" do
194
+ CLOBBER.should include('tmp')
195
+ end
196
+ end
197
+
198
+ it "should warn when pre-compiled files exist in extension directory" do
199
+ Rake::FileList.stub!(:[]).
200
+ and_return(["ext/extension_one/source.c"],
201
+ ["ext/extension_one/source.o"])
202
+
203
+ _, err = capture_output do
204
+ Rake::ExtensionTask.new('extension_one')
205
+ end
206
+ err.should match(/rake-compiler found compiled files in 'ext\/extension_one' directory. Please remove them./)
207
+ end
208
+ end
209
+
210
+ context '(extension in custom location)' do
211
+ before :each do
212
+ Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], [])
213
+ @ext = Rake::ExtensionTask.new('extension_one') do |ext|
214
+ ext.ext_dir = 'custom/ext/foo'
215
+ end
216
+ @ext_bin = ext_bin('extension_one')
217
+ @platform = RUBY_PLATFORM
218
+ @ruby_ver = RUBY_VERSION
219
+ end
220
+
221
+ context 'tmp/{platform}/extension_one/{ruby_ver}/Makefile' do
222
+ it "should depend on 'custom/ext/foo/extconf.rb'" do
223
+ Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("custom/ext/foo/extconf.rb")
224
+ end
225
+ end
226
+ end
227
+
228
+ context '(native tasks)' do
229
+ before :each do
230
+ Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], [])
231
+ @spec = mock_gem_spec
232
+ @ext_bin = ext_bin('extension_one')
233
+ @platform = RUBY_PLATFORM
234
+ @ruby_ver = RUBY_VERSION
235
+ end
236
+
237
+ context 'native' do
238
+ before :each do
239
+ @spec.stub!(:platform=).and_return('ruby')
240
+ end
241
+
242
+ it 'should define a task for building the supplied gem' do
243
+ Rake::ExtensionTask.new('extension_one', @spec)
244
+ Rake::Task.task_defined?('native:my_gem').should be_true
245
+ end
246
+
247
+ it 'should define as task for pure ruby gems' do
248
+ Rake::Task.task_defined?('native').should be_false
249
+ Rake::ExtensionTask.new('extension_one', @spec)
250
+ Rake::Task.task_defined?('native').should be_true
251
+ end
252
+
253
+ it 'should not define a task for already native gems' do
254
+ @spec.stub!(:platform).and_return('current')
255
+ Rake::ExtensionTask.new('extension_one', @spec)
256
+ Rake::Task.task_defined?('native').should be_false
257
+ end
258
+
259
+ it 'should depend on platform specific native tasks' do
260
+ Rake::ExtensionTask.new('extension_one', @spec)
261
+ Rake::Task["native"].prerequisites.should include("native:#{@platform}")
262
+ end
263
+
264
+ context 'native:my_gem:{platform}' do
265
+ it 'should depend on binary extension' do
266
+ Rake::ExtensionTask.new('extension_one', @spec)
267
+ Rake::Task["native:my_gem:#{@platform}"].prerequisites.should include("tmp/#{@platform}/stage/lib/#{@ext_bin}")
268
+ end
269
+ end
270
+ end
271
+ end
272
+
273
+ context '(cross platform tasks)' do
274
+ before :each do
275
+ File.stub!(:exist?).and_return(true)
276
+ YAML.stub!(:load_file).and_return(mock_config_yml)
277
+ Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], [])
278
+ @spec = mock_gem_spec
279
+ @config_file = File.expand_path("~/.rake-compiler/config.yml")
280
+ @ruby_ver = RUBY_VERSION
281
+ @platform = 'i386-mingw32'
282
+ @config_path = mock_config_yml["rbconfig-#{@platform}-#{@ruby_ver}"]
283
+
284
+ File.stub!(:open).and_yield(mock_fake_rb)
285
+ end
286
+
287
+ context 'if no rake-compiler configuration exists' do
288
+ before :each do
289
+ File.should_receive(:exist?).with(@config_file).and_return(false)
290
+
291
+ _, @err = capture_output do
292
+ Rake::ExtensionTask.new('extension_one') do |ext|
293
+ ext.cross_compile = true
294
+ end
295
+ end
296
+ end
297
+
298
+ it 'should not generate a warning' do
299
+ @err.should eq("")
300
+ end
301
+
302
+ it 'should create a dummy nested cross-compile target that raises an error' do
303
+ Rake::Task.should have_defined("cross")
304
+ Rake::Task["cross"].invoke
305
+ lambda {
306
+ Rake::Task["compile"].invoke
307
+ }.should raise_error(RuntimeError,
308
+ /rake-compiler must be configured first to enable cross-compilation/)
309
+ end
310
+ end
311
+
312
+ it 'should parse the config file using YAML' do
313
+ YAML.should_receive(:load_file).with(@config_file).and_return(mock_config_yml)
314
+ Rake::ExtensionTask.new('extension_one') do |ext|
315
+ ext.cross_compile = true
316
+ end
317
+ end
318
+
319
+ it 'should warn if no section of config file defines running version of ruby' do
320
+ config = mock(Hash)
321
+ config.should_receive(:[]).with("rbconfig-#{@platform}-#{@ruby_ver}").and_return(nil)
322
+ YAML.stub!(:load_file).and_return(config)
323
+ out, err = capture_output do
324
+ Rake::ExtensionTask.new('extension_one') do |ext|
325
+ ext.cross_compile = true
326
+ end
327
+ end
328
+ err.should match(/no configuration section for specified version of Ruby/)
329
+ end
330
+
331
+ it 'should capture an action block to be executed when cross compiling' do
332
+ lambda {
333
+ Rake::ExtensionTask.new('extension_one') do |ext|
334
+ ext.cross_compiling do |gem_spec|
335
+ gem_spec.post_install_message = "Cross compiled gem"
336
+ end
337
+ end
338
+ }.should_not raise_error
339
+ end
340
+
341
+ it 'should allow usage of RUBY_CC_VERSION to indicate a different version of ruby' do
342
+ config = mock(Hash)
343
+ config.should_receive(:[]).with("rbconfig-i386-mingw32-1.9.1").and_return('/path/to/ruby/1.9.1/rbconfig.rb')
344
+ YAML.stub!(:load_file).and_return(config)
345
+
346
+ ENV['RUBY_CC_VERSION'] = '1.9.1'
347
+ Rake::ExtensionTask.new('extension_one') do |ext|
348
+ ext.cross_compile = true
349
+ end
350
+ end
351
+
352
+ it 'should allow multiple versions be supplied to RUBY_CC_VERSION' do
353
+ config = mock(Hash)
354
+ config.should_receive(:[]).once.with("rbconfig-i386-mingw32-1.8.6").and_return('/path/to/ruby/1.8.6/rbconfig.rb')
355
+ config.should_receive(:[]).once.with("rbconfig-i386-mingw32-1.9.1").and_return('/path/to/ruby/1.9.1/rbconfig.rb')
356
+ YAML.stub!(:load_file).and_return(config)
357
+
358
+ ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
359
+ Rake::ExtensionTask.new('extension_one') do |ext|
360
+ ext.cross_compile = true
361
+ end
362
+ end
363
+
364
+ after :each do
365
+ ENV.delete('RUBY_CC_VERSION')
366
+ end
367
+
368
+ context "(cross compile for multiple versions)" do
369
+ before :each do
370
+ config = mock(Hash)
371
+ config.stub!(:[]).and_return('/path/to/ruby/1.8.6/rbconfig.rb', '/path/to/ruby/1.9.1/rbconfig.rb')
372
+ YAML.stub!(:load_file).and_return(config)
373
+
374
+ ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
375
+ @ext = Rake::ExtensionTask.new('extension_one') do |ext|
376
+ ext.cross_compile = true
377
+ ext.cross_platform = 'universal-unknown'
378
+ end
379
+ end
380
+
381
+ it 'should create specific copy of binaries for each version' do
382
+ Rake::Task.should have_defined("copy:extension_one:universal-unknown:1.8.6")
383
+ Rake::Task.should have_defined("copy:extension_one:universal-unknown:1.9.1")
384
+ end
385
+ end
386
+
387
+ context "(cross for 'universal-unknown' platform)" do
388
+ before :each do
389
+ @ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext|
390
+ ext.cross_compile = true
391
+ ext.cross_platform = 'universal-unknown'
392
+ end
393
+ end
394
+
395
+ context 'fake' do
396
+ it 'should chain fake task to Makefile generation' do
397
+ Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/fake.rb")
398
+ end
399
+ end
400
+
401
+ context 'rbconfig' do
402
+ it 'should chain rbconfig tasks to Makefile generation' do
403
+ Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/rbconfig.rb")
404
+ end
405
+
406
+ it 'should take rbconfig from rake-compiler configuration' do
407
+ Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/rbconfig.rb"].prerequisites.should include(@config_path)
408
+ end
409
+ end
410
+
411
+ context 'mkmf' do
412
+ it 'should chain mkmf tasks to Makefile generation' do
413
+ Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/mkmf.rb")
414
+ end
415
+
416
+ it 'should take mkmf from rake-compiler configuration' do
417
+ mkmf_path = File.expand_path(File.join(File.dirname(@config_path), '..', 'mkmf.rb'))
418
+ Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/mkmf.rb"].prerequisites.should include(mkmf_path)
419
+ end
420
+ end
421
+
422
+ context 'compile:universal-unknown' do
423
+ it "should be defined" do
424
+ Rake::Task.task_defined?('compile:universal-unknown').should be_true
425
+ end
426
+
427
+ it "should depend on 'compile:extension_one:universal-unknown'" do
428
+ Rake::Task['compile:universal-unknown'].prerequisites.should include('compile:extension_one:universal-unknown')
429
+ end
430
+ end
431
+
432
+ context 'native:universal-unknown' do
433
+ it "should be defined" do
434
+ Rake::Task.task_defined?('native:universal-unknown').should be_true
435
+ end
436
+
437
+ it "should depend on 'native:my_gem:universal-unknown'" do
438
+ Rake::Task['native:universal-unknown'].prerequisites.should include('native:my_gem:universal-unknown')
439
+ end
440
+ end
441
+ end
442
+
443
+ context '(cross for multiple platforms)' do
444
+ before :each do
445
+ @ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext|
446
+ ext.cross_compile = true
447
+ ext.cross_platform = ['universal-known', 'universal-unknown']
448
+ ext.cross_config_options << '--with-something'
449
+ ext.cross_config_options << {'universal-known' => '--with-known'}
450
+ end
451
+ end
452
+
453
+ it 'should define task for each supplied platform' do
454
+ Rake::Task.should have_defined('compile:universal-known')
455
+ Rake::Task.should have_defined('compile:universal-unknown')
456
+ end
457
+
458
+ it 'should filter options for each supplied platform' do
459
+ @ext.cross_config_options('universal-unknown').should eq(%w[--with-something])
460
+ @ext.cross_config_options('universal-known').should eq(%w[--with-something --with-known])
461
+ end
462
+ end
463
+ end
464
+ end
465
+
466
+ private
467
+ def ext_bin(extension_name)
468
+ "#{extension_name}.#{RbConfig::CONFIG['DLEXT']}"
469
+ end
470
+
471
+ def mock_gem_spec(stubs = {})
472
+ mock(Gem::Specification,
473
+ { :name => 'my_gem', :platform => 'ruby', :files => [] }.merge(stubs)
474
+ )
475
+ end
476
+
477
+ def mock_config_yml
478
+ {
479
+ 'rbconfig-i386-mingw32-1.8.6' => '/some/path/version/1.8/to/rbconfig.rb',
480
+ 'rbconfig-universal-unknown-1.8.6' => '/some/path/version/1.8/to/rbconfig.rb',
481
+ 'rbconfig-i386-mingw32-1.8.7' => '/some/path/version/1.8/to/rbconfig.rb',
482
+ 'rbconfig-universal-known-1.8.7' => '/some/path/version/1.8/to/rbconfig.rb',
483
+ 'rbconfig-universal-unknown-1.8.7' => '/some/path/version/1.8/to/rbconfig.rb',
484
+ 'rbconfig-universal-unknown-1.9.1' => '/some/path/version/1.9.1/to/rbconfig.rb',
485
+ 'rbconfig-universal-unknown-1.9.2' => '/some/path/version/1.9.1/to/rbconfig.rb',
486
+ 'rbconfig-universal-unknown-1.9.3' => '/some/path/version/1.9.1/to/rbconfig.rb',
487
+ 'rbconfig-i386-mingw32-1.9.3' => '/some/path/version/1.9.1/to/rbconfig.rb',
488
+ 'rbconfig-universal-known-1.9.3' => '/some/path/version/1.9.1/to/rbconfig.rb',
489
+ 'rbconfig-universal-known-2.0.0' => '/some/path/version/2.0.0/to/rbconfig.rb',
490
+ 'rbconfig-universal-unknown-1.9.3' => '/some/path/version/1.9.1/to/rbconfig.rb',
491
+ 'rbconfig-universal-unknown-2.0.0' => '/some/path/version/2.0.0/to/rbconfig.rb',
492
+ 'rbconfig-i386-mingw32-2.0.0' => '/some/path/version/2.0.0/to/rbconfig.rb',
493
+ 'rbconfig-x64-mingw32-2.0.0' => '/some/path/version/2.0.0/to/rbconfig.rb',
494
+ 'rbconfig-x64-mingw32-3.0.0' => '/some/fake/version/3.0.0/to/rbconfig.rb'
495
+ }
496
+ end
497
+
498
+ def mock_fake_rb
499
+ mock(File, :write => 45)
500
+ end
501
+ end