# File lib/rake/extensiontask.rb, line 35 35: def binary(platform = nil) 36: if platform == "java" 37: warn_once Compiling a native C extension on JRuby. This is discouraged and a Java extension should be preferred. 38: "#{name}.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}" 39: else 40: super 41: end 42: end
# File lib/rake/extensiontask.rb, line 31 31: def cross_compiling(&block) 32: @cross_compiling = block if block_given? 33: end
# File lib/rake/extensiontask.rb, line 27 27: def cross_platform 28: @cross_platform ||= 'i386-mingw32' 29: end
# File lib/rake/extensiontask.rb, line 47 47: def define 48: if (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby') 49: warn_once WARNING: You're attempting to (cross-)compile C extensions from a platform(#{RUBY_ENGINE}) that does not support native extensions or mkmf.rb.Rerun `rake` under MRI Ruby 1.8.x/1.9.x to cross/native compile. 50: return 51: end 52: 53: super 54: 55: # only gems with 'ruby' platforms are allowed to define native tasks 56: define_native_tasks if !@no_native && (@gem_spec && @gem_spec.platform == 'ruby') 57: 58: # only define cross platform functionality when enabled 59: return unless @cross_compile 60: 61: if cross_platform.is_a?(Array) then 62: cross_platform.each { |platf| define_cross_platform_tasks(platf) } 63: else 64: define_cross_platform_tasks(cross_platform) 65: end 66: end
# File lib/rake/extensiontask.rb, line 17 17: def init(name = nil, gem_spec = nil) 18: super 19: @config_script = 'extconf.rb' 20: @source_pattern = "*.c" 21: @cross_compile = false 22: @cross_config_options = [] 23: @cross_compiling = nil 24: @no_native = false 25: end
# File lib/rake/extensiontask.rb, line 368 368: def compiles_cross_platform 369: [*@cross_platform].map { |p| "compile:#{p}" } 370: end
# File lib/rake/extensiontask.rb, line 73 73: def define_compile_tasks(for_platform = nil, ruby_ver = RUBY_VERSION) 74: # platform usage 75: platf = for_platform || platform 76: 77: # lib_path 78: lib_path = lib_dir 79: 80: # tmp_path 81: tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}" 82: 83: # cleanup and clobbering 84: CLEAN.include(tmp_path) 85: CLOBBER.include("#{lib_path}/#{binary(platf)}") 86: CLOBBER.include("#{@tmp_dir}") 87: 88: # directories we need 89: directory tmp_path 90: directory lib_dir 91: 92: # copy binary from temporary location to final lib 93: # tmp/extension_name/extension_name.{so,bundle} => lib/ 94: task "copy:#{@name}:#{platf}:#{ruby_ver}" => [lib_path, "#{tmp_path}/#{binary(platf)}"] do 95: cp "#{tmp_path}/#{binary(platf)}", "#{lib_path}/#{binary(platf)}" 96: end 97: 98: # binary in temporary folder depends on makefile and source files 99: # tmp/extension_name/extension_name.{so,bundle} 100: file "#{tmp_path}/#{binary(platf)}" => ["#{tmp_path}/Makefile"] + source_files do 101: chdir tmp_path do 102: sh make 103: end 104: end 105: 106: # makefile depends of tmp_dir and config_script 107: # tmp/extension_name/Makefile 108: file "#{tmp_path}/Makefile" => [tmp_path, extconf] do |t| 109: options = @config_options.dup 110: 111: # include current directory 112: cmd = ['-I.'] 113: 114: # if fake.rb is present, add to the command line 115: if t.prerequisites.include?("#{tmp_path}/fake.rb") then 116: cmd << '-rfake' 117: end 118: 119: # build a relative path to extconf script 120: abs_tmp_path = Pathname.new(Dir.pwd) + tmp_path 121: abs_extconf = Pathname.new(Dir.pwd) + extconf 122: 123: # now add the extconf script 124: cmd << abs_extconf.relative_path_from(abs_tmp_path) 125: 126: # rbconfig.rb will be present if we are cross compiling 127: if t.prerequisites.include?("#{tmp_path}/rbconfig.rb") then 128: options.push(*@cross_config_options) 129: end 130: 131: # add options to command 132: cmd.push(*options) 133: 134: chdir tmp_path do 135: # FIXME: Rake is broken for multiple arguments system() calls. 136: # Add current directory to the search path of Ruby 137: # Also, include additional parameters supplied. 138: ruby cmd.join(' ') 139: end 140: end 141: 142: # compile tasks 143: unless Rake::Task.task_defined?('compile') then 144: desc "Compile all the extensions" 145: task "compile" 146: end 147: 148: # compile:name 149: unless Rake::Task.task_defined?("compile:#{@name}") then 150: desc "Compile #{@name}" 151: task "compile:#{@name}" 152: end 153: 154: # Allow segmented compilation by platform (open door for 'cross compile') 155: task "compile:#{@name}:#{platf}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"] 156: task "compile:#{platf}" => ["compile:#{@name}:#{platf}"] 157: 158: # Only add this extension to the compile chain if current 159: # platform matches the indicated one. 160: if platf == RUBY_PLATFORM then 161: # ensure file is always copied 162: file "#{lib_path}/#{binary(platf)}" => ["copy:#{name}:#{platf}:#{ruby_ver}"] 163: 164: task "compile:#{@name}" => ["compile:#{@name}:#{platf}"] 165: task "compile" => ["compile:#{platf}"] 166: end 167: end
# File lib/rake/extensiontask.rb, line 234 234: def define_cross_platform_tasks(for_platform) 235: if ruby_vers = ENV['RUBY_CC_VERSION'] 236: ruby_vers = ENV['RUBY_CC_VERSION'].split(':') 237: else 238: ruby_vers = [RUBY_VERSION] 239: end 240: 241: multi = (ruby_vers.size > 1) ? true : false 242: 243: ruby_vers.each do |version| 244: # save original lib_dir 245: orig_lib_dir = @lib_dir 246: 247: # tweak lib directory only when targeting multiple versions 248: if multi then 249: version =~ /(\d+.\d+)/ 250: @lib_dir = "#{@lib_dir}/#{$1}" 251: end 252: 253: define_cross_platform_tasks_with_version(for_platform, version) 254: 255: # restore lib_dir 256: @lib_dir = orig_lib_dir 257: end 258: end
# File lib/rake/extensiontask.rb, line 260 260: def define_cross_platform_tasks_with_version(for_platform, ruby_ver) 261: config_path = File.expand_path("~/.rake-compiler/config.yml") 262: 263: # warn the user about the need of configuration to use cross compilation. 264: unless File.exist?(config_path) 265: warn "rake-compiler must be configured first to enable cross-compilation" 266: return 267: end 268: 269: config_file = YAML.load_file(config_path) 270: 271: # tmp_path 272: tmp_path = "#{@tmp_dir}/#{for_platform}/#{@name}/#{ruby_ver}" 273: 274: # lib_path 275: lib_path = lib_dir 276: 277: unless rbconfig_file = config_file["rbconfig-#{ruby_ver}"] then 278: warn "no configuration section for specified version of Ruby (rbconfig-#{ruby_ver})" 279: return 280: end 281: 282: # mkmf 283: mkmf_file = File.expand_path(File.join(File.dirname(rbconfig_file), '..', 'mkmf.rb')) 284: 285: # define compilation tasks for cross platform! 286: define_compile_tasks(for_platform, ruby_ver) 287: 288: # chain fake.rb, rbconfig.rb and mkmf.rb to Makefile generation 289: file "#{tmp_path}/Makefile" => ["#{tmp_path}/fake.rb", 290: "#{tmp_path}/rbconfig.rb", 291: "#{tmp_path}/mkmf.rb"] 292: 293: # copy the file from the cross-ruby location 294: file "#{tmp_path}/rbconfig.rb" => [rbconfig_file] do |t| 295: cp t.prerequisites.first, t.name 296: end 297: 298: # copy mkmf from cross-ruby location 299: file "#{tmp_path}/mkmf.rb" => [mkmf_file] do |t| 300: cp t.prerequisites.first, t.name 301: end 302: 303: # genearte fake.rb for different ruby versions 304: file "#{tmp_path}/fake.rb" do |t| 305: File.open(t.name, 'w') do |f| 306: f.write fake_rb(ruby_ver) 307: end 308: end 309: 310: # now define native tasks for cross compiled files 311: if @gem_spec && @gem_spec.platform == 'ruby' then 312: define_native_tasks(for_platform, ruby_ver, @cross_compiling) 313: end 314: 315: # create cross task 316: task 'cross' do 317: # clear compile dependencies 318: Rake::Task['compile'].prerequisites.reject! { |t| !compiles_cross_platform.include?(t) } 319: 320: # chain the cross platform ones 321: task 'compile' => ["compile:#{for_platform}"] 322: 323: # clear lib/binary dependencies and trigger cross platform ones 324: # check if lib/binary is defined (damn bundle versus so versus dll) 325: if Rake::Task.task_defined?("#{lib_path}/#{binary(for_platform)}") then 326: Rake::Task["#{lib_path}/#{binary(for_platform)}"].prerequisites.clear 327: end 328: 329: # FIXME: targeting multiple platforms copies the file twice 330: file "#{lib_path}/#{binary(for_platform)}" => ["copy:#{@name}:#{for_platform}:#{ruby_ver}"] 331: 332: # if everything for native task is in place 333: if @gem_spec && @gem_spec.platform == 'ruby' then 334: # double check: only cross platform native tasks should be here 335: # FIXME: Sooo brittle 336: Rake::Task['native'].prerequisites.reject! { |t| !natives_cross_platform.include?(t) } 337: task 'native' => ["native:#{for_platform}"] 338: end 339: end 340: end
# File lib/rake/extensiontask.rb, line 169 169: def define_native_tasks(for_platform = nil, ruby_ver = RUBY_VERSION, callback = nil) 170: platf = for_platform || platform 171: 172: # tmp_path 173: tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}" 174: 175: # lib_path 176: lib_path = lib_dir 177: 178: # create 'native:gem_name' and chain it to 'native' task 179: unless Rake::Task.task_defined?("native:#{@gem_spec.name}:#{platf}") 180: task "native:#{@gem_spec.name}:#{platf}" do |t| 181: # FIXME: truly duplicate the Gem::Specification 182: # workaround the lack of #dup for Gem::Specification 183: spec = gem_spec.dup 184: 185: # adjust to specified platform 186: spec.platform = Gem::Platform.new(platf) 187: 188: # clear the extensions defined in the specs 189: spec.extensions.clear 190: 191: # add the binaries that this task depends on 192: ext_files = [] 193: 194: # go through native prerequisites and grab the real extension files from there 195: t.prerequisites.each do |ext| 196: ext_files << ext 197: end 198: 199: # include the files in the gem specification 200: spec.files += ext_files 201: 202: # expose gem specification for customization 203: if callback 204: callback.call(spec) 205: end 206: 207: # Generate a package for this gem 208: gem_package = Rake::GemPackageTask.new(spec) do |pkg| 209: pkg.need_zip = false 210: pkg.need_tar = false 211: end 212: end 213: end 214: 215: # add binaries to the dependency chain 216: task "native:#{@gem_spec.name}:#{platf}" => ["#{lib_path}/#{binary(platf)}"] 217: 218: # ensure the extension get copied 219: unless Rake::Task.task_defined?("#{lib_path}/#{binary(platf)}") then 220: file "#{lib_path}/#{binary(platf)}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"] 221: end 222: 223: # Allow segmented packaging by platform (open door for 'cross compile') 224: task "native:#{platf}" => ["native:#{@gem_spec.name}:#{platf}"] 225: 226: # Only add this extension to the compile chain if current 227: # platform matches the indicated one. 228: if platf == RUBY_PLATFORM then 229: task "native:#{@gem_spec.name}" => ["native:#{@gem_spec.name}:#{platf}"] 230: task "native" => ["native:#{platf}"] 231: end 232: end
# File lib/rake/extensiontask.rb, line 360 360: def dev_null 361: windows? ? 'NUL' : '/dev/null' 362: end
# File lib/rake/extensiontask.rb, line 342 342: def extconf 343: "#{@ext_dir}/#{@config_script}" 344: end
# File lib/rake/extensiontask.rb, line 376 376: def fake_rb(version) 377: class Object remove_const :RUBY_PLATFORM remove_const :RUBY_VERSION RUBY_PLATFORM = "i386-mingw32" RUBY_VERSION = "#{version}" end 378: end
# File lib/rake/extensiontask.rb, line 346 346: def make 347: unless @make 348: @make = 349: if RUBY_PLATFORM =~ /mswin/ then 350: 'nmake' 351: else 352: ENV['MAKE'] || ]gmake make].find { |c| 353: system("#{c} -v >> #{dev_null} 2>&1") 354: } 355: end 356: end 357: @make 358: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.