diff options
author | Luis Lavena <luislavena@gmail.com> | 2009-04-25 12:02:17 -0300 |
---|---|---|
committer | Luis Lavena <luislavena@gmail.com> | 2009-04-25 12:02:17 -0300 |
commit | 166800107d24fa41474c1dc0a93df238f16563df (patch) | |
tree | 40cb32fa22e9b8ec74d8abb6a336b446d4dd00b8 | |
parent | 622336ffab97769a99627f468208b4e79d4f1d7f (diff) | |
download | rake-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.feature | 15 | ||||
-rw-r--r-- | features/step_definitions/compilation.rb | 11 | ||||
-rw-r--r-- | features/support/file_template_helpers.rb | 10 | ||||
-rw-r--r-- | features/support/generator_helpers.rb | 15 | ||||
-rw-r--r-- | lib/rake/extensiontask.rb | 43 | ||||
-rw-r--r-- | spec/lib/rake/extensiontask_spec.rb | 12 | ||||
-rw-r--r-- | spec/spec_helper.rb | 2 |
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 |