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.
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