rake-compiler-sgonyea 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +254 -0
- data/Isolate +6 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +393 -0
- data/Rakefile +21 -0
- data/bin/rake-compiler +24 -0
- data/cucumber.yml +4 -0
- data/features/compile.feature +79 -0
- data/features/cross-compile.feature +22 -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 +25 -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 +6 -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 +431 -0
- data/lib/rake/javaextensiontask.rb +226 -0
- data/spec/lib/rake/extensiontask_spec.rb +481 -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 +196 -0
- data/tasks/bootstrap.rake +11 -0
- data/tasks/common.rake +10 -0
- data/tasks/cucumber.rake +23 -0
- data/tasks/gem.rake +53 -0
- data/tasks/news.rake +39 -0
- data/tasks/release.rake +26 -0
- data/tasks/rspec.rake +9 -0
- metadata +145 -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,481 @@
|
|
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("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
|
+
@config_path = mock_config_yml["rbconfig-#{@ruby_ver}"]
|
282
|
+
|
283
|
+
File.stub!(:open).and_yield(mock_fake_rb)
|
284
|
+
end
|
285
|
+
|
286
|
+
context 'if no rake-compiler configuration exists' do
|
287
|
+
before :each do
|
288
|
+
File.should_receive(:exist?).with(@config_file).and_return(false)
|
289
|
+
|
290
|
+
_, @err = capture_output do
|
291
|
+
Rake::ExtensionTask.new('extension_one') do |ext|
|
292
|
+
ext.cross_compile = true
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'should not generate a warning' do
|
298
|
+
@err.should eq("")
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'should create a dummy nested cross-compile target that raises an error' do
|
302
|
+
Rake::Task.should have_defined("cross")
|
303
|
+
Rake::Task["cross"].invoke
|
304
|
+
lambda {
|
305
|
+
Rake::Task["compile"].invoke
|
306
|
+
}.should raise_error(RuntimeError,
|
307
|
+
/rake-compiler must be configured first to enable cross-compilation/)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'should parse the config file using YAML' do
|
312
|
+
YAML.should_receive(:load_file).with(@config_file).and_return(mock_config_yml)
|
313
|
+
Rake::ExtensionTask.new('extension_one') do |ext|
|
314
|
+
ext.cross_compile = true
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'should warn if no section of config file defines running version of ruby' do
|
319
|
+
config = mock(Hash)
|
320
|
+
config.should_receive(:[]).with("rbconfig-#{@ruby_ver}").and_return(nil)
|
321
|
+
YAML.stub!(:load_file).and_return(config)
|
322
|
+
out, err = capture_output do
|
323
|
+
Rake::ExtensionTask.new('extension_one') do |ext|
|
324
|
+
ext.cross_compile = true
|
325
|
+
end
|
326
|
+
end
|
327
|
+
err.should match(/no configuration section for specified version of Ruby/)
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'should capture an action block to be executed when cross compiling' do
|
331
|
+
lambda {
|
332
|
+
Rake::ExtensionTask.new('extension_one') do |ext|
|
333
|
+
ext.cross_compiling do |gem_spec|
|
334
|
+
gem_spec.post_install_message = "Cross compiled gem"
|
335
|
+
end
|
336
|
+
end
|
337
|
+
}.should_not raise_error
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'should allow usage of RUBY_CC_VERSION to indicate a different version of ruby' do
|
341
|
+
config = mock(Hash)
|
342
|
+
config.should_receive(:[]).with("rbconfig-1.9.1").and_return('/path/to/ruby/1.9.1/rbconfig.rb')
|
343
|
+
YAML.stub!(:load_file).and_return(config)
|
344
|
+
|
345
|
+
ENV['RUBY_CC_VERSION'] = '1.9.1'
|
346
|
+
Rake::ExtensionTask.new('extension_one') do |ext|
|
347
|
+
ext.cross_compile = true
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'should allow multiple versions be supplied to RUBY_CC_VERSION' do
|
352
|
+
config = mock(Hash)
|
353
|
+
config.should_receive(:[]).once.with("rbconfig-1.8.6").and_return('/path/to/ruby/1.8.6/rbconfig.rb')
|
354
|
+
config.should_receive(:[]).once.with("rbconfig-1.9.1").and_return('/path/to/ruby/1.9.1/rbconfig.rb')
|
355
|
+
YAML.stub!(:load_file).and_return(config)
|
356
|
+
|
357
|
+
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
|
358
|
+
Rake::ExtensionTask.new('extension_one') do |ext|
|
359
|
+
ext.cross_compile = true
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
after :each do
|
364
|
+
ENV.delete('RUBY_CC_VERSION')
|
365
|
+
end
|
366
|
+
|
367
|
+
context "(cross compile for multiple versions)" do
|
368
|
+
before :each do
|
369
|
+
config = mock(Hash)
|
370
|
+
config.stub!(:[]).and_return('/path/to/ruby/1.8.6/rbconfig.rb', '/path/to/ruby/1.9.1/rbconfig.rb')
|
371
|
+
YAML.stub!(:load_file).and_return(config)
|
372
|
+
|
373
|
+
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
|
374
|
+
@ext = Rake::ExtensionTask.new('extension_one') do |ext|
|
375
|
+
ext.cross_compile = true
|
376
|
+
ext.cross_platform = 'universal-unknown'
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'should create specific copy of binaries for each version' do
|
381
|
+
Rake::Task.should have_defined("copy:extension_one:universal-unknown:1.8.6")
|
382
|
+
Rake::Task.should have_defined("copy:extension_one:universal-unknown:1.9.1")
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
context "(cross for 'universal-unknown' platform)" do
|
387
|
+
before :each do
|
388
|
+
@ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext|
|
389
|
+
ext.cross_compile = true
|
390
|
+
ext.cross_platform = 'universal-unknown'
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
context 'fake' do
|
395
|
+
it 'should chain fake task to Makefile generation' do
|
396
|
+
Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/fake.rb")
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
context 'rbconfig' do
|
401
|
+
it 'should chain rbconfig tasks to Makefile generation' do
|
402
|
+
Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/rbconfig.rb")
|
403
|
+
end
|
404
|
+
|
405
|
+
it 'should take rbconfig from rake-compiler configuration' do
|
406
|
+
Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/rbconfig.rb"].prerequisites.should include(@config_path)
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
context 'mkmf' do
|
411
|
+
it 'should chain mkmf tasks to Makefile generation' do
|
412
|
+
Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/mkmf.rb")
|
413
|
+
end
|
414
|
+
|
415
|
+
it 'should take mkmf from rake-compiler configuration' do
|
416
|
+
mkmf_path = File.expand_path(File.join(File.dirname(@config_path), '..', 'mkmf.rb'))
|
417
|
+
Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/mkmf.rb"].prerequisites.should include(mkmf_path)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
context 'compile:universal-unknown' do
|
422
|
+
it "should be defined" do
|
423
|
+
Rake::Task.task_defined?('compile:universal-unknown').should be_true
|
424
|
+
end
|
425
|
+
|
426
|
+
it "should depend on 'compile:extension_one:universal-unknown'" do
|
427
|
+
Rake::Task['compile:universal-unknown'].prerequisites.should include('compile:extension_one:universal-unknown')
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context 'native:universal-unknown' do
|
432
|
+
it "should be defined" do
|
433
|
+
Rake::Task.task_defined?('native:universal-unknown').should be_true
|
434
|
+
end
|
435
|
+
|
436
|
+
it "should depend on 'native:my_gem:universal-unknown'" do
|
437
|
+
Rake::Task['native:universal-unknown'].prerequisites.should include('native:my_gem:universal-unknown')
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
context '(cross for multiple platforms)' do
|
443
|
+
it 'should define task for each supplied platform' do
|
444
|
+
@ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext|
|
445
|
+
ext.cross_compile = true
|
446
|
+
ext.cross_platform = ['universal-known', 'universal-unknown']
|
447
|
+
end
|
448
|
+
|
449
|
+
Rake::Task.should have_defined('compile:universal-known')
|
450
|
+
Rake::Task.should have_defined('compile:universal-unknown')
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
private
|
457
|
+
def ext_bin(extension_name)
|
458
|
+
"#{extension_name}.#{RbConfig::CONFIG['DLEXT']}"
|
459
|
+
end
|
460
|
+
|
461
|
+
def mock_gem_spec(stubs = {})
|
462
|
+
mock(Gem::Specification,
|
463
|
+
{ :name => 'my_gem', :platform => 'ruby' }.merge(stubs)
|
464
|
+
)
|
465
|
+
end
|
466
|
+
|
467
|
+
def mock_config_yml
|
468
|
+
{
|
469
|
+
'rbconfig-1.8.6' => '/some/path/version/1.8/to/rbconfig.rb',
|
470
|
+
'rbconfig-1.8.7' => '/some/path/version/1.8/to/rbconfig.rb',
|
471
|
+
'rbconfig-1.9.1' => '/some/path/version/1.9.1/to/rbconfig.rb',
|
472
|
+
'rbconfig-1.9.2' => '/some/path/version/1.9.1/to/rbconfig.rb',
|
473
|
+
'rbconfig-1.9.3' => '/some/path/version/1.9.1/to/rbconfig.rb',
|
474
|
+
'rbconfig-3.0.0' => '/some/fake/version/3.0.0/to/rbconfig.rb'
|
475
|
+
}
|
476
|
+
end
|
477
|
+
|
478
|
+
def mock_fake_rb
|
479
|
+
mock(File, :write => 45)
|
480
|
+
end
|
481
|
+
end
|