1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
#--
# Cross-compile ruby, using Rake
#
# This source code is released under the MIT License.
# See LICENSE file for details
#++
#
# This code is inspired and based on notes from the following sites:
#
# http://tenderlovemaking.com/2008/11/21/cross-compiling-ruby-gems-for-win32/
# http://github.com/jbarnette/johnson/tree/master/cross-compile.txt
# http://eigenclass.org/hiki/cross+compiling+rcovrt
#
# This recipe only cleanup the dependency chain and automate it.
# Also opens the door to usage different ruby versions
# for cross-compilation.
#
require 'rake'
require 'rake/clean'
begin
require 'psych'
rescue LoadError
end
require 'yaml'
require "rbconfig"
# load compiler helpers
# add lib directory to the search path
libdir = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
if RUBY_PLATFORM =~ /mingw|mswin/ then
puts "This command is meant to be executed under Linux or OSX, not Windows (is for cross-compilation)"
exit(1)
end
require 'rake/extensioncompiler'
MAKE = ENV['MAKE'] || %w[gmake make].find { |c| system("#{c} -v > /dev/null 2>&1") }
USER_HOME = File.expand_path("~/.rake-compiler")
RUBY_CC_VERSION = "ruby-" << ENV.fetch("VERSION", "1.8.7-p334")
RUBY_SOURCE = ENV['SOURCE']
RUBY_BUILD = RbConfig::CONFIG["host"]
# grab the major "1.8" or "1.9" part of the version number
MAJOR = RUBY_CC_VERSION.match(/.*-(\d.\d).\d/)[1]
# Use Rake::ExtensionCompiler helpers to find the proper host
MINGW_HOST = ENV['HOST'] || Rake::ExtensionCompiler.mingw_host
MINGW_TARGET = MINGW_HOST.gsub('msvc', '')
# define a location where sources will be stored
directory "#{USER_HOME}/sources/#{RUBY_CC_VERSION}"
directory "#{USER_HOME}/builds/#{RUBY_CC_VERSION}"
# clean intermediate files and folders
CLEAN.include("#{USER_HOME}/sources/#{RUBY_CC_VERSION}")
CLEAN.include("#{USER_HOME}/builds/#{RUBY_CC_VERSION}")
# remove the final products and sources
CLOBBER.include("#{USER_HOME}/sources")
CLOBBER.include("#{USER_HOME}/builds")
CLOBBER.include("#{USER_HOME}/ruby/#{RUBY_CC_VERSION}")
CLOBBER.include("#{USER_HOME}/config.yml")
# ruby source file should be stored there
file "#{USER_HOME}/sources/#{RUBY_CC_VERSION}.tar.bz2" => ["#{USER_HOME}/sources"] do |t|
# download the source file using wget or curl
chdir File.dirname(t.name) do
if RUBY_SOURCE
url = RUBY_SOURCE
else
url = "http://ftp.ruby-lang.org/pub/ruby/#{MAJOR}/#{File.basename(t.name)}"
end
sh "wget #{url} || curl -O #{url}"
end
end
# Extract the sources
source_file = RUBY_SOURCE ? RUBY_SOURCE.split('/').last : "#{RUBY_CC_VERSION}.tar.bz2"
file "#{USER_HOME}/sources/#{RUBY_CC_VERSION}" => ["#{USER_HOME}/sources/#{source_file}"] do |t|
chdir File.dirname(t.name) do
t.prerequisites.each { |f| sh "tar xf #{File.basename(f)}" }
end
end
# backup makefile.in
file "#{USER_HOME}/sources/#{RUBY_CC_VERSION}/Makefile.in.bak" => ["#{USER_HOME}/sources/#{RUBY_CC_VERSION}"] do |t|
cp "#{USER_HOME}/sources/#{RUBY_CC_VERSION}/Makefile.in", t.name
end
# correct the makefiles
file "#{USER_HOME}/sources/#{RUBY_CC_VERSION}/Makefile.in" => ["#{USER_HOME}/sources/#{RUBY_CC_VERSION}/Makefile.in.bak"] do |t|
content = File.open(t.name, 'rb') { |f| f.read }
out = ""
content.each_line do |line|
if line =~ /^\s*ALT_SEPARATOR =/
out << "\t\t ALT_SEPARATOR = \"\\\\\\\\\"; \\\n"
else
out << line
end
end
when_writing("Patching Makefile.in") {
File.open(t.name, 'wb') { |f| f.write(out) }
}
end
task :mingw32 do
unless MINGW_HOST then
warn "You need to install mingw32 cross compile functionality to be able to continue."
warn "Please refer to your distribution/package manager documentation about installation."
fail
end
end
# generate the makefile in a clean build location
file "#{USER_HOME}/builds/#{RUBY_CC_VERSION}/Makefile" => ["#{USER_HOME}/builds/#{RUBY_CC_VERSION}",
"#{USER_HOME}/sources/#{RUBY_CC_VERSION}/Makefile.in"] do |t|
options = [
"--host=#{MINGW_HOST}",
"--target=#{MINGW_TARGET}",
"--build=#{RUBY_BUILD}",
'--enable-shared',
'--disable-install-doc',
'--without-tk',
'--without-tcl'
]
# Force Winsock2 for Ruby 1.8, 1.9 defaults to it
options << "--with-winsock2" if MAJOR == "1.8"
chdir File.dirname(t.name) do
prefix = File.expand_path("../../ruby/#{RUBY_CC_VERSION}")
options << "--prefix=#{prefix}"
sh File.expand_path("../../sources/#{RUBY_CC_VERSION}/configure"), *options
end
end
# make
file "#{USER_HOME}/builds/#{RUBY_CC_VERSION}/ruby.exe" => ["#{USER_HOME}/builds/#{RUBY_CC_VERSION}/Makefile"] do |t|
chdir File.dirname(t.prerequisites.first) do
sh MAKE
end
end
# make install
file "#{USER_HOME}/ruby/#{RUBY_CC_VERSION}/bin/ruby.exe" => ["#{USER_HOME}/builds/#{RUBY_CC_VERSION}/ruby.exe"] do |t|
chdir File.dirname(t.prerequisites.first) do
sh "#{MAKE} install"
end
end
task :install => ["#{USER_HOME}/ruby/#{RUBY_CC_VERSION}/bin/ruby.exe"]
desc "Update rake-compiler list of installed Ruby versions"
task 'update-config' do
config_file = "#{USER_HOME}/config.yml"
if File.exist?(config_file) then
puts "Updating #{config_file}"
config = YAML.load_file(config_file)
else
puts "Generating #{config_file}"
config = {}
end
files = Dir.glob("#{USER_HOME}/ruby/*/**/rbconfig.rb").sort
files.each do |rbconfig|
version = rbconfig.match(/.*-(\d.\d.\d)/)[1]
config["rbconfig-#{version}"] = rbconfig
puts "Found Ruby version #{version} (#{rbconfig})"
end
when_writing("Saving changes into #{config_file}") {
File.open(config_file, 'w') do |f|
f.puts config.to_yaml
end
}
end
task :default do
# Force the display of the available tasks when no option is given
Rake.application.options.show_task_pattern = //
Rake.application.display_tasks_and_comments
end
desc "Build #{RUBY_CC_VERSION} suitable for cross-platform development."
task 'cross-ruby' => [:mingw32, :install, 'update-config']
|