lib/rake/extensiontask.rb in luislavena-rake-compiler-0.5.0 vs lib/rake/extensiontask.rb in luislavena-rake-compiler-0.6.0
- old
+ new
@@ -70,30 +70,33 @@
define_cross_platform_tasks(cross_platform)
end
end
private
- def define_compile_tasks(for_platform = nil)
+ def define_compile_tasks(for_platform = nil, ruby_ver = RUBY_VERSION)
# platform usage
platf = for_platform || platform
+ # lib_path
+ lib_path = lib_dir
+
# tmp_path
- tmp_path = "#{@tmp_dir}/#{platf}/#{@name}"
+ tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}"
# cleanup and clobbering
CLEAN.include(tmp_path)
- CLOBBER.include("#{@lib_dir}/#{binary(platf)}")
+ CLOBBER.include("#{lib_path}/#{binary(platf)}")
CLOBBER.include("#{@tmp_dir}")
# directories we need
directory tmp_path
directory lib_dir
# copy binary from temporary location to final lib
# tmp/extension_name/extension_name.{so,bundle} => lib/
- task "copy:#{@name}:#{platf}" => [lib_dir, "#{tmp_path}/#{binary(platf)}"] do
- cp "#{tmp_path}/#{binary(platf)}", "#{@lib_dir}/#{binary(platf)}"
+ task "copy:#{@name}:#{platf}:#{ruby_ver}" => [lib_path, "#{tmp_path}/#{binary(platf)}"] do
+ cp "#{tmp_path}/#{binary(platf)}", "#{lib_path}/#{binary(platf)}"
end
# binary in temporary folder depends on makefile and source files
# tmp/extension_name/extension_name.{so,bundle}
file "#{tmp_path}/#{binary(platf)}" => ["#{tmp_path}/Makefile"] + source_files do
@@ -145,30 +148,33 @@
desc "Compile #{@name}"
task "compile:#{@name}"
end
# Allow segmented compilation by platform (open door for 'cross compile')
- task "compile:#{@name}:#{platf}" => ["copy:#{@name}:#{platf}"]
+ task "compile:#{@name}:#{platf}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"]
task "compile:#{platf}" => ["compile:#{@name}:#{platf}"]
# Only add this extension to the compile chain if current
# platform matches the indicated one.
if platf == RUBY_PLATFORM then
# ensure file is always copied
- file "#{@lib_dir}/#{binary(platf)}" => ["copy:#{name}:#{platf}"]
+ file "#{lib_path}/#{binary(platf)}" => ["copy:#{name}:#{platf}:#{ruby_ver}"]
task "compile:#{@name}" => ["compile:#{@name}:#{platf}"]
task "compile" => ["compile:#{platf}"]
end
end
- def define_native_tasks(for_platform = nil)
+ def define_native_tasks(for_platform = nil, ruby_ver = RUBY_VERSION)
platf = for_platform || platform
# tmp_path
- tmp_path = "#{@tmp_dir}/#{platf}/#{@name}"
+ tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}"
+ # lib_path
+ lib_path = lib_dir
+
# create 'native:gem_name' and chain it to 'native' task
unless Rake::Task.task_defined?("native:#{@gem_spec.name}:#{platf}")
task "native:#{@gem_spec.name}:#{platf}" do |t|
# FIXME: truly duplicate the Gem::Specification
# workaround the lack of #dup for Gem::Specification
@@ -179,41 +185,36 @@
# clear the extensions defined in the specs
spec.extensions.clear
# add the binaries that this task depends on
- # ensure the files get properly copied to lib_dir
- ext_files = t.prerequisites.map { |ext| "#{@lib_dir}/#{File.basename(ext)}" }
- ext_files.each do |ext|
- unless Rake::Task.task_defined?("#{@lib_dir}/#{File.basename(ext)}") then
- # strip out path and .so/.bundle
- file "#{@lib_dir}/#{File.basename(ext)}" => ["copy:#{File.basename(ext).ext('')}:#{platf}"]
- end
+ ext_files = []
+
+ # go through native prerequisites and grab the real extension files from there
+ t.prerequisites.each do |ext|
+ ext_files << ext
end
# include the files in the gem specification
spec.files += ext_files
- # Make sure that the required ruby version matches the ruby version
- # we've used for cross compiling:
- target_version = RUBY_VERSION =~ /^1.8/ ? '1.8.6' : '1.9.0'
- spec.required_ruby_version = "~> #{target_version}"
-
# Generate a package for this gem
gem_package = Rake::GemPackageTask.new(spec) do |pkg|
pkg.need_zip = false
pkg.need_tar = false
end
-
- # ensure the binaries are copied
- task "#{gem_package.package_dir}/#{gem_package.gem_file}" => ["copy:#{@name}:#{platf}"]
end
end
# add binaries to the dependency chain
- task "native:#{@gem_spec.name}:#{platf}" => ["#{tmp_path}/#{binary(platf)}"]
+ task "native:#{@gem_spec.name}:#{platf}" => ["#{lib_path}/#{binary(platf)}"]
+ # ensure the extension get copied
+ unless Rake::Task.task_defined?("#{lib_path}/#{binary(platf)}") then
+ file "#{lib_path}/#{binary(platf)}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"]
+ end
+
# Allow segmented packaging by platfrom (open door for 'cross compile')
task "native:#{platf}" => ["native:#{@gem_spec.name}:#{platf}"]
# Only add this extension to the compile chain if current
# platform matches the indicated one.
@@ -222,49 +223,87 @@
task "native" => ["native:#{platf}"]
end
end
def define_cross_platform_tasks(for_platform)
+ if ruby_vers = ENV['RUBY_CC_VERSION']
+ ruby_vers = ENV['RUBY_CC_VERSION'].split(File::PATH_SEPARATOR)
+ else
+ ruby_vers = [RUBY_VERSION]
+ end
+
+ multi = (ruby_vers.size > 1) ? true : false
+
+ ruby_vers.each do |version|
+ # save original lib_dir
+ orig_lib_dir = @lib_dir
+
+ # tweak lib directory only when targeting multiple versions
+ if multi then
+ version =~ /(\d+.\d+)/
+ @lib_dir = "#{@lib_dir}/#{$1}"
+ end
+
+ define_cross_platform_tasks_with_version(for_platform, version)
+
+ # restore lib_dir
+ @lib_dir = orig_lib_dir
+ end
+ end
+
+ def define_cross_platform_tasks_with_version(for_platform, ruby_ver)
config_path = File.expand_path("~/.rake-compiler/config.yml")
- ruby_ver = ENV['RUBY_CC_VERSION'] || RUBY_VERSION
# warn the user about the need of configuration to use cross compilation.
unless File.exist?(config_path)
warn "rake-compiler must be configured first to enable cross-compilation"
return
end
config_file = YAML.load_file(config_path)
# tmp_path
- tmp_path = "#{@tmp_dir}/#{for_platform}/#{@name}"
+ tmp_path = "#{@tmp_dir}/#{for_platform}/#{@name}/#{ruby_ver}"
+ # lib_path
+ lib_path = lib_dir
+
unless rbconfig_file = config_file["rbconfig-#{ruby_ver}"] then
warn "no configuration section for specified version of Ruby (rbconfig-#{ruby_ver})"
return
end
+ # mkmf
+ mkmf_file = File.expand_path(File.join(File.dirname(rbconfig_file), '..', 'mkmf.rb'))
+
# define compilation tasks for cross platfrom!
- define_compile_tasks(for_platform)
+ define_compile_tasks(for_platform, ruby_ver)
- # chain fake.rb and rbconfig.rb to Makefile generation
- file "#{tmp_path}/Makefile" => ["#{tmp_path}/fake.rb", "#{tmp_path}/rbconfig.rb"]
+ # chain fake.rb, rbconfig.rb and mkmf.rb to Makefile generation
+ file "#{tmp_path}/Makefile" => ["#{tmp_path}/fake.rb",
+ "#{tmp_path}/rbconfig.rb",
+ "#{tmp_path}/mkmf.rb"]
# copy the file from the cross-ruby location
file "#{tmp_path}/rbconfig.rb" => [rbconfig_file] do |t|
cp t.prerequisites.first, t.name
end
+ # copy mkmf from cross-ruby location
+ file "#{tmp_path}/mkmf.rb" => [mkmf_file] do |t|
+ cp t.prerequisites.first, t.name
+ end
+
# genearte fake.rb for different ruby versions
file "#{tmp_path}/fake.rb" do |t|
File.open(t.name, 'w') do |f|
f.write fake_rb(ruby_ver)
end
end
# now define native tasks for cross compiled files
- define_native_tasks(for_platform) if @gem_spec && @gem_spec.platform == 'ruby'
+ define_native_tasks(for_platform, ruby_ver) if @gem_spec && @gem_spec.platform == 'ruby'
# create cross task
task 'cross' do
# clear compile dependencies
Rake::Task['compile'].prerequisites.reject! { |t| !compiles_cross_platform.include?(t) }
@@ -272,15 +311,15 @@
# chain the cross platform ones
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(for_platform)}") then
- Rake::Task["#{@lib_dir}/#{binary(for_platform)}"].prerequisites.clear
+ if Rake::Task.task_defined?("#{lib_path}/#{binary(for_platform)}") then
+ Rake::Task["#{lib_path}/#{binary(for_platform)}"].prerequisites.clear
end
# FIXME: targeting multiple platforms copies the file twice
- file "#{@lib_dir}/#{binary(for_platform)}" => ["copy:#{@name}:#{for_platform}"]
+ file "#{lib_path}/#{binary(for_platform)}" => ["copy:#{@name}:#{for_platform}:#{ruby_ver}"]
# if everything for native task is in place
if @gem_spec && @gem_spec.platform == 'ruby' then
# double check: only cross platform native tasks should be here
# FIXME: Sooo brittle