blackwinter-rake-compiler 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/History.txt +308 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +415 -0
- data/Rakefile +15 -0
- data/bin/rake-compiler +24 -0
- data/cucumber.yml +4 -0
- data/features/compile.feature +79 -0
- data/features/cross-compile.feature +23 -0
- data/features/cross-package-multi.feature +15 -0
- data/features/cross-package.feature +14 -0
- data/features/java-compile.feature +22 -0
- data/features/java-no-native-compile.feature +33 -0
- data/features/java-package.feature +24 -0
- data/features/package.feature +40 -0
- data/features/step_definitions/compilation.rb +70 -0
- data/features/step_definitions/cross_compilation.rb +27 -0
- data/features/step_definitions/execution.rb +52 -0
- data/features/step_definitions/folders.rb +32 -0
- data/features/step_definitions/gem.rb +46 -0
- data/features/step_definitions/java_compilation.rb +7 -0
- data/features/support/env.rb +10 -0
- data/features/support/file_template_helpers.rb +137 -0
- data/features/support/generator_helpers.rb +123 -0
- data/features/support/platform_extension_helpers.rb +27 -0
- data/lib/rake/baseextensiontask.rb +90 -0
- data/lib/rake/extensioncompiler.rb +53 -0
- data/lib/rake/extensiontask.rb +513 -0
- data/lib/rake/javaextensiontask.rb +226 -0
- data/spec/lib/rake/extensiontask_spec.rb +501 -0
- data/spec/lib/rake/javaextensiontask_spec.rb +182 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/capture_output_helper.rb +22 -0
- data/tasks/bin/cross-ruby.rake +213 -0
- data/tasks/bootstrap.rake +11 -0
- data/tasks/common.rake +10 -0
- data/tasks/cucumber.rake +23 -0
- data/tasks/gem.rake +52 -0
- data/tasks/news.rake +39 -0
- data/tasks/release.rake +26 -0
- data/tasks/rspec.rake +9 -0
- 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
|