luislavena-rake-compiler 0.1.1 → 0.2.0

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.
data/README.rdoc CHANGED
@@ -157,12 +157,78 @@ personalize several settings for <tt>Rake::ExtensionTask</tt>:
157
157
  ext.config_script = 'custom_extconf.rb' # use instead of 'extconf.rb' default
158
158
  ext.tmp_dir = 'tmp' # temporary folder used during compilation.
159
159
  ext.source_pattern = "*.{c,cpp}" # monitor file changes to allow simple rebuild.
160
- ext.additional_options << '--with-foo' # supply addition configure options to config script-
160
+ ext.config_options << '--with-foo' # supply additional configure options to config script.
161
161
  ext.gem_spec = spec # optional indicate which gem specification
162
162
  # will be used to based on.
163
163
  end
164
164
 
165
165
 
166
+ == Future is now: Cross compilation
167
+
168
+ rake-compiler provides now an standarized way to generate, from Linux or OSX
169
+ both extensions and gem binaries for Windows!
170
+
171
+ It takes advantages from GCC host/target to build binaries (for target) on
172
+ different OS (hosts).
173
+
174
+
175
+ === How I enjoy this?
176
+
177
+ Besides having the development tool chain installed (GCC), you should install
178
+ also <tt>mingw32</tt> cross compilation package.
179
+
180
+ Dependending on your operating system distribution, a simple <tt>apt-get install mingw32</tt>
181
+ will be enough.
182
+
183
+ Please check OSX documentation about installing mingw32 from macports.
184
+
185
+
186
+ === I have my toolchain, now what?
187
+
188
+ You need to build Ruby for Windows.
189
+
190
+ Relax, no need to freak out. rake-compiler do it for you:
191
+
192
+ rake-compiler cross-ruby
193
+
194
+ And you're done. It will automatically download, configure and compile latest
195
+ stable version of Ruby for Windows, and place it into <tt>~/.rake-compiler</tt>
196
+
197
+ If, instead, you want to build another version than the default one, please
198
+ supply a <tt>VERSION</tt>:
199
+
200
+ rake-compiler cross-ruby VERSION=1.8.6-p114
201
+
202
+ === Let's build some gems!
203
+
204
+ Now, you only need to use additional options in your extension defintion:
205
+
206
+ Rake::ExtensionTask.new('my_extension', gem_spec) do |ext|
207
+ ext.cross_compile = true # enable cross compilation (requires cross compile toolchain)
208
+ ext.cross_platform = 'i386-mswin32' # forces the Windows platform instead of the default one
209
+ # configure options only for cross compile
210
+ ext.cross_config_options << '--with-something'
211
+ end
212
+
213
+ By default, cross compilation targets 'i386-mingw32' which is default GCC platform
214
+ for Ruby.
215
+
216
+ To target gems for current Ruby official distribution, please force the platform
217
+ to the one shown before.
218
+
219
+ === Magician doing some tricks, don't blink!
220
+
221
+ Compiles keeps being simple:
222
+
223
+ rake cross compile
224
+
225
+ And now, build your gems for Windows is just 4 more letters:
226
+
227
+ rake cross native gem
228
+
229
+ And you're done, yeah.
230
+
231
+
166
232
  == Future
167
233
 
168
234
  rake-compiler is a work in progress and we will appreciate feedback during the
@@ -20,7 +20,7 @@ Feature: Compile C code into Ruby extensions.
20
20
  And not changed any file since
21
21
  When rake task 'compile' is invoked
22
22
  Then rake task 'compile' succeeded
23
- And output of rake task 'compile' do not contain /extension_one/
23
+ And output of rake task 'compile' do not contain /gcc|cl/
24
24
 
25
25
  Scenario: recompile extension when source is modified
26
26
  Given a safe project directory
