blackwinter-rake-compiler 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- 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,182 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
require 'rake/javaextensiontask'
|
4
|
+
require 'rbconfig'
|
5
|
+
|
6
|
+
describe Rake::JavaExtensionTask 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::JavaExtensionTask.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::JavaExtensionTask.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::JavaExtensionTask.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::JavaExtensionTask.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::JavaExtensionTask.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::JavaExtensionTask.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::JavaExtensionTask.new('weird_extension') do |ext|
|
51
|
+
ext.platform = 'java-128bit'
|
52
|
+
end
|
53
|
+
ext.platform.should == 'java-128bit'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context '(defaults)' do
|
59
|
+
before :each do
|
60
|
+
@ext = Rake::JavaExtensionTask.new('extension_one')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should dump intermediate files to tmp/' do
|
64
|
+
@ext.tmp_dir.should == 'tmp'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should copy build extension into lib/' do
|
68
|
+
@ext.lib_dir.should == 'lib'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should look for Java files pattern (.java)' do
|
72
|
+
@ext.source_pattern.should == "**/*.java"
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should have no configuration options preset to delegate' do
|
76
|
+
@ext.config_options.should be_empty
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should default to Java platform' do
|
80
|
+
@ext.platform.should == 'java'
|
81
|
+
end
|
82
|
+
|
83
|
+
context '(tasks)' do
|
84
|
+
before :each do
|
85
|
+
Rake.application.clear
|
86
|
+
CLEAN.clear
|
87
|
+
CLOBBER.clear
|
88
|
+
end
|
89
|
+
|
90
|
+
context '(one extension)' do
|
91
|
+
before :each do
|
92
|
+
Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.java"])
|
93
|
+
@ext = Rake::JavaExtensionTask.new('extension_one')
|
94
|
+
@ext_bin = ext_bin('extension_one')
|
95
|
+
@platform = 'java'
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'compile' do
|
99
|
+
it 'should define as task' do
|
100
|
+
Rake::Task.task_defined?('compile').should be_true
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should depend on 'compile:{platform}'" do
|
104
|
+
pending 'needs fixing'
|
105
|
+
Rake::Task['compile'].prerequisites.should include("compile:#{@platform}")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'compile:extension_one' do
|
110
|
+
it 'should define as task' do
|
111
|
+
Rake::Task.task_defined?('compile:extension_one').should be_true
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should depend on 'compile:extension_one:{platform}'" do
|
115
|
+
pending 'needs fixing'
|
116
|
+
Rake::Task['compile:extension_one'].prerequisites.should include("compile:extension_one:#{@platform}")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'lib/extension_one.jar' do
|
121
|
+
it 'should define as task' do
|
122
|
+
pending 'needs fixing'
|
123
|
+
Rake::Task.task_defined?("lib/#{@ext_bin}").should be_true
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should depend on 'copy:extension_one:{platform}'" do
|
127
|
+
pending 'needs fixing'
|
128
|
+
Rake::Task["lib/#{@ext_bin}"].prerequisites.should include("copy:extension_one:#{@platform}")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'tmp/{platform}/extension_one/extension_one.jar' do
|
133
|
+
it 'should define as task' do
|
134
|
+
Rake::Task.task_defined?("tmp/#{@platform}/extension_one/#{@ext_bin}").should be_true
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should depend on checkpoint file" do
|
138
|
+
Rake::Task["tmp/#{@platform}/extension_one/#{@ext_bin}"].prerequisites.should include("tmp/#{@platform}/extension_one/.build")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'tmp/{platform}/extension_one/.build' do
|
143
|
+
it 'should define as task' do
|
144
|
+
Rake::Task.task_defined?("tmp/#{@platform}/extension_one/.build").should be_true
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should depend on source files' do
|
148
|
+
Rake::Task["tmp/#{@platform}/extension_one/.build"].prerequisites.should include("ext/extension_one/source.java")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'clean' do
|
153
|
+
it "should include 'tmp/{platform}/extension_one' in the pattern" do
|
154
|
+
CLEAN.should include("tmp/#{@platform}/extension_one")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'clobber' do
|
159
|
+
it "should include 'lib/extension_one.jar'" do
|
160
|
+
CLOBBER.should include("lib/#{@ext_bin}")
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should include 'tmp'" do
|
164
|
+
CLOBBER.should include('tmp')
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
private
|
171
|
+
|
172
|
+
def ext_bin(extension_name)
|
173
|
+
"#{extension_name}.jar"
|
174
|
+
end
|
175
|
+
|
176
|
+
def mock_gem_spec(stubs = {})
|
177
|
+
mock(Gem::Specification,
|
178
|
+
{ :name => 'my_gem', :platform => 'ruby' }.merge(stubs)
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
# Console redirection helper
|
4
|
+
require File.expand_path('../support/capture_output_helper', __FILE__)
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.include CaptureOutputHelper
|
8
|
+
end
|
9
|
+
|
10
|
+
# Rake::Task matcher helper
|
11
|
+
RSpec::Matchers.define :have_defined do |task|
|
12
|
+
match do |tasks|
|
13
|
+
tasks.task_defined?(task)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CaptureOutputHelper
|
2
|
+
def capture_output(&block)
|
3
|
+
old_stdout = $stdout
|
4
|
+
old_stderr = $stderr
|
5
|
+
|
6
|
+
stream_out = StringIO.new
|
7
|
+
stream_err = StringIO.new
|
8
|
+
|
9
|
+
begin
|
10
|
+
$stdout = stream_out
|
11
|
+
$stderr = stream_err
|
12
|
+
yield
|
13
|
+
ensure
|
14
|
+
$stdout = old_stdout
|
15
|
+
$stderr = old_stderr
|
16
|
+
end
|
17
|
+
stream_out.rewind
|
18
|
+
stream_err.rewind
|
19
|
+
|
20
|
+
[stream_out.read, stream_err.read]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
#--
|
2
|
+
# Cross-compile ruby, using Rake
|
3
|
+
#
|
4
|
+
# This source code is released under the MIT License.
|
5
|
+
# See LICENSE file for details
|
6
|
+
#++
|
7
|
+
|
8
|
+
#
|
9
|
+
# This code is inspired and based on notes from the following sites:
|
10
|
+
#
|
11
|
+
# http://tenderlovemaking.com/2008/11/21/cross-compiling-ruby-gems-for-win32/
|
12
|
+
# http://github.com/jbarnette/johnson/tree/master/cross-compile.txt
|
13
|
+
# http://eigenclass.org/hiki/cross+compiling+rcovrt
|
14
|
+
#
|
15
|
+
# This recipe only cleanup the dependency chain and automate it.
|
16
|
+
# Also opens the door to usage different ruby versions
|
17
|
+
# for cross-compilation.
|
18
|
+
#
|
19
|
+
|
20
|
+
abort <<-EOT if RUBY_PLATFORM =~ /mingw|mswin/
|
21
|
+
This tool is meant to be executed under Linux or OSX, not Windows.
|
22
|
+
It is used for cross-compilation only.
|
23
|
+
EOT
|
24
|
+
|
25
|
+
require 'rake'
|
26
|
+
require 'rake/clean'
|
27
|
+
|
28
|
+
require 'rbconfig'
|
29
|
+
require 'safe_yaml/load'
|
30
|
+
|
31
|
+
ruby_src = ENV['SRC']
|
32
|
+
ruby_svn = ENV['SVN']
|
33
|
+
|
34
|
+
make_command = ENV.fetch('MAKE') {
|
35
|
+
require 'nuggets/file/which'
|
36
|
+
File.which_command(%w[gmake make])
|
37
|
+
}
|
38
|
+
|
39
|
+
mingw_host = ENV.fetch('HOST') {
|
40
|
+
require 'rake/extensioncompiler'
|
41
|
+
Rake::ExtensionCompiler.mingw_host
|
42
|
+
}
|
43
|
+
|
44
|
+
version_name = 'ruby-%s' % ENV.fetch('VERSION') {
|
45
|
+
'%s-p%s' % [RUBY_VERSION, RUBY_PATCHLEVEL]
|
46
|
+
}
|
47
|
+
|
48
|
+
# Grab the major "1.8" or "1.9" part of the version number
|
49
|
+
version_major = version_name[/.*-(\d\.\d)\.\d/, 1]
|
50
|
+
|
51
|
+
download_url = "http://cache.ruby-lang.org/pub/ruby/#{version_major}"
|
52
|
+
svn_repo_url = 'http://svn.ruby-lang.org/repos/ruby'
|
53
|
+
|
54
|
+
base_directory = File.expand_path('~/.rake-compiler')
|
55
|
+
config_file = File.join(base_directory, 'config.yml')
|
56
|
+
|
57
|
+
sources_directory = File.join(base_directory, 'sources')
|
58
|
+
builds_directory = File.join(base_directory, 'builds')
|
59
|
+
targets_directory = File.join(base_directory, 'ruby')
|
60
|
+
|
61
|
+
source_directory = File.join(sources_directory, version_name)
|
62
|
+
build_directory = File.join(builds_directory, mingw_host, version_name)
|
63
|
+
target_directory = File.join(targets_directory, mingw_host, version_name)
|
64
|
+
|
65
|
+
tarball_file = !ruby_src ? source_directory + '.tar.bz2' :
|
66
|
+
File.join(sources_directory, File.basename(ruby_src))
|
67
|
+
|
68
|
+
makefile_file = File.join(build_directory, 'Makefile')
|
69
|
+
makefile_in_file = File.join(source_directory, 'Makefile.in')
|
70
|
+
makefile_in_bak_file = makefile_in_file + '.bak'
|
71
|
+
|
72
|
+
build_ruby_exe_file = File.join(build_directory, 'ruby.exe')
|
73
|
+
target_ruby_exe_file = File.join(target_directory, 'bin', 'ruby.exe')
|
74
|
+
|
75
|
+
# Unset any possible variable that might affect compilation
|
76
|
+
%w[CC CXX CPPFLAGS LDFLAGS RUBYOPT].each { |k| ENV.delete(k) }
|
77
|
+
|
78
|
+
# Define a location where sources will be stored
|
79
|
+
directory source_directory
|
80
|
+
directory build_directory
|
81
|
+
|
82
|
+
# Clean intermediate files and folders
|
83
|
+
CLEAN.include(source_directory)
|
84
|
+
CLEAN.include(build_directory)
|
85
|
+
|
86
|
+
# Remove the final products and sources
|
87
|
+
CLOBBER.include(sources_directory)
|
88
|
+
CLOBBER.include(builds_directory)
|
89
|
+
CLOBBER.include(target_directory)
|
90
|
+
CLOBBER.include(config_file)
|
91
|
+
|
92
|
+
# Ruby source file should be stored here
|
93
|
+
file tarball_file => sources_directory do |t|
|
94
|
+
url = ruby_src || File.join(download_url, File.basename(t.name))
|
95
|
+
chdir(sources_directory) { sh "wget #{url} || curl -O #{url}" }
|
96
|
+
end
|
97
|
+
|
98
|
+
# Extract the sources
|
99
|
+
if ruby_svn
|
100
|
+
file source_directory => sources_directory do |t|
|
101
|
+
sh "svn export -q #{File.join(svn_repo_url, ruby_svn)} #{t.name}"
|
102
|
+
chdir(source_directory) { sh 'autoreconf' }
|
103
|
+
end
|
104
|
+
else
|
105
|
+
file source_directory => tarball_file do |t|
|
106
|
+
chdir(sources_directory) { sh "tar xf #{tarball_file}" }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Backup makefile.in
|
111
|
+
file makefile_in_bak_file => source_directory do |t|
|
112
|
+
cp makefile_in_file, t.name
|
113
|
+
end
|
114
|
+
|
115
|
+
# Correct the makefile
|
116
|
+
file makefile_in_file => makefile_in_bak_file do |t|
|
117
|
+
out = ''
|
118
|
+
|
119
|
+
File.foreach(t.name) { |line|
|
120
|
+
line.sub!(/\A(\s*ALT_SEPARATOR =).*/, "\\1 \"\\\\\\\\\"; \\\n")
|
121
|
+
out << line
|
122
|
+
}
|
123
|
+
|
124
|
+
when_writing('Patching Makefile.in') { File.write(t.name, out) }
|
125
|
+
end
|
126
|
+
|
127
|
+
# Generate the makefile in a clean build location
|
128
|
+
file makefile_file => [build_directory, makefile_in_file] do |t|
|
129
|
+
options = %W[
|
130
|
+
--host=#{mingw_host}
|
131
|
+
--target=#{mingw_host.gsub('msvc', '')}
|
132
|
+
--build=#{RbConfig::CONFIG['host']}
|
133
|
+
--prefix=#{target_directory}
|
134
|
+
--enable-shared
|
135
|
+
--disable-install-doc
|
136
|
+
--without-tk
|
137
|
+
--without-tcl
|
138
|
+
]
|
139
|
+
|
140
|
+
# Force Winsock2 for Ruby 1.8, 1.9 defaults to it
|
141
|
+
options << '--with-winsock2' if version_major == '1.8'
|
142
|
+
|
143
|
+
chdir(build_directory) {
|
144
|
+
sh File.join(source_directory, 'configure'), *options
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
# Make
|
149
|
+
file build_ruby_exe_file => makefile_file do |t|
|
150
|
+
chdir(build_directory) { sh make_command }
|
151
|
+
end
|
152
|
+
|
153
|
+
# Make install
|
154
|
+
file target_ruby_exe_file => build_ruby_exe_file do |t|
|
155
|
+
chdir(build_directory) { sh "#{make_command} install" }
|
156
|
+
end
|
157
|
+
|
158
|
+
task :install => target_ruby_exe_file
|
159
|
+
|
160
|
+
task :mingw32 do
|
161
|
+
abort <<-EOT unless mingw_host
|
162
|
+
You need to install mingw32 cross compile functionality to be able to continue.
|
163
|
+
Please refer to your distribution/package manager documentation about installation.
|
164
|
+
EOT
|
165
|
+
end
|
166
|
+
|
167
|
+
desc 'Update rake-compiler list of installed Ruby versions'
|
168
|
+
task 'update-config' do
|
169
|
+
config = if File.exist?(config_file)
|
170
|
+
puts "Updating #{config_file}"
|
171
|
+
SafeYAML.load_file(config_file)
|
172
|
+
else
|
173
|
+
puts "Generating #{config_file}"
|
174
|
+
{}
|
175
|
+
end
|
176
|
+
|
177
|
+
Dir["#{targets_directory}/*/*/**/rbconfig.rb"].sort.each { |rbconfig|
|
178
|
+
if rbconfig =~ %r{.*-(\d.\d.\d).*/([-\w]+)/rbconfig}
|
179
|
+
version, platform = $1, $2
|
180
|
+
else
|
181
|
+
warn "Invalid pattern: #{rbconfig}"
|
182
|
+
next
|
183
|
+
end
|
184
|
+
|
185
|
+
platforms, key = [platform], "rbconfig-%s-#{version}"
|
186
|
+
|
187
|
+
# Fake alternate (binary compatible) i386-mswin32-60 platform
|
188
|
+
platforms << 'i386-mswin32-60' if platform == 'i386-mingw32'
|
189
|
+
|
190
|
+
platforms.each { |pf|
|
191
|
+
config[key % pf] = rbconfig
|
192
|
+
|
193
|
+
# Also store RubyGems-compatible version
|
194
|
+
config[key % Gem::Platform.new(pf)] = rbconfig
|
195
|
+
}
|
196
|
+
|
197
|
+
puts "Found Ruby version #{version} for platform #{platform} (#{rbconfig})"
|
198
|
+
}
|
199
|
+
|
200
|
+
when_writing("Saving changes into #{config_file}") {
|
201
|
+
File.open(config_file, 'w') { |f| YAML.dump(config, f) }
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
205
|
+
task :default do
|
206
|
+
# Force the display of the available tasks when no option is given
|
207
|
+
Rake.application.options.show_task_pattern = //
|
208
|
+
Rake.application.options.show_tasks = :tasks
|
209
|
+
Rake.application.display_tasks_and_comments
|
210
|
+
end
|
211
|
+
|
212
|
+
desc "Build #{version_name} suitable for cross-platform development."
|
213
|
+
task 'cross-ruby' => [:mingw32, :install, 'update-config']
|
@@ -0,0 +1,11 @@
|
|
1
|
+
desc 'Ensure all the cross compiled versions are installed'
|
2
|
+
task :bootstrap do
|
3
|
+
fail "Sorry, this only works on OSX and Linux" if RUBY_PLATFORM =~ /mswin|mingw/
|
4
|
+
|
5
|
+
versions = %w(1.8.7-p371 1.9.3-p392 2.0.0-p0)
|
6
|
+
|
7
|
+
versions.each do |version|
|
8
|
+
puts "[INFO] Attempt to cross-compile Ruby #{version}"
|
9
|
+
ruby "-Ilib bin/rake-compiler cross-ruby VERSION=#{version}"
|
10
|
+
end
|
11
|
+
end
|