# 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.