@@ -0,0 +1,13 @@
1
+ Feature: Cross-compile C extensions
2
+
3
+ In order to avoid bitching from Windows users
4
+ As a Ruby developer on Linux
5
+ I want some rake tasks that take away the pain of compilation
6
+
7
+ Scenario: compile single extension
8
+ Given that all my source files are in place
9
+ And I'm running a POSIX operating system
10
+ And I've installed cross compile toolchain
11
+ When rake task 'cross compile' is invoked
12
+ Then rake task 'cross compile' succeeded
13
+ And binaries for platform 'i386-mingw32' get generated
@@ -0,0 +1,14 @@
1
+ Feature: Generate Windows gems from Linux
2
+
3
+ In order to keep sanity in the Ruby world
4
+ As a Gem developer on Linux
5
+ I want more rake magic that turns monotony into joy.
6
+
7
+ Scenario: package a gem for Windows
8
+ Given that my gem source is all in place
9
+ And I'm running a POSIX operating system
10
+ And I've installed cross compile toolchain
11
+ And I've already successfully executed rake task 'cross compile'
12
+ When rake task 'cross native gem' is invoked
13
+ Then rake task 'cross native gem' succeeded
14
+ And gem for platform 'x86-mingw32' get generated
@@ -33,8 +33,8 @@ Feature: Distribute native extension with gems
33
33
  And a extension 'extension_one' with forced platform 'universal-unknown'
34
34
  And I've already successfully executed rake task 'compile'
35
35
  And 'pkg' folder is deleted
36
- When rake task 'native gem' is invoked
37
- Then rake task 'native gem' succeeded
36
+ When rake task 'native:universal-unknown gem' is invoked
37
+ Then rake task 'native:universal-unknown gem' succeeded
38
38
  And 'pkg' folder is created
39
39
  And ruby gem for 'my_project' version '0.1.0' do exist in 'pkg'
40
40
  And a gem for 'my_project' version '0.1.0' platform 'universal-unknown' do exist in 'pkg'
@@ -3,11 +3,27 @@ Given /^a extension named '(.*)'$/ do |extension_name|
3
3
  generate_source_code_for extension_name
4
4
  end
5
5
 
6
+ Given /^a extension cross-compilable '(.*)'$/ do |extension_name|
7
+ generate_cross_compile_extension_task_for extension_name
8
+ generate_source_code_for extension_name
9
+ end
10
+
6
11
  Given /^a extension '(.*)' with forced platform '(.*)'$/ do |extension_name, forced_platform|
7
12
  generate_extension_task_for extension_name, forced_platform
8
13
  generate_source_code_for extension_name
9
14
  end
10
15
 
16
+ Given /^that all my source files are in place$/ do
17
+ Given "a safe project directory"
18
+ Given "a extension cross-compilable 'extension_one'"
19
+ end
20
+
21
+ Given /^that my gem source is all in place$/ do
22
+ Given "a safe project directory"
23
+ Given "a gem named 'gem_abc'"
24
+ Given "a extension cross-compilable 'extension_one'"
25
+ end
26
+
11
27
  Given /^not changed any file since$/ do
12
28
  # don't do anything, that's the purpose of this step!
13
29
  end
