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,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
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format nested
3
+ --loadby mtime
@@ -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