summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Lavena <luislavena@gmail.com>2009-04-25 12:02:17 -0300
committerLuis Lavena <luislavena@gmail.com>2009-04-25 12:02:17 -0300
commit166800107d24fa41474c1dc0a93df238f16563df (patch)
tree40cb32fa22e9b8ec74d8abb6a336b446d4dd00b8
parent622336ffab97769a99627f468208b4e79d4f1d7f (diff)
downloadrake-compiler-166800107d24fa41474c1dc0a93df238f16563df.tar.gz
Allow generation of multiple gems for Windows
- This allows build gems for both VC6 and MinGW builts of Ruby. Rake::ExtensionTask.new('my_extension', GEM_SPEC) do |ext| ext.cross_compile = true ext.cross_platform = ['i386-mswin32', 'i386-mingw32'] end This is highly experimental and exposed the need to refactor ExtensionTask internals. Right now it fires the compilation process twice, which is suboptimal.
-rw-r--r--features/cross-package-multi.feature15
-rw-r--r--features/step_definitions/compilation.rb11
-rw-r--r--features/support/file_template_helpers.rb10
-rw-r--r--features/support/generator_helpers.rb15
-rw-r--r--lib/rake/extensiontask.rb43
-rw-r--r--spec/lib/rake/extensiontask_spec.rb12
-rw-r--r--spec/spec_helper.rb2
7 files changed, 95 insertions, 13 deletions
diff --git a/features/cross-package-multi.feature b/features/cross-package-multi.feature
new file mode 100644
index 0000000..a40aa33
--- /dev/null
+++ b/features/cross-package-multi.feature
@@ -0,0 +1,15 @@
+Feature: Generate multiple Windows gems from Linux
+
+ In order to keep compatibility with versions of Ruby on Windows
+ As a Gem developer on Linux
+ I want to build binary gems for One-Click Installer (old and new versions)
+
+ Scenario: package multiple gems for Windows
+ Given that my gem source is all in place to target two platforms
+ And I'm running a POSIX operating system
+ And I've installed cross compile toolchain
+ And I've already successfully executed rake task 'cross compile'
+ When rake task 'cross native gem' is invoked
+ Then rake task 'cross native gem' succeeded
+ And gem for platform 'x86-mswin32' get generated
+ And gem for platform 'x86-mingw32' get generated
diff --git a/features/step_definitions/compilation.rb b/features/step_definitions/compilation.rb
index 2056ad9..35e72dd 100644
--- a/features/step_definitions/compilation.rb
+++ b/features/step_definitions/compilation.rb
@@ -8,6 +8,11 @@ Given /^a extension cross-compilable '(.*)'$/ do |extension_name|
generate_source_code_for extension_name
end
+Given /^a extension '(.*)' multi cross\-compilable$/ do |extension_name|
+ generate_multi_cross_compile_extension_task_for extension_name
+ generate_source_code_for extension_name
+end
+
Given /^a extension '(.*)' with forced platform '(.*)'$/ do |extension_name, forced_platform|
generate_extension_task_for extension_name, forced_platform
generate_source_code_for extension_name
@@ -24,6 +29,12 @@ Given /^that my gem source is all in place$/ do
Given "a extension cross-compilable 'extension_one'"
end
+Given /^that my gem source is all in place to target two platforms$/ do
+ Given "a safe project directory"
+ Given "a gem named 'gem_abc'"
+ Given "a extension 'extension_one' multi cross-compilable"
+end
+
Given /^not changed any file since$/ do
# don't do anything, that's the purpose of this step!
end
diff --git a/features/support/file_template_helpers.rb b/features/support/file_template_helpers.rb
index f4ea86c..76bed50 100644
--- a/features/support/file_template_helpers.rb
+++ b/features/support/file_template_helpers.rb
@@ -65,6 +65,16 @@ end
EOF
end
+ def template_rake_extension_multi_cross_compile(extension_name)
+ <<-EOF
+require 'rake/extensiontask'
+Rake::ExtensionTask.new("#{extension_name}", SPEC) do |ext|
+ ext.cross_compile = true
+ ext.cross_platform = ['i386-mswin32', 'i386-mingw32']
+end
+EOF
+ end
+
def template_extconf(extension_name)
<<-EOF
require 'mkmf'
diff --git a/features/support/generator_helpers.rb b/features/support/generator_helpers.rb
index 2910781..c0a8e01 100644
--- a/features/support/generator_helpers.rb
+++ b/features/support/generator_helpers.rb
@@ -60,6 +60,21 @@ module GeneratorHelpers
end
end
+ def generate_multi_cross_compile_extension_task_for(extension_name)
+ # create folder structure
+ FileUtils.mkdir_p "ext/#{extension_name}"
+
+ return if File.exist?("tasks/#{extension_name}.rake")
+
+ # create specific extension rakefile
+ # Building a gem?
+ if File.exist?("tasks/gem.rake") then
+ File.open("tasks/gem.rake", 'a+') do |ext_in_gem|
+ ext_in_gem.puts template_rake_extension_multi_cross_compile(extension_name)
+ end
+ end
+ end
+
def generate_source_code_for(extension_name)
# source C file
File.open("ext/#{extension_name}/source.c", 'w') do |c|
diff --git a/lib/rake/extensiontask.rb b/lib/rake/extensiontask.rb
index fb9315e..770d776 100644
--- a/lib/rake/extensiontask.rb
+++ b/lib/rake/extensiontask.rb
@@ -62,8 +62,13 @@ module Rake
define_native_tasks if @gem_spec && @gem_spec.platform == 'ruby'
# only define cross platform functionality when enabled
- # FIXME: there is no value for having this on Windows or JRuby
- define_cross_platform_tasks if @cross_compile
+ return unless @cross_compile
+
+ if cross_platform.is_a?(Array) then
+ cross_platform.each { |platf| define_cross_platform_tasks(platf) }
+ else
+ define_cross_platform_tasks(cross_platform)
+ end
end
private
@@ -218,7 +223,7 @@ module Rake
end
end
- def define_cross_platform_tasks
+ def define_cross_platform_tasks(for_platform)
config_path = File.expand_path("~/.rake-compiler/config.yml")
ruby_ver = ENV['RUBY_CC_VERSION'] || RUBY_VERSION
@@ -231,7 +236,7 @@ module Rake
config_file = YAML.load_file(config_path)
# tmp_path
- tmp_path = "#{@tmp_dir}/#{cross_platform}/#{@name}"
+ tmp_path = "#{@tmp_dir}/#{for_platform}/#{@name}"
unless rbconfig_file = config_file["rbconfig-#{ruby_ver}"] then
warn "no configuration section for specified version of Ruby (rbconfig-#{ruby_ver})"
@@ -239,7 +244,7 @@ module Rake
end
# define compilation tasks for cross platfrom!
- define_compile_tasks(cross_platform)
+ define_compile_tasks(for_platform)
# chain fake.rb and rbconfig.rb to Makefile generation
file "#{tmp_path}/Makefile" => ["#{tmp_path}/fake.rb", "#{tmp_path}/rbconfig.rb"]
@@ -257,27 +262,31 @@ module Rake
end
# now define native tasks for cross compiled files
- define_native_tasks(cross_platform) if @gem_spec && @gem_spec.platform == 'ruby'
+ define_native_tasks(for_platform) if @gem_spec && @gem_spec.platform == 'ruby'
# create cross task
task 'cross' do
# clear compile dependencies
- Rake::Task['compile'].prerequisites.clear
+ Rake::Task['compile'].prerequisites.reject! { |t| !compiles_cross_platform.include?(t) }
# chain the cross platform ones
- task 'compile' => ["compile:#{cross_platform}"]
+ task 'compile' => ["compile:#{for_platform}"]
# clear lib/binary dependencies and trigger cross platform ones
# check if lib/binary is defined (damn bundle versus so versus dll)
- if Rake::Task.task_defined?("#{@lib_dir}/#{binary(cross_platform)}") then
- Rake::Task["#{@lib_dir}/#{binary(cross_platform)}"].prerequisites.clear
+ if Rake::Task.task_defined?("#{@lib_dir}/#{binary(for_platform)}") then
+ Rake::Task["#{@lib_dir}/#{binary(for_platform)}"].prerequisites.clear
end
- file "#{@lib_dir}/#{binary(cross_platform)}" => ["copy:#{@name}:#{cross_platform}"]
+
+ # FIXME: targeting multiple platforms copies the file twice
+ file "#{@lib_dir}/#{binary(for_platform)}" => ["copy:#{@name}:#{for_platform}"]
# if everything for native task is in place
if @gem_spec && @gem_spec.platform == 'ruby' then
- Rake::Task['native'].prerequisites.clear
- task 'native' => ["native:#{cross_platform}"]
+ # double check: only cross platform native tasks should be here
+ # FIXME: Sooo brittle
+ Rake::Task['native'].prerequisites.reject! { |t| !natives_cross_platform.include?(t) }
+ task 'native' => ["native:#{for_platform}"]
end
end
end
@@ -306,6 +315,14 @@ module Rake
@source_files ||= FileList["#{@ext_dir}/#{@source_pattern}"]
end
+ def compiles_cross_platform
+ [*@cross_platform].map { |p| "compile:#{p}" }
+ end
+
+ def natives_cross_platform
+ [*@cross_platform].map { |p| "native:#{p}" }
+ end
+
def fake_rb(version)
<<-FAKE_RB
class Object
diff --git a/spec/lib/rake/extensiontask_spec.rb b/spec/lib/rake/extensiontask_spec.rb
index 0d72592..15c35d7 100644
--- a/spec/lib/rake/extensiontask_spec.rb
+++ b/spec/lib/rake/extensiontask_spec.rb
@@ -355,6 +355,18 @@ describe Rake::ExtensionTask do
end
end
end
+
+ context '(cross for multiple platforms)' do
+ it 'should define task for each supplied platform' do
+ @ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext|
+ ext.cross_compile = true
+ ext.cross_platform = ['universal-known', 'universal-unknown']
+ end
+
+ Rake::Task.should have_defined('compile:universal-known')
+ Rake::Task.should have_defined('compile:universal-unknown')
+ end
+ end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9c3c7bf..c534666 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -9,5 +9,7 @@ require 'spec'
require File.expand_path(File.join(File.dirname(__FILE__), 'support/capture_output_helper'))
Spec::Runner.configure do |config|
+ config.predicate_matchers[:have_defined] = :task_defined?
+
include CaptureOutputHelper
end