@@ -0,0 +1,20 @@
1
+ # Naive way of looking into platforms, please include others like FreeBSD?
2
+ if RUBY_PLATFORM =~ /linux|darwin/
3
+ Given %r{^I'm running a POSIX operating system$} do
4
+ end
5
+ end
6
+
7
+ Given %r{^I've installed cross compile toolchain$} do
8
+ compiler = 'i586-mingw32msvc-gcc'
9
+ found = false
10
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
11
+ next unless File.exist?(File.join(path, compiler))
12
+ found = true
13
+ end
14
+ raise "Cannot locate '#{compiler}' in the PATH." unless found
15
+ end
16
+
17
+ Then /^binaries for platform '(.*)' get generated$/ do |platform|
18
+ ext_for_platform = Dir.glob("tmp/#{platform}/**/*.#{RbConfig::CONFIG['DLEXT']}")
19
+ ext_for_platform.should_not be_empty
20
+ end
@@ -14,6 +14,10 @@ Then /^a gem for '(.*)' version '(.*)' platform '(.*)' do exist in '(.*)'$/ do |
14
14
  File.exist?(gem_file_platform(folder, name, version, platform)).should be_true
15
15
  end
16
16
 
17
+ Then /^gem for platform '(.*)' get generated$/ do |platform|
18
+ Then "a gem for 'gem_abc' version '0.1.0' platform '#{platform}' do exist in 'pkg'"
19
+ end
20
+
17
21
  def gem_file(folder, name, version)
18
22
  "#{folder}/#{name}-#{version}.gem"
19
23
  end
@@ -19,6 +19,10 @@ SPEC = Gem::Specification.new do |s|
19
19
  s.version = "0.1.0"
20
20
  s.summary = "#{gem_name} test gem for rake-compiler"
21
21
 
22
+ s.files = FileList["ext/**/*.{rb,c,h}", "Rakefile", "tasks/*.rake", "lib/**/*.rb"]
23
+
24
+ s.extensions = FileList["ext/**/extconf.rb"]
25
+
22
26
  s.has_rdoc = true
23
27
 
24
28
  s.homepage = 'http://github.com/luislavena/rake-compiler'
@@ -51,6 +55,15 @@ end
51
55
  EOF
52
56
  end
53
57
 
58
+ def template_rake_extension_cross_compile(extension_name, gem_spec = nil)
59
+ <<-EOF
60
+ require 'rake/extensiontask'
61
+ Rake::ExtensionTask.new("#{extension_name}"#{', SPEC' if gem_spec}) do |ext|
62
+ ext.cross_compile = true
63
+ end
64
+ EOF
65
+ end
66
+
54
67
  def template_extconf(extension_name)
55
68
  <<-EOF
56
69
  require 'mkmf'
@@ -40,6 +40,25 @@ def generate_extension_task_for(extension_name, platform = nil)
40
40
  end
41
41
  end
42
42
 
43
+ def generate_cross_compile_extension_task_for(extension_name)
44
+ # create folder structure
45
+ FileUtils.mkdir_p "ext/#{extension_name}"
46
+
47
+ return if File.exist?("tasks/#{extension_name}.rake")
48
+
49
+ # create specific extension rakefile
50
+ # Building a gem?
51
+ if File.exist?("tasks/gem.rake") then
52
+ File.open("tasks/gem.rake", 'a+') do |ext_in_gem|
53
+ ext_in_gem.puts template_rake_extension_cross_compile(extension_name, true)
54
+ end
55
+ else
56
+ File.open("tasks/#{extension_name}.rake", 'w') do |ext_rake|
57
+ ext_rake.puts template_rake_extension_cross_compile(extension_name)
58
+ end
59
+ end
60
+ end
61
+
43
62
  def generate_source_code_for(extension_name)
44
63
  # source C file
45
64
  File.open("ext/#{extension_name}/source.c", 'w') do |c|
@@ -9,6 +9,9 @@ require 'rake/tasklib'
9
9
  require 'rbconfig'
10
10
 
11
11
  module Rake
12
+ autoload :GemPackageTask, 'rake/gempackagetask'
13
+ autoload :YAML, 'yaml'
14
+
12
15
  class ExtensionTask < TaskLib
13
16
  attr_accessor :name
14
17
  attr_accessor :gem_spec
@@ -17,8 +20,11 @@ module Rake
17
20
  attr_accessor :ext_dir
18
21
  attr_accessor :lib_dir
19
22
  attr_accessor :platform
20
- attr_accessor :additional_options
23
+ attr_accessor :config_options
21
24
  attr_accessor :source_pattern
25
+ attr_accessor :cross_compile
26
+ attr_accessor :cross_platform
27
+ attr_accessor :cross_config_options
22
28
 
23
29
  def initialize(name = nil, gem_spec = nil)
24
30
  init(name, gem_spec)
@@ -34,149 +40,231 @@ module Rake
34
40
  @ext_dir = 'ext'
35
41
  @lib_dir = 'lib'
36
42
  @source_pattern = "*.c"
37
- @additional_options = []
43
+ @config_options = []
44
+ @cross_compile = false
45
+ @cross_config_options = []
38
46
  end
39
47
 
40
48
  def platform
41
49
  @platform ||= RUBY_PLATFORM
42
50
  end
43
51
 
52
+ def cross_platform
53
+ @cross_platform ||= 'i386-mingw32'
54
+ end
55
+
44
56
  def define
45
57
  fail "Extension name must be provided." if @name.nil?
46
58
 
47
59
  define_compile_tasks
48
- define_native_tasks if @gem_spec
60
+
61
+ # only gems with 'ruby' platforms are allowed to define native tasks
62
+ define_native_tasks if @gem_spec && @gem_spec.platform == 'ruby'
63
+
64
+ # only define cross platform functionality when enabled
65
+ # FIXME: there is no value for having this on Windows or JRuby
66
+ define_cross_platform_tasks if @cross_compile
49
67
  end
50
68
 
51
69
  private
52
- def define_compile_tasks
70
+ def define_compile_tasks(for_platform = nil)
71
+ # platform usage
72
+ platf = for_platform || platform
73
+
74
+ # tmp_path
75
+ tmp_path = "#{@tmp_dir}/#{platf}/#{@name}"
76
+
77
+ # cleanup and clobbering
78
+ CLEAN.include(tmp_path)
79
+ CLOBBER.include("#{@lib_dir}/#{binary}")
80
+ CLOBBER.include("#{@tmp_dir}")
81
+
53
82
  # directories we need
54
83
  directory tmp_path
55
- directory @lib_dir
84
+ directory lib_dir
56
85
 
57
- # platform specific temp folder should be on the cleaning
58
- CLEAN.include(tmp_path)
86
+ # copy binary from temporary location to final lib
87
+ # tmp/extension_name/extension_name.{so,bundle} => lib/
88
+ task "copy:#{@name}:#{platf}" => [lib_dir, "#{tmp_path}/#{binary}"] do
89
+ cp "#{tmp_path}/#{binary}", "#{@lib_dir}/#{binary}"
90
+ end
91
+
92
+ # binary in temporary folder depends on makefile and source files
93
+ # tmp/extension_name/extension_name.{so,bundle}
94
+ file "#{tmp_path}/#{binary}" => ["#{tmp_path}/Makefile"] + source_files do
95
+ chdir tmp_path do
96
+ sh make
97
+ end
98
+ end
59
99
 
60
100
  # makefile depends of tmp_dir and config_script
61
101
  # tmp/extension_name/Makefile
62
- file makefile => [tmp_path, extconf] do
102
+ file "#{tmp_path}/Makefile" => [tmp_path, extconf] do |t|
103
+ options = @config_options.dup
104
+
105
+ # rbconfig.rb will be present if we are cross compiling
106
+ if t.prerequisites.include?("#{tmp_path}/rbconfig.rb") then
107
+ options.push(*@cross_config_options)
108
+ end
109
+
63
110
  parent = Dir.pwd
64
- Dir.chdir tmp_path do
111
+ chdir tmp_path do
65
112
  # FIXME: Rake is broken for multiple arguments system() calls.
66
113
  # Add current directory to the search path of Ruby
67
114
  # Also, include additional parameters supplied.
68
- ruby ['-I.', File.join(parent, extconf), *@additional_options].join(' ')
115
+ ruby ['-I.', File.join(parent, extconf), *options].join(' ')
69
116
  end
70
117
  end
71
118
 
72
- # binary in temporary folder depends on makefile and source files
73
- # tmp/extension_name/extension_name.{so,bundle}
74
- file tmp_binary => [makefile] + source_files do
75
- Dir.chdir tmp_path do
76
- sh make
77
- end
119
+ # compile tasks
120
+ unless Rake::Task.task_defined?('compile') then
121
+ desc "Compile all the extensions"
122
+ task "compile"
78
123
  end
79
124
 
80
- # copy binary from temporary location to final lib
81
- # tmp/extension_name/extension_name.{so,bundle} => lib/
82
- file lib_binary => [lib_path, tmp_binary] do
83
- cp tmp_binary, lib_binary
125
+ # compile:name
126
+ unless Rake::Task.task_defined?("compile:#{@name}") then
127
+ desc "Compile #{@name}"
128
+ task "compile:#{@name}"
84
129
  end
85
130
 
86
- # clobbering should remove the binaries from lib_path
87
- CLOBBER.include(lib_binary)
131
+ # Allow segmented compilation by platfrom (open door for 'cross compile')
132
+ task "compile:#{@name}:#{platf}" => ["copy:#{@name}:#{platf}"]
133
+ task "compile:#{platf}" => ["compile:#{@name}:#{platf}"]
88
134
 
89
- # we should also clobber the tmp folder
90
- CLOBBER.include(@tmp_dir)
135
+ # Only add this extension to the compile chain if current
136
+ # platform matches the indicated one.
137
+ if platf == RUBY_PLATFORM then
138
+ # ensure file is always copied
139
+ file "#{@lib_dir}/#{binary}" => ["copy:#{name}:#{platf}"]
91
140
 
92
- desc "Compile just the #{@name} extension"
93
- task "compile:#{@name}" => [lib_binary]
94
-
95
- desc "Compile the extension(s)" unless Rake::Task.task_defined?('compile')
96
- task "compile" => ["compile:#{@name}"]
141
+ task "compile:#{@name}" => ["compile:#{@name}:#{platf}"]
142
+ task "compile" => ["compile:#{platf}"]
143
+ end
97
144
  end
98
145
 
99
- def define_native_tasks
100
- # only gems with 'ruby' platforms are allowed to define native tasks
101
- return unless @gem_spec.platform == 'ruby'
146
+ def define_native_tasks(for_platform = nil)
147
+ platf = for_platform || platform
102
148
 
103
- require 'rake/gempackagetask' unless defined?(Rake::GemPackageTask)
149
+ # tmp_path
150
+ tmp_path = "#{@tmp_dir}/#{platf}/#{@name}"
104
151
 
105
152
  # create 'native:gem_name' and chain it to 'native' task
106
- native_task_for(@gem_spec)
107
-
108
- # hook the binary to the prerequisites for this task
109
- task native_task_gem => [lib_binary]
110
- end
111
-
112
- def makefile
113
- "#{tmp_path}/Makefile"
114
- end
153
+ spec = @gem_spec.dup
154
+
155
+ unless Rake::Task.task_defined?("native:#{@gem_spec.name}:#{platf}")
156
+ task "native:#{@gem_spec.name}:#{platf}" do |t|
157
+ # adjust to specified platform
158
+ spec.platform = platf
159
+
160
+ # clear the extensions defined in the specs
161
+ spec.extensions.clear
162
+
163
+ # add the binaries that this task depends on
164
+ # ensure the files get properly copied to lib_dir
165
+ ext_files = t.prerequisites.map { |ext| "#{@lib_dir}/#{File.basename(ext)}" }
166
+ ext_files.each do |ext|
167
+ unless Rake::Task.task_defined?("#{@lib_dir}/#{File.basename(ext)}") then
168
+ # strip out path and .so/.bundle
169
+ file "#{@lib_dir}/#{File.basename(ext)}" => ["copy:#{File.basename(ext).ext('')}:#{platf}"]
170
+ end
171
+ end
172
+
173
+ # include the files in the gem specification
174
+ spec.files += ext_files
175
+
176
+ # Generate a package for this gem
177
+ gem_package = Rake::GemPackageTask.new(spec) do |pkg|
178
+ pkg.need_zip = false
179
+ pkg.need_tar = false
180
+ end
181
+
182
+ # ensure the binaries are copied
183
+ task "#{gem_package.package_dir}/#{gem_package.gem_file}" => ["copy:#{@name}:#{platf}"]
184
+ end
185
+ end
115
186
 
116
- def extconf
117
- "#{ext_path}/#{@config_script}"
118
- end
187
+ # add binaries to the dependency chain
188
+ task "native:#{@gem_spec.name}:#{platf}" => ["#{tmp_path}/#{binary}"]
119
189
 
120
- def tmp_path
121
- File.join(@tmp_dir, platform, @name)
122
- end
190
+ # Allow segmented packaging by platfrom (open door for 'cross compile')
191
+ task "native:#{platf}" => ["native:#{@gem_spec.name}:#{platf}"]
123
192
 
124
- def ext_path
125
- File.join(@ext_dir, @name)
193
+ # Only add this extension to the compile chain if current
194
+ # platform matches the indicated one.
195
+ if platf == RUBY_PLATFORM then
196
+ task "native:#{@gem_spec.name}" => ["native:#{@gem_spec.name}:#{platf}"]
197
+ task "native" => ["native:#{platf}"]
198
+ end
126
199
  end
127
200
 
128
- def lib_path
129
- @lib_dir
130
- end
201
+ def define_cross_platform_tasks
202
+ config_path = File.expand_path("~/.rake-compiler/config.yml")
203
+ major_ver = RUBY_VERSION.match(/(\d+.\d+)/)[1]
131
204
 
132
- def make
133
- RUBY_PLATFORM =~ /mswin/ ? 'nmake' : 'make'
134
- end
205
+ # warn the user about the need of configuration to use cross compilation.
206
+ unless File.exist?(config_path)
207
+ warn "rake-compiler must be configured first to enable cross-compilation"
208
+ return
209
+ end
135
210
 
136
- def binary
137
- "#{@name}.#{RbConfig::CONFIG['DLEXT']}"
138
- end
211
+ config_file = YAML.load_file(config_path)
139
212
 
140
- def source_files
141
- @source_files ||= FileList["#{ext_path}/#{@source_pattern}"]
142
- end
213
+ # tmp_path
214
+ tmp_path = "#{@tmp_dir}/#{cross_platform}/#{@name}"
143
215
 
144
- def tmp_binary
145
- "#{tmp_path}/#{binary}"
146
- end
216
+ unless rbconfig_file = config_file["rbconfig-#{major_ver}"] then
217
+ fail "no configuration section for this version of Ruby (rbconfig-#{major_ver})"
218
+ end
147
219
 
148
- def lib_binary
149
- "#{lib_path}/#{binary}"
150
- end
220
+ # define compilation tasks for cross platfrom!
221
+ define_compile_tasks(cross_platform)
151
222
 
152
- def native_task_gem
153
- "native:#{@gem_spec.name}"
154
- end
223
+ # chain rbconfig.rb to Makefile generation
224
+ file "#{tmp_path}/Makefile" => ["#{tmp_path}/rbconfig.rb"]
155
225
 
156
- def native_task_for(gem_spec)
157
- return if Rake::Task.task_defined?(native_task_gem)
226
+ # copy the file from the cross-ruby location
227
+ file "#{tmp_path}/rbconfig.rb" => [rbconfig_file] do |t|
228
+ cp t.prerequisites.first, t.name
229
+ end
158
230
 
159
- spec = gem_spec.dup
231
+ # now define native tasks for cross compiled files
232
+ define_native_tasks(cross_platform) if @gem_spec && @gem_spec.platform == 'ruby'
160
233
 
161
- task native_task_gem do |t|
162
- # adjust to current platform
163
- spec.platform = (@platform || Gem::Platform::CURRENT)
234
+ # create cross task
235
+ task 'cross' do
236
+ # clear compile dependencies
237
+ Rake::Task['compile'].prerequisites.clear
164
238
 
165
- # clear the extensions defined in the specs
166
- spec.extensions.clear
239
+ # chain the cross platform ones
240
+ task 'compile' => ["compile:#{cross_platform}"]
167
241
 
168
- # add the binary dependencies of this task
169
- spec.files += t.prerequisites
242
+ # clear lib/binary dependencies and trigger cross platform ones
243
+ Rake::Task["#{@lib_dir}/#{binary}"].prerequisites.clear
244
+ file "#{@lib_dir}/#{binary}" => ["copy:#{@name}:#{cross_platform}"]
170
245
 
171
- # Generate a package for this gem
172
- gem_package = Rake::GemPackageTask.new(spec) do |pkg|
173
- pkg.need_zip = false
174
- pkg.need_tar = false
246
+ # if everything for native task is in place
247
+ if @gem_spec && @gem_spec.platform == 'ruby' then
248
+ Rake::Task['native'].prerequisites.clear
249
+ task 'native' => ["native:#{cross_platform}"]
175
250
  end
176
251
  end
252
+ end
177
253
 
178
- # add this native task to the list
179
- task "native" => [native_task_gem]
254
+ def extconf
255
+ "#{@ext_dir}/#{@name}/#{@config_script}"
256
+ end
257
+
258
+ def make
259
+ RUBY_PLATFORM =~ /mswin/ ? 'nmake' : 'make'
260
+ end
261
+
262
+ def binary
263
+ "#{@name}.#{RbConfig::CONFIG['DLEXT']}"
264
+ end
265
+
266
+ def source_files
267
+ @source_files ||= FileList["#{@ext_dir}/#{@name}/#{@source_pattern}"]
180
268
  end
181
269
  end
182
270
  end
@@ -80,13 +80,25 @@ describe Rake::ExtensionTask do
80
80
  @ext.source_pattern.should == "*.c"
81
81
  end
82
82
 
83
- it 'should have no additional options preset to delegate' do
84
- @ext.additional_options.should be_empty
83
+ it 'should have no configuration options preset to delegate' do
84
+ @ext.config_options.should be_empty
85
85
  end
86
86
 
87
87
  it 'should default to current platform' do
88
88
  @ext.platform.should == RUBY_PLATFORM
89
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
90
102
  end
91
103
 
92
104
  describe '(tasks)' do
@@ -109,8 +121,8 @@ describe Rake::ExtensionTask do
109
121
  Rake::Task.task_defined?('compile').should be_true
110
122
  end
111
123
 
112
- it "should depend on 'compile:extension_one'" do
113
- Rake::Task['compile'].prerequisites.should include('compile:extension_one')
124
+ it "should depend on 'compile:{platform}'" do
125
+ Rake::Task['compile'].prerequisites.should include("compile:#{@platform}")
114
126
  end
115
127
  end
116
128
 
@@ -119,8 +131,8 @@ describe Rake::ExtensionTask do
119
131
  Rake::Task.task_defined?('compile:extension_one').should be_true
120
132
  end
121
133
 
122
- it "should depend on 'lib/extension_one.{so,bundle}'" do
123
- Rake::Task['compile:extension_one'].prerequisites.should include("lib/#{@ext_bin}")
134
+ it "should depend on 'compile:extension_one:{platform}'" do
135
+ Rake::Task['compile:extension_one'].prerequisites.should include("compile:extension_one:#{@platform}")
124
136
  end
125
137
  end
126
138
 
@@ -129,12 +141,8 @@ describe Rake::ExtensionTask do
129
141
  Rake::Task.task_defined?("lib/#{@ext_bin}").should be_true
130
142
  end
131
143
 
132
- it "should depend on 'lib'" do
133
- Rake::Task["lib/#{@ext_bin}"].prerequisites.should include("lib")
134
- end
135
-
136
- it "should depend on 'tmp/extension_one.{so,bundle}'" do
137
- Rake::Task["lib/#{@ext_bin}"].prerequisites.should include("tmp/#{@platform}/extension_one/#{@ext_bin}")
144
+ it "should depend on 'copy:extension_one:{platform}'" do
145
+ Rake::Task["lib/#{@ext_bin}"].prerequisites.should include("copy:extension_one:#{@platform}")
138
146
  end
139
147
  end
140
148
 
@@ -192,6 +200,7 @@ describe Rake::ExtensionTask do
192
200
  Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"])
193
201
  @spec = mock_gem_spec
194
202
  @ext_bin = ext_bin('extension_one')
203
+ @platform = RUBY_PLATFORM
195
204
  end
196
205
 
197
206
  describe 'native' do
@@ -216,15 +225,93 @@ describe Rake::ExtensionTask do
216
225
  Rake::Task.task_defined?('native').should be_false
217
226
  end
218
227
 
219
- it 'should depend on gem specific native tasks' do
228
+ it 'should depend on platform specific native tasks' do
220
229
  Rake::ExtensionTask.new('extension_one', @spec)
221
- Rake::Task["native"].prerequisites.should include("native:my_gem")
230
+ Rake::Task["native"].prerequisites.should include("native:#{@platform}")
222
231
  end
223
232
 
224
- describe 'native:my_gem' do
233
+ describe 'native:my_gem:{platform}' do
225
234
  it 'should depend on binary extension' do
226
235
  Rake::ExtensionTask.new('extension_one', @spec)
227
- Rake::Task["native:my_gem"].prerequisites.should include("lib/#{@ext_bin}")
236
+ Rake::Task["native:my_gem:#{@platform}"].prerequisites.should include("tmp/#{@platform}/extension_one/#{@ext_bin}")
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '(cross platform tasks)' do
243
+ before :each do
244
+ File.stub!(:exist?).and_return(true)
245
+ YAML.stub!(:load_file).and_return(mock_config_yml)
246
+ Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"])
247
+ @spec = mock_gem_spec
248
+ @config_file = File.expand_path("~/.rake-compiler/config.yml")
249
+ @major_ver = RUBY_VERSION.match(/(\d+.\d+)/)[1]
250
+ @config_path = mock_config_yml["rbconfig-#{@major_ver}"]
251
+ end
252
+
253
+ it 'should not generate an error if no rake-compiler configuration exist' do
254
+ File.should_receive(:exist?).with(@config_file).and_return(false)
255
+ lambda {
256
+ Rake::ExtensionTask.new('extension_one') do |ext|
257
+ ext.cross_compile = true
258
+ end
259
+ }.should_not raise_error(RuntimeError)
260
+ end
261
+
262
+ it 'should parse the config file using YAML' do
263
+ YAML.should_receive(:load_file).with(@config_file).and_return(mock_config_yml)
264
+ Rake::ExtensionTask.new('extension_one') do |ext|
265
+ ext.cross_compile = true
266
+ end
267
+ end
268
+
269
+ it 'should fail if no section of config file defines running version of ruby' do
270
+ config = mock(Hash)
271
+ config.should_receive(:[]).with("rbconfig-#{@major_ver}").and_return(nil)
272
+ YAML.stub!(:load_file).and_return(config)
273
+ lambda {
274
+ Rake::ExtensionTask.new('extension_one') do |ext|
275
+ ext.cross_compile = true
276
+ end
277
+ }.should raise_error(RuntimeError, /no configuration section for this version of Ruby/)
278
+ end
279
+
280
+ describe "(cross for 'universal-unknown' platform)" do
281
+ before :each do
282
+ @ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext|
283
+ ext.cross_compile = true
284
+ ext.cross_platform = 'universal-unknown'
285
+ end
286
+ end
287
+
288
+ describe 'rbconfig' do
289
+ it 'should chain rbconfig tasks to Makefile generation' do
290
+ Rake::Task['tmp/universal-unknown/extension_one/Makefile'].prerequisites.should include('tmp/universal-unknown/extension_one/rbconfig.rb')
291
+ end
292
+
293
+ it 'should take rbconfig from rake-compiler configuration' do
294
+ Rake::Task['tmp/universal-unknown/extension_one/rbconfig.rb'].prerequisites.should include(@config_path)
295
+ end
296
+ end
297
+
298
+ describe 'compile:universal-unknown' do
299
+ it "should be defined" do
300
+ Rake::Task.task_defined?('compile:universal-unknown').should be_true
301
+ end
302
+
303
+ it "should depend on 'compile:extension_one:universal-unknown'" do
304
+ Rake::Task['compile:universal-unknown'].prerequisites.should include('compile:extension_one:universal-unknown')
305
+ end
306
+ end
307
+
308
+ describe 'native:universal-unknown' do
309
+ it "should be defined" do
310
+ Rake::Task.task_defined?('native:universal-unknown').should be_true
311
+ end
312
+
313
+ it "should depend on 'native:my_gem:universal-unknown'" do
314
+ Rake::Task['native:universal-unknown'].prerequisites.should include('native:my_gem:universal-unknown')
228
315
  end
229
316
  end
230
317
  end
@@ -242,4 +329,10 @@ describe Rake::ExtensionTask do
242
329
  )
243
330
  end
244
331
 
332
+ def mock_config_yml
333
+ {
334
+ 'rbconfig-1.8' => '/some/path/version/1.8/to/rbconfig.rb',
335
+ 'rbconfig-1.9' => '/some/path/version/1.9/to/rbconfig.rb'
336
+ }
337
+ end
245
338
  end
data/tasks/rubygems.rake CHANGED
@@ -3,7 +3,7 @@ require 'rake/gempackagetask'
3
3
  spec = Gem::Specification.new do |s|
4
4
  # basic information
5
5
  s.name = "rake-compiler"
6
- s.version = "0.1.1"
6
+ s.version = "0.2.0"
7
7
  s.platform = Gem::Platform::RUBY
8
8
 
9
9
  # description and details
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: luislavena-rake-compiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luis Lavena
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-27 18:00:00 -08:00
12
+ date: 2008-11-28 18:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -36,8 +36,11 @@ extra_rdoc_files:
36
36
  - LICENSE.txt
37
37
  files:
38
38
  - features/compile.feature
39
+ - features/cross-compile.feature
40
+ - features/cross-package.feature
39
41
  - features/package.feature
40
42
  - features/step_definitions/compilation.rb
43
+ - features/step_definitions/cross_compilation.rb
41
44
  - features/step_definitions/execution.rb
42
45
  - features/step_definitions/folders.rb
43
46
  - features/step_definitions/gem.rb