rake-compiler-0.9.5/0000755000004100000410000000000012457522125014314 5ustar www-datawww-datarake-compiler-0.9.5/Rakefile0000644000004100000410000000046312457522125015764 0ustar www-datawww-data#-- # Copyright (c) 2008 Luis Lavena # # This source code is released under the MIT License. # See LICENSE file for details #++ # # NOTE: Keep this file clean. # Add your customizations inside tasks directory. # Thank You. # # load rakefile extensions (tasks) Dir['tasks/*.rake'].sort.each { |f| load f } rake-compiler-0.9.5/bin/0000755000004100000410000000000012457522125015064 5ustar www-datawww-datarake-compiler-0.9.5/bin/rake-compiler0000755000004100000410000000073612457522125017552 0ustar www-datawww-data#!/usr/bin/env ruby #-- # Copyright (c) 2008 Luis Lavena # # This source code is released under the MIT License. # See LICENSE file for details #++ begin require 'rake' rescue LoadError require 'rubygems' require 'rake' end # Initialize 'rake-compiler' application Rake.application.init('rake-compiler') # Load the already cooked tasks ;-) load File.join(File.dirname(__FILE__), %w{.. tasks bin cross-ruby.rake}) # delegate control to Rake Rake.application.top_level rake-compiler-0.9.5/Gemfile0000644000004100000410000000017712457522125015614 0ustar www-datawww-datasource "https://rubygems.org" gem "rake" group :development do gem "rspec", "~> 2.8.0" gem "cucumber", "~> 1.1.4" end rake-compiler-0.9.5/appveyor.yml0000644000004100000410000000063112457522125016704 0ustar www-datawww-data--- version: "{build}" branches: only: - master clone_depth: 10 install: - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% - ruby --version - gem --version - gem install bundler --quiet --no-ri --no-rdoc - bundler --version - bundle install build: off test_script: - bundle exec rake spec environment: matrix: - ruby_version: "193" - ruby_version: "200" - ruby_version: "200-x64" rake-compiler-0.9.5/features/0000755000004100000410000000000012457522125016132 5ustar www-datawww-datarake-compiler-0.9.5/features/java-package.feature0000644000004100000410000000167312457522125022030 0ustar www-datawww-dataFeature: Generate JRuby gems from JRuby or MRI In order to keep sanity in the Ruby world As a Gem developer who used to do J2EE development I want more rake magic that turns monotony into joy. @java Scenario: package a gem for Java (with default Rake) Given that my JRuby gem source is all in place And I've installed the Java Development Kit And I've already successfully executed rake task 'java compile' When rake task 'java gem' is invoked Then rake task 'java gem' succeeded And gem for platform 'java' get generated @java Scenario: package a gem for Java (with Rake on JRuby) Given that my JRuby gem source is all in place And I've installed the Java Development Kit And I've installed JRuby And I've already successfully executed rake task 'java compile' on JRuby When rake task 'java gem' is invoked Then rake task 'java gem' succeeded And gem for platform 'java' get generated rake-compiler-0.9.5/features/step_definitions/0000755000004100000410000000000012457522125021500 5ustar www-datawww-datarake-compiler-0.9.5/features/step_definitions/execution.rb0000644000004100000410000000302412457522125024027 0ustar www-datawww-data# FIXME: Make the Transform work # # Transform /^| on JRuby$/ do |step_arg| # / on JRuby/.match(step_arg) != nil # end Given %r{^I've already successfully executed rake task '(.*)'(| on JRuby)$} do |task_name, on_jruby| rake_cmd = "rake #{task_name}" rake_cmd = 'jruby -S ' << rake_cmd if on_jruby == ' on JRuby' emptyness = `#{rake_cmd} 2>&1` unless $?.success? warn emptyness raise "rake failed with #{$?.exitstatus}" end end When /^rake task '(.*)' is invoked(| on JRuby)$/ do |task_name, on_jruby| @output ||= {} @result ||= {} rake_cmd = "rake #{task_name}" rake_cmd = 'jruby -S ' << rake_cmd if on_jruby == ' on JRuby' @output[task_name] = `#{rake_cmd} 2>&1` @result[task_name] = $?.success? end Then /^rake task '(.*)' succeeded$/ do |task_name| if @result.nil? || !@result.include?(task_name) then raise "The task #{task_name} should be invoked first." else @result[task_name].should be_true end end Then /^rake task '(.*)' should fail$/ do |task_name| if @result.nil? || !@result.include?(task_name) then raise "The task #{task_name} should be invoked first." else @result[task_name].should be_false end end Then /^output of rake task '(.*)' (contains|do not contain) \/(.*)\/$/ do |task_name, condition, regex| if condition == 'contains' then @output[task_name].should match(%r(#{regex})) else @output[task_name].should_not match(%r(#{regex})) end end Then /^output of rake task '(.*)' warns$/ do |task_name, warning| @output[task_name].should include(warning) end rake-compiler-0.9.5/features/step_definitions/folders.rb0000644000004100000410000000155712457522125023473 0ustar www-datawww-dataGiven /^a safe project directory$/ do # step back to ROOT Dir.chdir ROOT_PATH tmp_name = "project.#{Process.pid}" @safe_dir = File.join(ROOT_PATH, 'tmp', tmp_name) FileUtils.rm_rf @safe_dir FileUtils.mkdir_p @safe_dir Dir.chdir @safe_dir generate_scaffold_structure end Given /^'(.*)' folder (exist|is deleted)$/ do |folder, condition| case condition when 'exist' raise "Folder #{folder} do not exist" unless File.exist?(folder) && File.directory?(folder) when 'is deleted' FileUtils.rm_rf folder end end Then /^'(.*)' folder is created$/ do |folder| File.directory?(folder).should be_true end Then /^'(.*)' folder do not exist$/ do |folder| File.directory?(folder).should_not be_true end Then /^no left over from '(.*)' remains in '(.*)'$/ do |name, folder| Dir.glob("#{folder}/**/#{name}/#{RUBY_VERSION}").should be_empty end rake-compiler-0.9.5/features/step_definitions/java_compilation.rb0000644000004100000410000000052512457522125025346 0ustar www-datawww-dataGiven %r{^I've installed the Java Development Kit$} do pending('Cannot locate suitable Java compiler (the Java Development Kit) in the PATH.') unless search_path(%w(javac javac.exe)) end Given %r{^I've installed JRuby$} do pending('Cannot locate a JRuby installation in the PATH.') unless search_path(%w(jruby jruby.exe jruby.bat)) end rake-compiler-0.9.5/features/step_definitions/cross_compilation.rb0000644000004100000410000000166612457522125025565 0ustar www-datawww-data# Naive way of looking into platforms, please include others like FreeBSD? Given %r{^I'm running a POSIX operating system$} do unless RbConfig::CONFIG['host_os'] =~ /linux|darwin/ then raise Cucumber::Pending.new("You need a POSIX operating system, no cheating ;-)") end end Given %r{^I've installed cross compile toolchain$} do unless search_path(%w(i586-mingw32msvc-gcc i386-mingw32-gcc i686-w64-mingw32-gcc)) pending 'Cannot locate suitable compiler in the PATH.' end end Then /^binaries for platform '(.*)' get generated$/ do |platform| ext = binary_extension(platform) ext_for_platform = Dir.glob("tmp/#{platform}/**/*.#{ext}") ext_for_platform.should_not be_empty end Then /^binaries for platform '(.*)' version '(.*)' get copied$/ do |platform, version| lib_path = "lib/#{version}" ext = binary_extension(platform) ext_for_platform = Dir.glob("#{lib_path}/*.#{ext}") ext_for_platform.should_not be_empty end rake-compiler-0.9.5/features/step_definitions/gem.rb0000644000004100000410000000321212457522125022573 0ustar www-datawww-dataGiven /^a gem named '(.*)'$/ do |gem_name| generate_gem_task gem_name end Then /^ruby gem for '(.*)' version '(.*)' do exist in '(.*)'$/ do |name, version, folder| File.exist?(gem_file(folder, name, version)).should be_true end Then /^binary gem for '(.*)' version '(.*)' do exist in '(.*)'$/ do |name, version, folder| File.exist?(gem_file_platform(folder, name, version)).should be_true end Then /^a gem for '(.*)' version '(.*)' platform '(.*)' do exist in '(.*)'$/ do |name, version, platform, folder| File.exist?(gem_file_platform(folder, name, version, platform)).should be_true # unpack the Gem and check what's inside! `gem unpack #{gem_file_platform(folder, name, version, platform)} --target tmp` unpacked_gem_dir = unpacked_gem_dir_platform('tmp', name, version, platform) File.exist?(unpacked_gem_dir).should be_true files = Dir.glob("#{unpacked_gem_dir}/lib/*.#{binary_extension(platform)}") files << Dir.glob("#{unpacked_gem_dir}/lib/*/*.#{binary_extension(platform)}") files.flatten.uniq.should_not be_empty end Then /^gem for platform '(.*)' get generated$/ do |platform| step "a gem for 'gem_abc' version '0.1.0' platform '#{platform}' do exist in 'pkg'" end def gem_file(folder, name, version) "#{folder}/#{name}-#{version}.gem" end def gem_file_platform(folder, name, version, platform = nil) file = "#{folder}/#{name}-#{version}" file << "-" << (platform || Gem::Platform.new(RUBY_PLATFORM).to_s) file << ".gem" file end def unpacked_gem_dir_platform(folder, name, version, platform = nil) file = "#{folder}/#{name}-#{version}" file << "-" << (platform || Gem::Platform.new(RUBY_PLATFORM).to_s) file end rake-compiler-0.9.5/features/step_definitions/compilation.rb0000644000004100000410000000437612457522125024355 0ustar www-datawww-dataGiven /^a extension named '(.*)'$/ do |extension_name| generate_extension_task_for extension_name generate_source_code_for extension_name end Given /^a extension cross-compilable '(.*)'$/ do |extension_name| generate_cross_compile_extension_task_for extension_name generate_source_code_for extension_name end Given /^a extension Java-compilable '(.*)'$/ do |extension_name| generate_java_compile_extension_task_for extension_name generate_java_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 end Given /^that all my source files are in place$/ do step "a safe project directory" step "a extension cross-compilable 'extension_one'" end Given /^that all my Java source files are in place$/ do step "a safe project directory" step "a extension Java-compilable 'extension_one'" end Given /^that my gem source is all in place$/ do step "a safe project directory" step "a gem named 'gem_abc'" step "a extension cross-compilable 'extension_one'" end Given /^that my JRuby gem source is all in place$/ do step "a safe project directory" step "a gem named 'gem_abc'" step "a extension Java-compilable 'extension_one'" end Given /^that my gem source is all in place to target two platforms$/ do step "a safe project directory" step "a gem named 'gem_abc'" step "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 When /^touching '(.*)' file of extension '(.*)'$/ do |file, extension_name| Kernel.sleep 1 FileUtils.touch "ext/#{extension_name}/#{file}" end Then /^binary extension '(.*)' (do|do not) exist in '(.*)'$/ do |extension_name, condition, folder| ext_for_platform = File.join(folder, "#{extension_name}.#{RbConfig::CONFIG['DLEXT']}") if condition == 'do' File.exist?(ext_for_platform).should be_true else File.exist?(ext_for_platform).should be_false end end rake-compiler-0.9.5/features/java-no-native-compile.feature0000644000004100000410000000302512457522125023754 0ustar www-datawww-dataFeature: No native or cross compilation on JRuby In order to present a good user experience to users of rake-compiler As a user of JRuby I want to be warned that my platform does not provide any support for C Extensions I want to be be informed of this without rake-compiler blowing up in my face @java Scenario: Attempting to do a cross compilation while on JRuby (without prerequisites) Given that all my source files are in place And I'm running a POSIX operating system When rake task 'cross compile' is invoked on JRuby Then rake task 'cross compile' should fail And output of rake task 'cross compile' warns """ WARNING: You're attempting to (cross-)compile C extensions from a platform (jruby) that does not support native extensions or mkmf.rb. """ And output of rake task 'cross compile' contains /Don't know how to build task 'cross'/ @java Scenario: Attempting to do a cross compilation while on JRuby (even with prerequisites) Given that all my source files are in place And I'm running a POSIX operating system And I've installed cross compile toolchain When rake task 'cross compile' is invoked on JRuby Then rake task 'cross compile' should fail And output of rake task 'cross compile' warns """ WARNING: You're attempting to (cross-)compile C extensions from a platform (jruby) that does not support native extensions or mkmf.rb. """ And output of rake task 'cross compile' contains /Don't know how to build task 'cross'/ rake-compiler-0.9.5/features/cross-compile.feature0000644000004100000410000000206412457522125022270 0ustar www-datawww-dataFeature: Cross-compile C extensions In order to avoid bitching from Windows users As a Ruby developer on Linux I want some rake tasks that take away the pain of compilation Scenario: compile single extension Given that all my source files are in place And I'm running a POSIX operating system And I've installed cross compile toolchain When rake task 'cross compile' is invoked Then rake task 'cross compile' succeeded And binaries for platform 'i386-mingw32' get generated Scenario: compile single extension to multiple versions Given that all my source files are in place And I'm running a POSIX operating system And I've installed cross compile toolchain When rake task 'cross compile RUBY_CC_VERSION=1.8.7:1.9.3:2.0.0' is invoked Then rake task 'cross compile RUBY_CC_VERSION=1.8.7:1.9.3:2.0.0' succeeded And binaries for platform 'i386-mingw32' version '1.8' get copied And binaries for platform 'i386-mingw32' version '1.9' get copied And binaries for platform 'i386-mingw32' version '2.0' get copied rake-compiler-0.9.5/features/package.feature0000644000004100000410000000324412457522125021105 0ustar www-datawww-dataFeature: Distribute native extension with gems In order to avoid compiler toolchain requirement during installation As a Gem developer. I want rake tasks generate platform specific gems for me Scenario: generate pure ruby gem Given a safe project directory And a gem named 'my_project' And a extension named 'extension_one' And I've already successfully executed rake task 'compile' And 'pkg' folder is deleted When rake task 'gem' is invoked Then rake task 'gem' succeeded And 'pkg' folder is created And ruby gem for 'my_project' version '0.1.0' do exist in 'pkg' Scenario: generate native gem Given a safe project directory And a gem named 'my_project' And a extension named 'extension_one' And I've already successfully executed rake task 'compile' And 'pkg' folder is deleted When rake task 'native gem' is invoked Then rake task 'native gem' succeeded And 'pkg' folder is created And ruby gem for 'my_project' version '0.1.0' do exist in 'pkg' And binary gem for 'my_project' version '0.1.0' do exist in 'pkg' Scenario: generate forced native gem Given a safe project directory And a gem named 'my_project' And a extension 'extension_one' with forced platform 'universal-unknown' And I've already successfully executed rake task 'compile' And 'pkg' folder is deleted When rake task 'native:universal-unknown gem' is invoked Then rake task 'native:universal-unknown gem' succeeded And 'pkg' folder is created And ruby gem for 'my_project' version '0.1.0' do exist in 'pkg' And a gem for 'my_project' version '0.1.0' platform 'universal-unknown' do exist in 'pkg' rake-compiler-0.9.5/features/cross-package-multi.feature0000644000004100000410000000130412457522125023357 0ustar www-datawww-dataFeature: 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-60' get generated And gem for platform 'x86-mingw32' get generated rake-compiler-0.9.5/features/support/0000755000004100000410000000000012457522125017646 5ustar www-datawww-datarake-compiler-0.9.5/features/support/file_template_helpers.rb0000644000004100000410000000617612457522125024541 0ustar www-datawww-datamodule FileTemplateHelpers def template_rakefile <<-EOF # add rake-compiler lib dir to the LOAD_PATH $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../..', 'lib')) require 'rubygems' require 'rake' # load rakefile extensions (tasks) Dir['tasks/*.rake'].each { |f| import f } EOF end def template_rake_gemspec(gem_name) <<-EOF require 'rubygems/package_task' SPEC = Gem::Specification.new do |s| s.name = "#{gem_name}" s.version = "0.1.0" s.summary = "#{gem_name} test gem for rake-compiler" s.description = "#{gem_name} is a fake gem for testing under rake-compiler" s.files = FileList["ext/**/*.{rb,c,h}", "Rakefile", "tasks/*.rake", "lib/**/*.rb"] s.extensions = FileList["ext/**/extconf.rb"] s.homepage = 'http://github.com/luislavena/rake-compiler' s.rubyforge_project = 'TODO' s.authors = ["Luis Lavena"] s.email = ["luislavena@gmail.com"] end Gem::PackageTask.new(SPEC) do |pkg| pkg.need_zip = false pkg.need_tar = false end EOF end def template_rake_extension(extension_name, gem_spec = nil) <<-EOF require 'rake/extensiontask' Rake::ExtensionTask.new("#{extension_name}"#{', SPEC' if gem_spec}) EOF end def template_rake_extension_with_platform(extension_name, platform) <<-EOF require 'rake/extensiontask' Rake::ExtensionTask.new("#{extension_name}", SPEC) do |ext| ext.platform = "#{platform}" end EOF end def template_rake_extension_cross_compile(extension_name, gem_spec = nil) <<-EOF require 'rake/extensiontask' Rake::ExtensionTask.new("#{extension_name}"#{', SPEC' if gem_spec}) do |ext| ext.cross_compile = true 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-60', 'i386-mingw32'] end EOF end def template_rake_extension_java_compile(extension_name, gem_spec = nil) <<-EOF require 'rake/javaextensiontask' Rake::JavaExtensionTask.new("#{extension_name}"#{', SPEC' if gem_spec}) do |ext| # nothing end EOF end def template_extconf(extension_name) <<-EOF require 'mkmf' create_makefile("#{extension_name}") EOF end def template_source_c(extension_name) <<-EOF #include "source.h" void Init_#{extension_name}() { printf("source.c of extension #{extension_name}\\n"); } EOF end def template_source_h <<-EOF #include "ruby.h" EOF end def template_source_java(extension_name) <<-EOF import org.jruby.Ruby; import org.jruby.runtime.load.BasicLibraryService; public class #{camelize(extension_name)}Service implements BasicLibraryService { public boolean basicLoad(final Ruby runtime) throws java.io.IOException { HelloWorldPrinter hwp = new HelloWorldPrinter(); hwp.tellTheWorld(); return true; } private class HelloWorldPrinter { void tellTheWorld() throws java.io.IOException { System.out.println("#{camelize(extension_name)}Service.java of extension #{extension_name}\\n"); } } } EOF end def camelize(str) str.gsub(/(^|_)(.)/) { $2.upcase } end end World(FileTemplateHelpers) rake-compiler-0.9.5/features/support/generator_helpers.rb0000644000004100000410000000714512457522125023712 0ustar www-datawww-datamodule GeneratorHelpers def generate_scaffold_structure # create folder structure FileUtils.mkdir_p "lib" FileUtils.mkdir_p "tasks" FileUtils.mkdir_p "tmp" # create Rakefile loader File.open("Rakefile", 'w') do |rakefile| rakefile.puts template_rakefile.strip end end def generate_gem_task(gem_name) # create generic gem task File.open("tasks/gem.rake", 'w') do |gem_rake| gem_rake.puts template_rake_gemspec(gem_name) end end def generate_extension_task_for(extension_name, platform = nil) # create folder structure FileUtils.mkdir_p "ext/#{extension_name}" return if File.exist?("tasks/#{extension_name}.rake") # Building a gem? if File.exist?("tasks/gem.rake") then File.open("tasks/gem.rake", 'a+') do |ext_in_gem| if platform ext_in_gem.puts template_rake_extension_with_platform(extension_name, platform) else ext_in_gem.puts template_rake_extension(extension_name, true) end end else # create specific extension rakefile File.open("tasks/#{extension_name}.rake", 'w') do |ext_rake| ext_rake.puts template_rake_extension(extension_name) end end end def generate_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_cross_compile(extension_name, true) end else File.open("tasks/#{extension_name}.rake", 'w') do |ext_rake| ext_rake.puts template_rake_extension_cross_compile(extension_name) end end end def generate_java_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_java_compile(extension_name, true) end else File.open("tasks/#{extension_name}.rake", 'w') do |ext_rake| ext_rake.puts template_rake_extension_java_compile(extension_name) end 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| c.puts template_source_c(extension_name) end # header H file File.open("ext/#{extension_name}/source.h", 'w') do |h| h.puts template_source_h end # extconf.rb file File.open("ext/#{extension_name}/extconf.rb", 'w') do |ext| ext.puts template_extconf(extension_name) end end def generate_java_source_code_for(extension_name) # source .java file File.open("ext/#{extension_name}/#{camelize(extension_name)}Service.java", 'w') do |c| c.puts template_source_java(extension_name) end end end World(GeneratorHelpers) rake-compiler-0.9.5/features/support/platform_extension_helpers.rb0000644000004100000410000000110612457522125025633 0ustar www-datawww-datamodule PlatformExtensionHelpers def binary_extension(platform = RUBY_PLATFORM) case platform when /darwin/ 'bundle' when /mingw|mswin|linux/ 'so' when /java/ 'jar' else RbConfig::CONFIG['DLEXT'] end end def search_path(binaries) paths = ENV['PATH'].split(File::PATH_SEPARATOR) binary = binaries.find do |bin_file| paths.find do |path| bin = File.join(path, bin_file) File.exist?(bin) && File.executable?(bin) end end binary end end World(PlatformExtensionHelpers) rake-compiler-0.9.5/features/support/env.rb0000644000004100000410000000035512457522125020766 0ustar www-datawww-datarequire 'cucumber' require 'rspec' require 'fileutils' require 'rbconfig' ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '../..')) # get rid of Bundler environment polution defined?(Bundler) and ENV.delete("RUBYOPT") rake-compiler-0.9.5/features/compile.feature0000644000004100000410000000632112457522125021141 0ustar www-datawww-dataFeature: Compile C code into Ruby extensions. In order to automate compilation process. As a Gem developer. I want rake tasks compile source code for me. Scenario: compile single extension Given a safe project directory And a extension named 'extension_one' And 'tmp' folder is deleted When rake task 'compile' is invoked Then rake task 'compile' succeeded And binary extension 'extension_one' do exist in 'lib' And 'tmp' folder is created Scenario: compile an extension with extra options Given a safe project directory And a extension named 'extension_one' And 'tmp' folder is deleted When rake task 'compile -- --with-opt-dir=/opt/local' is invoked Then rake task 'compile -- --with-opt-dir=/opt/local' succeeded And output of rake task 'compile -- --with-opt-dir=/opt/local' contains /with-opt-dir/ Scenario: not recompile unmodified extension Given a safe project directory And a extension named 'extension_one' And I've already successfully executed rake task 'compile' And not changed any file since When rake task 'compile' is invoked Then rake task 'compile' succeeded And output of rake task 'compile' do not contain /gcc|cl/ Scenario: recompile extension when source is modified Given a safe project directory And a extension named 'extension_one' And I've already successfully executed rake task 'compile' When touching 'source.c' file of extension 'extension_one' And rake task 'compile' is invoked Then rake task 'compile' succeeded And output of rake task 'compile' contains /extension_one/ Scenario: compile multiple extensions Given a safe project directory And a extension named 'extension_one' And a extension named 'extension_two' And 'tmp' folder is deleted When rake task 'compile' is invoked Then rake task 'compile' succeeded And binary extension 'extension_one' do exist in 'lib' And binary extension 'extension_two' do exist in 'lib' And 'tmp' folder is created Scenario: compile one extension instead of all present Given a safe project directory And a extension named 'extension_one' And a extension named 'extension_two' When rake task 'compile:extension_one' is invoked Then rake task 'compile:extension_one' succeeded And output of rake task 'compile:extension_one' do not contain /extension_two/ And binary extension 'extension_one' do exist in 'lib' And binary extension 'extension_two' do not exist in 'lib' Scenario: removing temporary files Given a safe project directory And a extension named 'extension_one' And I've already successfully executed rake task 'compile' When rake task 'clean' is invoked Then rake task 'clean' succeeded And binary extension 'extension_one' do exist in 'lib' And no left over from 'extension_one' remains in 'tmp' Scenario: clobbering binary and temporary files Given a safe project directory And a extension named 'extension_one' And I've already successfully executed rake task 'compile' When rake task 'clobber' is invoked Then rake task 'clobber' succeeded And binary extension 'extension_one' do not exist in 'lib' And 'tmp' folder do not exist rake-compiler-0.9.5/features/java-compile.feature0000644000004100000410000000150412457522125022056 0ustar www-datawww-dataFeature: JCompile Java extensions In order to avoid bitching from Enterprise users As a Ruby developer I want some rake tasks that take away the pain of compilation @java Scenario: Compile single Java extension (with default Rake) Given that all my Java source files are in place And I've installed the Java Development Kit When rake task 'java compile' is invoked Then rake task 'java compile' succeeded And binaries for platform 'java' get generated @java Scenario: Compile single Java extension (with Rake on JRuby) Given that all my Java source files are in place And I've installed the Java Development Kit When I've installed JRuby When rake task 'java compile' is invoked on JRuby Then rake task 'java compile' succeeded And binaries for platform 'java' get generated rake-compiler-0.9.5/features/cross-package.feature0000644000004100000410000000106712457522125022235 0ustar www-datawww-dataFeature: Generate Windows gems from Linux In order to keep sanity in the Ruby world As a Gem developer on Linux I want more rake magic that turns monotony into joy. Scenario: package a gem for Windows Given that my gem source is all in place 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-mingw32' get generated rake-compiler-0.9.5/LICENSE.txt0000644000004100000410000000204512457522125016140 0ustar www-datawww-dataCopyright (c) 2008-2011 Luis Lavena. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rake-compiler-0.9.5/History.txt0000644000004100000410000002535112457522125016524 0ustar www-datawww-data=== 0.9.5 / 2015-01-03 * Enhancements * Support adding bundled files in cross_compiling block. Closes #100 [Patch by Aaron Stone] === 0.9.4 / 2014-12-28 * Notes: * Change maintainer to Kouhei Sutou from Luis Lavena. Thanks Luis Lavena for your great works! * Change repository to https://github.com/rake-compiler/rake-compiler from https://github.com/luislavena/rake-compiler . * Bugfixes: * Loose RubyGems dependency a little bit to ease old Debian/Ubuntu. Closes #93 === 0.9.3 / 2014-08-03 * Bugfixes: * Fix specs to run (and pass) on Ruby 2.1 and beyond. Pull #94 [hggh] === 0.9.2 / 2013-11-14 * Bugfixes: * Pre-load resolver to avoid Bundler blow up during cross-compilation Pull #83 [larskanis] === 0.9.1 / 2013-08-03 * Bugfixes: * Restore compatibility with RubyGems platforms for cross-compilation (i386-mingw32 and x86-mingw32 are the same and supported) === 0.9.0 / 2013-08-03 * Enhancements: * Add support for cross-builds and multiple platforms (x86/x64). Pull #74 [larskanis] $ rake-compiler cross-ruby VERSION=1.8.7-p371 $ rake-compiler cross-ruby VERSION=1.9.3-p392 $ rake-compiler cross-ruby VERSION=2.0.0-p0 $ rake-compiler cross-ruby VERSION=2.0.0-p0 HOST=x86_64-w64-mingw32 $ rake cross compile RUBY_CC_VERSION=1.8.7:1.9.3:2.0.0 # Rakefile ext.cross_platform = %w[i386-mingw32 x64-mingw32] * Support for cross-platform specific options. Pull #74 [larskanis] # Rakefile ext.cross_config_options << "--with-common-option" ext.cross_config_options << {"x64-mingw32" => "--enable-64bits"} * Bugfixes: * Correct fat-gems support caused by RubyGems issues. Pull #76 [knu] * Deprecations: * Requires minimum Ruby 1.8.7 and RubyGems 1.8.25 * Usage of 'i386-mswin32' needs to be changed to 'i386-mswin32-60' === 0.9.0.pre.1 / 2013-05-05 See 0.9.0 changes. === 0.8.3 / 2013-02-16 * Bugfixes: * Support FreeBSD 'mingw32-gcc' cross compiler. Closes #72 [knu] === 0.8.2 / 2013-01-11 * Bugfixes: * Unset CC, LDFLAGS and CPPFLAGS prior cross-compiling. Closes #55 === 0.8.1 / 2012-04-15 * Bugfixes: * Raise error when either make or gmake could be found. Closes #53, #54 === 0.8.0 / 2012-01-08 * Enhancements: * Invocation from command line now support extra options similar to RubyGems. Closes #4 from Pull #47 [jonforums] $ rake compile -- --with-opt-dir=/opt/local * Bugfixes: * Only emit cross-compilation warnings for C when `cross` is invoked. Closes #16 from Pull #48 [mvz] * Only emit warnings when invoking cross-compilation tasks for JRuby. Pull #45 [jfirebaugh] * Use x86 MinGW cross-compiler. Pull #49 [larskanis] === 0.7.9 / 2011-06-08 * Enhancements: * Consistently use RubyGems features available since version 1.3.2 and avoid deprecation warnings with Rake > 0.8.7. * Bugfixes: * Use correct platform in fake.rb. Pull #39 [kou] * Workaround Gem::Specification and Gem::PackageTask limitations. Closes #43 === 0.7.8 / 2011-04-26 * Enhancements: * Bump default cross-ruby version to 1.8.7-p334. * ExtensionTask now support config_includes to load additional directories. [jfinkhaeuser] Rake::ExtensionTask.new("myext", GEM_SPEC) do |ext| ext.config_includes << File.expand_path("my", "custom", "dir") end * Bugfixes: * Warn if compiled files exists in extension's source directory. Closes GH-35 * Workaround issue with WINE using proper build option. Closes GH-37 * Use FileUtils#install instead of cp. Closes GH-33 [Eric Wong] * Update README instructions for OSX. Closes GH-29 [tmm1] === 0.7.7 / 2011-04-04 * Bugfixes: * Use Winsock2 as default to match Ruby 1.9.2 library linking. === 0.7.6 / 2011-02-04 * Bugfixes: * Prefer Psych over Syck for YAML parsing on Ruby 1.9.2. [tenderlove] === 0.7.5 / 2010-11-25 * Enhancements: * Promoted stable version for cross-compilation to 1.8.6-p398. Closes GH-19 * Bugfixes: * Generate a fake.rb compatible with Ruby 1.9.2. Closes GH-25 * fake.rb will not try to mimic Ruby's own fake to the letter. Closes GH-28 * Expand symlinks for tmp_dir. Closes GH-24 * Silence make output during rake-compiler invocation. * Usage of Gem.ruby instead of RbConfig ruby_install_name This solve issues with ruby vs. ruby.exe and jruby.exe * Experimental: * Allow setting of HOST during cross-compilation. This enable usage of mingw-w64 compiler and not the first one found in the PATH. rake-compiler cross-ruby VERSION=1.9.2-p0 HOST=i686-w64-mingw32 rake-compiler cross-ruby HOST=i386-mingw32 (OSX mingw32 port) rake-compiler cross-ruby HOST=i586-pc-mingw32 (Debian/Ubuntu mingw32) === 0.7.1 / 2010-08-07 * Bugfixes: * Update gem files to make "gem install -t" works. Closes GH-14 * Update mocks to work under 1.8.7. Closes GH-15 [luisparravicini] * Do not allow cross-ruby be executed under Windows. Closes GH-22 * Experimental: * Allow JRuby to compile C extensions [timfel]. It is now possible compile C extensions using latest JRuby. Offered in experimental mode since JRuby cext hasn't been officially released. === 0.7.0 / 2009-12-08 * Enhancements * Allow generation of JRuby extensions. Thanks to Alex Coles (myabc) for the contribution. This will allow, with proper JDK tools, cross compilation of JRuby gems from MRI. Rake::JavaExtensionTask.new('my_java_extension', GEM_SPEC) do |ext| # most of ExtensionTask options can be used # plus, java_compiling: ext.java_compiling do |gem_spec| gem_spec.post_install_message = "This is a native JRuby gem!" end end Please note that cross-compiling JRuby gems requires either JRUBY_HOME or JRUBY_PARENT_CLASSPATH environment variables being properly set. * Allow alteration of the Gem Specification when cross compiling. Closes GH-3 This is useful to indicate a custom requirement message, like DLLs installation or similar. Rake::ExtensionTask.new('my_extension', GEM_SPEC) do |ext| ext.cross_compile = true # ... ext.cross_compiling do |gem_spec| gem_spec.post_install_message = "You've installed a binary version of this gem" end end * Bugfixes * Detect GNU make independently of distribution based naming. Thanks to flori for patches. * Usage of #dup to duplicate gemspec instead of YAML dumping. * No longer support Ruby older than 1.8.6 * No longer support RubyGems older than 1.3.5 * Force definition of binary directory and executables. Closes GH-11 * Workaround path with spaces issues using relative paths. Closes GH-6 * Removed gemspec, GitHub gems no more * Known issues * Usage of rake-compiler under projects with Jeweler requires some tweaks Please read issue GH-73 for Jeweler: http://github.com/technicalpickles/jeweler/issues#issue/73 For a workaround, look here: http://gist.github.com/251663 === 0.6.0 / 2009-07-25 * Enhancements * Implemented 'fat-binaries' generation for cross compiling (for now). Thanks to Aaron Patterson for the suggestion and original idea. rake cross native gem RUBY_CC_VERSION=1.8.6:1.9.1 Will package extensions for 1.8 and 1.9 versions of Ruby. * Can now cross compile extensions for 1.9 using 1.8.x as base. Be warned: works from 1.8 to 1.9, but not if your default ruby is 1.9 rake cross compile RUBY_CC_VERSION=1.9.1 * Allow simultaneous versions of Ruby to compile extensions. This change allow 1.8.x compiles co-exist with 1.9.x ones and don't override each other. Please perform rake clobber prior compiling again. * Allow optional source file URL for cross-compile tasks. (Thanks to deepj for the patches) rake-compiler cross-ruby VERSION=1.9.1-p0 SOURCE=http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p0.tar.bz2 * Bugfixes * Removed strict versioning for gems since it clash with fat binaries. From now on, if your gem only targets a specific version of Ruby, please indicate it in the Gem::Specification (required_ruby_version) === 0.5.0 / 2009-04-25 * Enhancements * Allow generation of multiple gems for Windows (EXPERIMENTAL) This allows build gems for both VC6 and MinGW builts of Ruby (Thanks to Jonathan Stott for the suggestion) Rake::ExtensionTask.new('my_extension', GEM_SPEC) do |ext| ext.cross_compile = true ext.cross_platform = ['i386-mswin32', 'i386-mingw32'] end === 0.4.1 / 2009-04-09 * Enhancements * Target specific versions of Ruby when generating binaries. This avoids installing a 1.8.x binary gem in 1.9.x and viceversa. (Thanks to Aaron Patterson for the patches) * Bugfixes * No longer raises error if rake-compiler configuration is missing. Not all users of a project would have it installed. (Thanks to Aaron Patterson for the patch) === 0.4.0 / 2009-04-03 * Enhancements * Bended the convention for extension folder. Defining ext_dir for custom extension location. Rake::ExtensionTask.new('my_extension') do |ext| ext.ext_dir = 'custom/location' # look into custom/location end # instead of ext/my_extension * Better detection of mingw target across Linux/OSX. Exposed it as Rake::ExtensionCompiler * Display list of available tasks when calling rake-compiler script * Track Ruby full versioning (x.y.z). This will help the compilation of extensions targetting 1.8.6/7 and 1.9.1 * Bugfixes * Better output of Rake development tasks (Thanks to Luis Parravicini). * Proper usage of Gem::Platform for native gems (Thanks to Dirkjan Bussink). * Don't use autoload for YAML (present problems with Ruby 1.9.1). === 0.3.1 / 2009-01-09 * Enhancements * Download cross-ruby source code using HTTP instead of FTP. * Disabled Tcl/Tk extension building on cross-ruby (helps with 1.9). * Bugfixes * Workaround bug introduced by lack of Gem::Specification cloning. Fixes DM LH #757. * Use proper binary extension on OSX (reported by Dirkjan Bussink). * Ensure lib/binary task is defined prior clear of requisites. === 0.3.0 / 2008-12-07 * New features * Let you specify the Ruby version used for cross compilation instead of default one. rake cross compile RUBY_CC_VERSION=1.8 * Enhancements * Properly update rake-compiler configuration when new version is installed. * Automated release process to RubyForge, yay! * Bugfixes * Corrected documentation to reflect the available options === 0.2.1 / 2008-11-30 * New features * Allow cross compilation (cross compile) using mingw32 on Linux or OSX. * Allow packaging of gems for Windows on Linux or OSX. * Enhancements * Made generation of extensions safe and target folders per-platform * Bugfixes * Ensure binaries for the specific platform are copied before packaging. rake-compiler-0.9.5/spec/0000755000004100000410000000000012457522125015246 5ustar www-datawww-datarake-compiler-0.9.5/spec/spec.opts0000644000004100000410000000005012457522125017102 0ustar www-datawww-data--colour --format nested --loadby mtime rake-compiler-0.9.5/spec/spec_helper.rb0000644000004100000410000000050212457522125020061 0ustar www-datawww-datarequire 'rspec' # Console redirection helper require File.expand_path('../support/capture_output_helper', __FILE__) RSpec.configure do |config| config.include CaptureOutputHelper end # Rake::Task matcher helper RSpec::Matchers.define :have_defined do |task| match do |tasks| tasks.task_defined?(task) end end rake-compiler-0.9.5/spec/lib/0000755000004100000410000000000012457522125016014 5ustar www-datawww-datarake-compiler-0.9.5/spec/lib/rake/0000755000004100000410000000000012457522125016736 5ustar www-datawww-datarake-compiler-0.9.5/spec/lib/rake/javaextensiontask_spec.rb0000644000004100000410000001246512457522125024046 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require 'rake/javaextensiontask' require 'rbconfig' describe Rake::JavaExtensionTask do context '#new' do context '(basic)' do it 'should raise an error if no name is provided' do lambda { Rake::JavaExtensionTask.new }.should raise_error(RuntimeError, /Extension name must be provided/) end it 'should allow string as extension name assignation' do ext = Rake::JavaExtensionTask.new('extension_one') ext.name.should == 'extension_one' end it 'should allow string as extension name using block assignation' do ext = Rake::JavaExtensionTask.new do |ext| ext.name = 'extension_two' end ext.name.should == 'extension_two' end it 'should return itself for the block' do from_block = nil from_lasgn = Rake::JavaExtensionTask.new('extension_three') do |ext| from_block = ext end from_block.should == from_lasgn end it 'should accept a gem specification as parameter' do spec = mock_gem_spec ext = Rake::JavaExtensionTask.new('extension_three', spec) ext.gem_spec.should == spec end it 'should allow gem specification be defined using block assignation' do spec = mock_gem_spec ext = Rake::JavaExtensionTask.new('extension_four') do |ext| ext.gem_spec = spec end ext.gem_spec.should == spec end it 'should allow forcing of platform' do ext = Rake::JavaExtensionTask.new('weird_extension') do |ext| ext.platform = 'java-128bit' end ext.platform.should == 'java-128bit' end end end context '(defaults)' do before :each do @ext = Rake::JavaExtensionTask.new('extension_one') end it 'should dump intermediate files to tmp/' do @ext.tmp_dir.should == 'tmp' end it 'should copy build extension into lib/' do @ext.lib_dir.should == 'lib' end it 'should look for Java files pattern (.java)' do @ext.source_pattern.should == "**/*.java" end it 'should have no configuration options preset to delegate' do @ext.config_options.should be_empty end it 'should default to Java platform' do @ext.platform.should == 'java' end context '(tasks)' do before :each do Rake.application.clear CLEAN.clear CLOBBER.clear end context '(one extension)' do before :each do Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.java"]) @ext = Rake::JavaExtensionTask.new('extension_one') @ext_bin = ext_bin('extension_one') @platform = 'java' end context 'compile' do it 'should define as task' do Rake::Task.task_defined?('compile').should be_true end it "should depend on 'compile:{platform}'" do pending 'needs fixing' Rake::Task['compile'].prerequisites.should include("compile:#{@platform}") end end context 'compile:extension_one' do it 'should define as task' do Rake::Task.task_defined?('compile:extension_one').should be_true end it "should depend on 'compile:extension_one:{platform}'" do pending 'needs fixing' Rake::Task['compile:extension_one'].prerequisites.should include("compile:extension_one:#{@platform}") end end context 'lib/extension_one.jar' do it 'should define as task' do pending 'needs fixing' Rake::Task.task_defined?("lib/#{@ext_bin}").should be_true end it "should depend on 'copy:extension_one:{platform}'" do pending 'needs fixing' Rake::Task["lib/#{@ext_bin}"].prerequisites.should include("copy:extension_one:#{@platform}") end end context 'tmp/{platform}/extension_one/extension_one.jar' do it 'should define as task' do Rake::Task.task_defined?("tmp/#{@platform}/extension_one/#{@ext_bin}").should be_true end it "should depend on checkpoint file" do Rake::Task["tmp/#{@platform}/extension_one/#{@ext_bin}"].prerequisites.should include("tmp/#{@platform}/extension_one/.build") end end context 'tmp/{platform}/extension_one/.build' do it 'should define as task' do Rake::Task.task_defined?("tmp/#{@platform}/extension_one/.build").should be_true end it 'should depend on source files' do Rake::Task["tmp/#{@platform}/extension_one/.build"].prerequisites.should include("ext/extension_one/source.java") end end context 'clean' do it "should include 'tmp/{platform}/extension_one' in the pattern" do CLEAN.should include("tmp/#{@platform}/extension_one") end end context 'clobber' do it "should include 'lib/extension_one.jar'" do CLOBBER.should include("lib/#{@ext_bin}") end it "should include 'tmp'" do CLOBBER.should include('tmp') end end end end end private def ext_bin(extension_name) "#{extension_name}.jar" end def mock_gem_spec(stubs = {}) mock(Gem::Specification, { :name => 'my_gem', :platform => 'ruby' }.merge(stubs) ) end end rake-compiler-0.9.5/spec/lib/rake/extensiontask_spec.rb0000644000004100000410000004573112457522125023206 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') require 'rake/extensiontask' require 'rbconfig' describe Rake::ExtensionTask do context '#new' do context '(basic)' do it 'should raise an error if no name is provided' do lambda { Rake::ExtensionTask.new }.should raise_error(RuntimeError, /Extension name must be provided/) end it 'should allow string as extension name assignation' do ext = Rake::ExtensionTask.new('extension_one') ext.name.should == 'extension_one' end it 'should allow string as extension name using block assignation' do ext = Rake::ExtensionTask.new do |ext| ext.name = 'extension_two' end ext.name.should == 'extension_two' end it 'should return itself for the block' do from_block = nil from_lasgn = Rake::ExtensionTask.new('extension_three') do |ext| from_block = ext end from_block.should == from_lasgn end it 'should accept a gem specification as parameter' do spec = mock_gem_spec ext = Rake::ExtensionTask.new('extension_three', spec) ext.gem_spec.should == spec end it 'should allow gem specification be defined using block assignation' do spec = mock_gem_spec ext = Rake::ExtensionTask.new('extension_four') do |ext| ext.gem_spec = spec end ext.gem_spec.should == spec end it 'should allow forcing of platform' do ext = Rake::ExtensionTask.new('weird_extension') do |ext| ext.platform = 'universal-foo-bar-10.5' end ext.platform.should == 'universal-foo-bar-10.5' end end end context '(defaults)' do before :each do @ext = Rake::ExtensionTask.new('extension_one') end it 'should look for extconf script' do @ext.config_script.should == 'extconf.rb' end it 'should dump intermediate files to tmp/' do @ext.tmp_dir.should == 'tmp' end it 'should copy build extension into lib/' do @ext.lib_dir.should == 'lib' end it 'should look for C files pattern (.c)' do @ext.source_pattern.should == "*.c" end it 'should have no configuration options preset to delegate' do @ext.config_options.should be_empty end it "should have no includes preset to delegate" do @ext.config_includes.should be_empty end it 'should default to current platform' do @ext.platform.should == RUBY_PLATFORM end it 'should default to no cross compilation' do @ext.cross_compile.should be_false end it 'should have no configuration options for cross compilation' do @ext.cross_config_options.should be_empty end it "should have cross platform defined to 'i386-mingw32'" do @ext.cross_platform.should == 'i386-mingw32' end end context '(tasks)' do before :each do Rake.application.clear CLEAN.clear CLOBBER.clear end context '(one extension)' do before :each do Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], []) @ext = Rake::ExtensionTask.new('extension_one') @ext_bin = ext_bin('extension_one') @platform = RUBY_PLATFORM @ruby_ver = RUBY_VERSION end context 'compile' do it 'should define as task' do Rake::Task.task_defined?('compile').should be_true end it "should depend on 'compile:{platform}'" do Rake::Task['compile'].prerequisites.should include("compile:#{@platform}") end end context 'compile:extension_one' do it 'should define as task' do Rake::Task.task_defined?('compile:extension_one').should be_true end it "should depend on 'compile:extension_one:{platform}'" do Rake::Task['compile:extension_one'].prerequisites.should include("compile:extension_one:#{@platform}") end end context 'lib/extension_one.{so,bundle}' do it 'should define as task' do Rake::Task.task_defined?("lib/#{@ext_bin}").should be_true end it "should depend on 'copy:extension_one:{platform}:{ruby_ver}'" do Rake::Task["lib/#{@ext_bin}"].prerequisites.should include("copy:extension_one:#{@platform}:#{@ruby_ver}") end end context 'tmp/{platform}/extension_one/{ruby_ver}/extension_one.{so,bundle}' do it 'should define as task' do Rake::Task.task_defined?("tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}").should be_true end it "should depend on 'tmp/{platform}/extension_one/{ruby_ver}/Makefile'" do Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}"].prerequisites.should include("tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile") end it "should depend on 'ext/extension_one/source.c'" do Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}"].prerequisites.should include("ext/extension_one/source.c") end it "should not depend on 'ext/extension_one/source.h'" do Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/#{@ext_bin}"].prerequisites.should_not include("ext/extension_one/source.h") end end context 'tmp/{platform}/extension_one/{ruby_ver}/Makefile' do it 'should define as task' do Rake::Task.task_defined?("tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile").should be_true end it "should depend on 'tmp/{platform}/extension_one/{ruby_ver}'" do Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/#{@platform}/extension_one/#{@ruby_ver}") end it "should depend on 'ext/extension_one/extconf.rb'" do Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("ext/extension_one/extconf.rb") end end context 'clean' do it "should include 'tmp/{platform}/extension_one/{ruby_ver}' in the pattern" do CLEAN.should include("tmp/#{@platform}/extension_one/#{@ruby_ver}") end end context 'clobber' do it "should include 'lib/extension_one.{so,bundle}'" do CLOBBER.should include("lib/#{@ext_bin}") end it "should include 'tmp'" do CLOBBER.should include('tmp') end end it "should warn when pre-compiled files exist in extension directory" do Rake::FileList.stub!(:[]). and_return(["ext/extension_one/source.c"], ["ext/extension_one/source.o"]) _, err = capture_output do Rake::ExtensionTask.new('extension_one') end err.should match(/rake-compiler found compiled files in 'ext\/extension_one' directory. Please remove them./) end end context '(extension in custom location)' do before :each do Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], []) @ext = Rake::ExtensionTask.new('extension_one') do |ext| ext.ext_dir = 'custom/ext/foo' end @ext_bin = ext_bin('extension_one') @platform = RUBY_PLATFORM @ruby_ver = RUBY_VERSION end context 'tmp/{platform}/extension_one/{ruby_ver}/Makefile' do it "should depend on 'custom/ext/foo/extconf.rb'" do Rake::Task["tmp/#{@platform}/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("custom/ext/foo/extconf.rb") end end end context '(native tasks)' do before :each do Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], []) @spec = mock_gem_spec @ext_bin = ext_bin('extension_one') @platform = RUBY_PLATFORM @ruby_ver = RUBY_VERSION end context 'native' do before :each do @spec.stub!(:platform=).and_return('ruby') end it 'should define a task for building the supplied gem' do Rake::ExtensionTask.new('extension_one', @spec) Rake::Task.task_defined?('native:my_gem').should be_true end it 'should define as task for pure ruby gems' do Rake::Task.task_defined?('native').should be_false Rake::ExtensionTask.new('extension_one', @spec) Rake::Task.task_defined?('native').should be_true end it 'should not define a task for already native gems' do @spec.stub!(:platform).and_return('current') Rake::ExtensionTask.new('extension_one', @spec) Rake::Task.task_defined?('native').should be_false end it 'should depend on platform specific native tasks' do Rake::ExtensionTask.new('extension_one', @spec) Rake::Task["native"].prerequisites.should include("native:#{@platform}") end context 'native:my_gem:{platform}' do it 'should depend on binary extension' do Rake::ExtensionTask.new('extension_one', @spec) Rake::Task["native:my_gem:#{@platform}"].prerequisites.should include("tmp/#{@platform}/stage/lib/#{@ext_bin}") end end end end context '(cross platform tasks)' do before :each do File.stub!(:exist?).and_return(true) YAML.stub!(:load_file).and_return(mock_config_yml) Rake::FileList.stub!(:[]).and_return(["ext/extension_one/source.c"], []) @spec = mock_gem_spec @config_file = File.expand_path("~/.rake-compiler/config.yml") @ruby_ver = RUBY_VERSION @platform = 'i386-mingw32' @config_path = mock_config_yml["rbconfig-#{@platform}-#{@ruby_ver}"] File.stub!(:open).and_yield(mock_fake_rb) end context 'if no rake-compiler configuration exists' do before :each do File.should_receive(:exist?).with(@config_file).and_return(false) _, @err = capture_output do Rake::ExtensionTask.new('extension_one') do |ext| ext.cross_compile = true end end end it 'should not generate a warning' do @err.should eq("") end it 'should create a dummy nested cross-compile target that raises an error' do Rake::Task.should have_defined("cross") Rake::Task["cross"].invoke lambda { Rake::Task["compile"].invoke }.should raise_error(RuntimeError, /rake-compiler must be configured first to enable cross-compilation/) end end it 'should parse the config file using YAML' do YAML.should_receive(:load_file).with(@config_file).and_return(mock_config_yml) Rake::ExtensionTask.new('extension_one') do |ext| ext.cross_compile = true end end it 'should warn if no section of config file defines running version of ruby' do config = mock(Hash) config.should_receive(:[]).with("rbconfig-#{@platform}-#{@ruby_ver}").and_return(nil) YAML.stub!(:load_file).and_return(config) out, err = capture_output do Rake::ExtensionTask.new('extension_one') do |ext| ext.cross_compile = true end end err.should match(/no configuration section for specified version of Ruby/) end it 'should capture an action block to be executed when cross compiling' do lambda { Rake::ExtensionTask.new('extension_one') do |ext| ext.cross_compiling do |gem_spec| gem_spec.post_install_message = "Cross compiled gem" end end }.should_not raise_error end it 'should generate additional rake tasks if files are added when cross compiling' do config = mock(Hash) config.stub!(:[]).and_return('/rubies/1.9.1/rbconfig.rb') YAML.stub!(:load_file).and_return(config) # Use a real spec instead of a mock because define_native_tasks dups and # calls methods on Gem::Specification, which is more than mock can do. spec = Gem::Specification.new do |s| s.name = 'my_gem' s.platform = Gem::Platform::RUBY end # Gem::PackageTask calls Rake::PackageTask which sets Gem.configuration.verbose, # which initializes Gem::ConfigFile, # which gets mad if it cannot find `sysconfdir`/gemrc Gem.stub_chain(:configuration, :verbose=).and_return(true) ENV['RUBY_CC_VERSION'] = '1.9.1' Rake::ExtensionTask.new('extension_one', spec) do |ext| ext.cross_compile = true ext.cross_platform = 'universal-unknown' ext.cross_compiling do |gem_spec| gem_spec.files << 'somedir/somefile' end end Rake::Task['native:my_gem:universal-unknown'].execute Rake::Task.should have_defined("tmp/universal-unknown/stage/somedir") Rake::Task.should have_defined("tmp/universal-unknown/stage/somedir/somefile") end it 'should allow usage of RUBY_CC_VERSION to indicate a different version of ruby' do config = mock(Hash) config.should_receive(:[]).with("rbconfig-i386-mingw32-1.9.1").and_return('/rubies/1.9.1/rbconfig.rb') YAML.stub!(:load_file).and_return(config) ENV['RUBY_CC_VERSION'] = '1.9.1' Rake::ExtensionTask.new('extension_one') do |ext| ext.cross_compile = true end end it 'should allow multiple versions be supplied to RUBY_CC_VERSION' do config = mock(Hash) config.should_receive(:[]).once.with("rbconfig-i386-mingw32-1.8.6").and_return('/rubies/1.8.6/rbconfig.rb') config.should_receive(:[]).once.with("rbconfig-i386-mingw32-1.9.1").and_return('/rubies/1.9.1/rbconfig.rb') YAML.stub!(:load_file).and_return(config) ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1' Rake::ExtensionTask.new('extension_one') do |ext| ext.cross_compile = true end end after :each do ENV.delete('RUBY_CC_VERSION') end context "(cross compile for multiple versions)" do before :each do config = mock(Hash) config.stub!(:[]).and_return('/rubies/1.8.6/rbconfig.rb', '/rubies/1.9.1/rbconfig.rb') YAML.stub!(:load_file).and_return(config) ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1' @ext = Rake::ExtensionTask.new('extension_one') do |ext| ext.cross_compile = true ext.cross_platform = 'universal-unknown' end end it 'should create specific copy of binaries for each version' do Rake::Task.should have_defined("copy:extension_one:universal-unknown:1.8.6") Rake::Task.should have_defined("copy:extension_one:universal-unknown:1.9.1") end end context "(cross for 'universal-unknown' platform)" do before :each do @ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext| ext.cross_compile = true ext.cross_platform = 'universal-unknown' end end context 'fake' do it 'should chain fake task to Makefile generation' do Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/fake.rb") end end context 'rbconfig' do it 'should chain rbconfig tasks to Makefile generation' do Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/rbconfig.rb") end it 'should take rbconfig from rake-compiler configuration' do Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/rbconfig.rb"].prerequisites.should include(@config_path) end end context 'mkmf' do it 'should chain mkmf tasks to Makefile generation' do Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/Makefile"].prerequisites.should include("tmp/universal-unknown/extension_one/#{@ruby_ver}/mkmf.rb") end it 'should take mkmf from rake-compiler configuration' do mkmf_path = File.expand_path(File.join(File.dirname(@config_path), '..', 'mkmf.rb')) Rake::Task["tmp/universal-unknown/extension_one/#{@ruby_ver}/mkmf.rb"].prerequisites.should include(mkmf_path) end end context 'compile:universal-unknown' do it "should be defined" do Rake::Task.task_defined?('compile:universal-unknown').should be_true end it "should depend on 'compile:extension_one:universal-unknown'" do Rake::Task['compile:universal-unknown'].prerequisites.should include('compile:extension_one:universal-unknown') end end context 'native:universal-unknown' do it "should be defined" do Rake::Task.task_defined?('native:universal-unknown').should be_true end it "should depend on 'native:my_gem:universal-unknown'" do Rake::Task['native:universal-unknown'].prerequisites.should include('native:my_gem:universal-unknown') end end end context '(cross for multiple platforms)' do before :each do @ext = Rake::ExtensionTask.new('extension_one', @spec) do |ext| ext.cross_compile = true ext.cross_platform = ['universal-known', 'universal-unknown'] ext.cross_config_options << '--with-something' ext.cross_config_options << {'universal-known' => '--with-known'} end end it 'should define task for each supplied platform' do Rake::Task.should have_defined('compile:universal-known') Rake::Task.should have_defined('compile:universal-unknown') end it 'should filter options for each supplied platform' do @ext.cross_config_options('universal-unknown').should eq(%w[--with-something]) @ext.cross_config_options('universal-known').should eq(%w[--with-something --with-known]) end end end end private def ext_bin(extension_name) "#{extension_name}.#{RbConfig::CONFIG['DLEXT']}" end def mock_gem_spec(stubs = {}) mock(Gem::Specification, { :name => 'my_gem', :platform => 'ruby', :files => [] }.merge(stubs) ) end def mock_config_yml return @mock_config_yml if @mock_config_yml versions = { "1.8.6" => "1.8", "1.8.7" => "1.8", "1.9.3" => "1.9.1", "2.0.0" => "2.0.0", "2.1.2" => "2.1.0", RUBY_VERSION => RbConfig::CONFIG["ruby_version"] } platforms = [ "i386-mingw32", "universal-known", "universal-unknown", "x64-mingw32", RUBY_PLATFORM ] @mock_config_yml = {} platforms.collect do |platform| versions.each do |version, api_version| @mock_config_yml["rbconfig-#{platform}-#{version}"] = "/rubies/#{api_version}/rbconfig.rb" end end @mock_config_yml end def mock_fake_rb mock(File, :write => 45) end end rake-compiler-0.9.5/spec/support/0000755000004100000410000000000012457522125016762 5ustar www-datawww-datarake-compiler-0.9.5/spec/support/capture_output_helper.rb0000644000004100000410000000063312457522125023733 0ustar www-datawww-datamodule CaptureOutputHelper def capture_output(&block) old_stdout = $stdout old_stderr = $stderr stream_out = StringIO.new stream_err = StringIO.new begin $stdout = stream_out $stderr = stream_err yield ensure $stdout = old_stdout $stderr = old_stderr end stream_out.rewind stream_err.rewind [stream_out.read, stream_err.read] end end rake-compiler-0.9.5/README.rdoc0000644000004100000410000003443612457522125016134 0ustar www-datawww-data= What is rake-compiler? rake-compiler is first and foremost a productivity tool for Ruby developers. It's goal is to make the busy developer's life easier by simplifying the building and packaging of Ruby extensions by simplifying code and reducing duplication. It follows *convention over configuration* by advocating a standardized build and package structure for both C and Java based RubyGems. rake-compiler is the result of many hard-won experiences dealing with several diverse RubyGems that provided native extensions for different platforms and different user configurations in different ways. Details such as differences in code portability, differences in code clarity, and differences in project directory structure often made it very difficult for newcomers to those RubyGems. From these challenges, rake-compiler was born with the single-minded goal of making the busy RubyGem developer's life much less difficult. == Feature Overview Some of the benefits rake-compiler provides include: * No custom rake tasks required. Less code duplication and errors. * Painlessly build extensions on different platforms (Linux, OSX and Windows). * Painlessly build extensions for different Ruby implementations (JRuby, Rubinius and MRI). * Allow multiple extensions to be compiled inside the same gem. * Painlessly build "fat" native gems for Windows users (from Linux or OSX). * Mimics RubyGems standard installation process, helping as a test environment. * Simplifies cross platform extension compilation (targeting Windows from Linux). == OK, I'm sold! Show me how to install it! Simple: $ gem install rake-compiler == That's easy. How do I use it? Now that you have installed rake-compiler, it's time to give your project a standardized structure. === Using a standardized project structure Let's say you want to compile an extension called 'hello_world'. Organizing your project's code tree in the following way will help rake-compiler do its job: |-- ext | `-- hello_world | |-- extconf.rb | |-- HelloWorldService.java | `-- hello_world.c |-- lib `-- Rakefile TIP: Having a consistent project directory structure will help developers and newcomers find and understand your code, making it easier for them to contribute back to your project. === Adding the code to enable rake-compiler Now the fun part. It's time to introduce the code to your projects Rakefile to tell it to use rake-compiler to build your extension: # File: extconf.rb # these lines must exist already require 'mkmf' create_makefile('hello_world') # File: Rakefile require 'rake/extensiontask' Rake::ExtensionTask.new('hello_world') That's it? Yes, that's it! No other lines of code are needed for rake-compiler to work its magic. Though, you need to make sure the parameter to create_makefile and ExtensionTask.new are the same or rake-compiler will not mimic the RubyGems standard install process. You can override this standard behaviour if needed, see the instructions for "non-standard project structure" below for details. If you want to do the same for a JRuby extension written in Java, it's just as easy: # File: Rakefile require 'rake/javaextensiontask' Rake::JavaExtensionTask.new('hello_world') === The simple process Those *two* simple lines of code automatically added the Rake tasks needed to build your 'hello_world' extension. For example, checking the Rake tasks on MRI Ruby 1.8.x/1.9 returns something similar to: $ rake -T (in /home/user/my_extension) rake compile # Compile the extension(s) rake compile:hello_world # Compile just the hello_world extension Simply calling compile like $ rake compile performs the entire compile and build process for you and places the resulting extension inside the lib directory of your project. NOTE: Please be aware that building C extensions requires the proper development environment for your Platform, including libraries, headers and build tools. Check your distro / vendor documentation on how to install these development resources. NOTE: Building Java extensions requires the javac, part of the Java Development Kit (JDK). This should be included by default on Mac OS X, and downloadable from http://java.sun.com for other operating systems. === Generating native RubyGems A common usage scenario for rake-compiler is generating native gems that bundle your extensions. As mentioned above, if you have your development environment configured correctly, the following examples work even when building native gems on Windows systems. Creating native gems is really easy with rake-compiler's Rake::ExtensionTask: # somewhere in your Rakefile, define your gem spec spec = Gem::Specification.new do |s| s.name = "my_gem" s.platform = Gem::Platform::RUBY s.extensions = FileList["ext/**/extconf.rb"] end # add your default gem packing task Gem::PackageTask.new(spec) do |pkg| end # feed the ExtensionTask with your spec Rake::ExtensionTask.new('hello_world', spec) As expected, you can still build your pure-ruby gem in the usual way (standard output) by running: $ rake gem (in /projects/oss/my_gem.git) mkdir -p pkg Successfully built RubyGem Name: my_gem Version: 0.1.0 File: my_gem-0.1.0.gem mv my_gem-0.1.0.gem pkg/my_gem-0.1.0.gem Plus, rake-compiler tasks give you the extra functionality needed to build native gems by running: # rake native gem (... compilation output ...) mkdir -p pkg Successfully built RubyGem Name: my_gem Version: 0.1.0 File: my_gem-0.1.0.gem mv my_gem-0.1.0.gem pkg/my_gem-0.1.0.gem Successfully built RubyGem Name: my_gem Version: 0.1.0 File: my_gem-0.1.0-x86-mingw32.gem mv my_gem-0.1.0-x86-mingw32.gem pkg/my_gem-0.1.0-x86-mingw32.gem Did you notice that you get two gems for the price of one? How's that for a time saver? Similarly, it's just as easy to do the same thing for JRuby extensions: # rake java gem (... compilation output ...) mkdir -p pkg Successfully built RubyGem Name: my_gem Version: 0.1.0 File: my_gem-0.1.0.gem mv my_gem-0.1.0.gem pkg/my_gem-0.1.0.gem Successfully built RubyGem Name: my_gem Version: 0.1.0 File: my_gem-0.1.0-java.gem mv my_gem-0.1.0-java.gem pkg/my_gem-0.1.0-java.gem === Great, but can I use a non-standard project structure? Yes you can! While the conventional project structure is recommended, you may want, or need, to tweak those conventions. Rake-compiler allows you to customize several settings for Rake::ExtensionTask: Rake::ExtensionTask.new do |ext| ext.name = 'hello_world' # indicate the name of the extension. ext.ext_dir = 'ext/weird_world' # search for 'hello_world' inside it. ext.lib_dir = 'lib/my_lib' # put binaries into this folder. ext.config_script = 'custom_extconf.rb' # use instead of the default 'extconf.rb'. ext.tmp_dir = 'tmp' # temporary folder used during compilation. ext.source_pattern = "*.{c,cpp}" # monitor file changes to allow simple rebuild. ext.config_options << '--with-foo' # supply additional options to configure script. ext.gem_spec = spec # optionally indicate which gem specification # will be used. end == Cross compilation - the future is now. Rake-compiler also provides a standardized way to generate, from either Linux or OSX, extensions and gem binaries for your Windows users! How can this be you say? Simple, rake-compiler's cross compilation features take advantage of GCC's host/target capabilities to build 'target' binaries on different 'host' OS's. === How do I do this from Linux or OSX? ==== The Easy Way Use rake-compiler-dev-box, a virtual machine provisioned with all the necessary build tools. With one command, you can cross-compile and package your gem into native, Java, and Windows fat binaries (with 1.8, 1.9, and 2.0 support). See https://github.com/tjschuck/rake-compiler-dev-box for more information. ==== The Manual Way In addition to having the development tool chain installed (GCC), you also need to install your platform's mingw32 cross compilation package. Installation depends upon your operating system/distribution. On Ubuntu and Debian host machines, a simple apt-get install mingw32 will be enough. On Arch, mingw32 is installed by running pacman -S mingw32-gcc On OSX, we no longer recommend the usage of MacPorts mingw32 package because it stagnated in GCC version 3.4.5. Instead we recommend you download mingw-w64 automated build packages available at SourceForge: http://sourceforge.net/downloads/mingw-w64/ Browse into Toolchains targetting Win32 and then Automated Builds. Files will be ordered by recency, find the latest one with version 1.0 in it, like this one: mingw-w32-1.0-bin_i686-darwin_20110422.tar.bz2 Download and extract. After that, make sure the bin directory is added to the PATH, eg: export PATH=~/mingw-w64/w32/bin:$PATH You can add this to your .profile to avoid the repitition. ==== I've got my tool-chain installed, now what? First, you need to build Ruby for Windows on your Linux or OSX system. Relax, no need to freak out! Let rake-compiler do all the heavy lifting for you: rake-compiler cross-ruby And you're done. It will automatically download, configure and compile the latest stable version of Ruby for Windows, and place it into your ~/.rake-compiler directory. This will create ~/.rake-compiler/config.yml file so that rake-compiler knows where to find the rbconfig.rb file that matches the Ruby version on the Windows host system you're cross-compiling for. An example: # File: ~/.rake-compiler/config.yml rbconfig-i386-mingw32-1.8.6: /path/to/ruby-1.8.6/rbconfig.rb rbconfig-i386-mingw32-1.8.7: /path/to/ruby-1.8.7/rbconfig.rb rbconfig-i386-mingw32-1.9.2: /path/to/ruby-1.9.2/rbconfig.rb If, instead, you want to build a different Ruby version than the default one, please supply a VERSION: rake-compiler cross-ruby VERSION=1.8.6-p114 If you, like me, have multiple versions of MinGW packages installed, you can specify the HOST that will be used to cross compile Ruby: rake-compiler cross-ruby HOST=i386-mingw32 # (OSX mingw32 port) The host will vary depending on provider (mingw32 versus mingw-w64 projects). Please consult the documentation and website of the MinGW package provider before reporting any issues. ==== OK, let's cross compile some gems! Now, you only need specify a few additional options in your extension definition: Rake::ExtensionTask.new('my_extension', gem_spec) do |ext| ext.cross_compile = true # enable cross compilation (requires cross compile toolchain) ext.cross_platform = 'i386-mswin32-60' # forces the Windows platform instead of the default one # configure options only for cross compile ext.cross_config_options << '--with-something' # perform alterations on the gemspec when cross compiling ext.cross_compiling do |gem_spec| gem_spec.post_install_message = "You installed the binary version of this gem!" end end By default, cross compilation targets 'i386-mingw32' which is the default GCC platform for Ruby. To target gems for MRI Ruby's current official distribution, please force the platform to the one (i386-mswin32-60) previously shown. ==== Warning, magician about to do some tricks, don't blink! Cross compiling is still very simple: rake cross compile And now, building gems for your Windows users is just 5 more letters: rake cross native gem And you're done, yeah. ==== But wait, there's more You can specify which version of Ruby to build the extension against: rake cross compile RUBY_CC_VERSION=1.8.6 For example, if you installed 1.9.2, you can do: rake cross compile RUBY_CC_VERSION=1.9.2 Even better, you can target multiple versions (ie. 1.8.6 and 1.9.2) in the same gem via: rake cross compile RUBY_CC_VERSION=1.8.6:1.9.2 And better yet, you can bundle both binary extensions into one so-called "fat" gem via: rake cross native gem RUBY_CC_VERSION=1.8.6:1.9.2 That will place binaries for both the 1.8 and 1.9 versions of your Ruby extensions inside your project's lib_dir directory: lib/1.8/my_extension.so lib/1.9/my_extension.so NOTE: building "fat" gems is currently only supported by rake-compiler when cross compiling from a Linux or OSX host. Patches are welcome if building "fat" gems from Windows hosts is desired, or natively for your platform :-) Now is up to you to make your gem load the proper binary at runtime: begin RUBY_VERSION =~ /(\d+.\d+)/ require "#{$1}/my_extension" rescue LoadError require "my_extension" end The above technique will lookup first for 1.8 or 1.9 version of the extension and when not found, will look for the plain extension. This approach catch the cases of provided fat binaries or gems compiled by the end user installing the gem. It has also been implemented successfully in several projects. == What are you talking about? (Give me examples) I know all the above sounds like a complete foreign language (it does even for me!). So, what if I show you some examples? Check our wiki with links to the proper rake files used by many developers and projects and how they use rake-compiler. http://github.com/rake-compiler/rake-compiler/wiki/projects-using-rake-compiler == Future rake-compiler is a work in progress and we appreciate any and all feedback during the development of it! (and contributions too!) You can find more information about rake-compiler: * GitHub: https://github.com/rake-compiler/rake-compiler * Issues: https://github.com/rake-compiler/rake-compiler/issues * Docs: http://rubydoc.info/gems/rake-compiler * Wiki: https://github.com/rake-compiler/rake-compiler/wiki == Disclaimer If you have any trouble, don't hesitate to contact the author. As always, I'm not going to say "Use at your own risk" because I don't want this library to be risky. If you trip on something, I'll share the liability by repairing things as quickly as I can. Your responsibility is to report the inadequacies. rake-compiler-0.9.5/lib/0000755000004100000410000000000012457522125015062 5ustar www-datawww-datarake-compiler-0.9.5/lib/rake/0000755000004100000410000000000012457522125016004 5ustar www-datawww-datarake-compiler-0.9.5/lib/rake/extensioncompiler.rb0000755000004100000410000000275112457522125022110 0ustar www-datawww-data#!/usr/bin/env ruby module Rake # # HACK: Lousy API design, sue me. At least works ;-) # # Define a series of helpers to aid in search and usage of MinGW (GCC) Compiler # by gem developer/creators. # module ExtensionCompiler # return the host portion from the installed MinGW def self.mingw_host return @mingw_host if @mingw_host # the mingw_gcc_executable is helpful here if target = mingw_gcc_executable then # we only care for the filename target = File.basename(target) # now strip the extension (if present) target.sub!(File.extname(target), '') # get rid of '-gcc' portion too ;-) target.sub!('-gcc', '') end raise "No MinGW tools or unknown setup platform?" unless target @mingw_host = target end # return the first compiler found that includes both mingw and gcc conditions # (this assumes you have one installed) def self.mingw_gcc_executable return @mingw_gcc_executable if @mingw_gcc_executable # grab the paths defined in the environment paths = ENV['PATH'].split(File::PATH_SEPARATOR) # the pattern to look into (captures *nix and windows executables) pattern = "{mingw32-,i?86*mingw*}gcc{,.*}" @mingw_gcc_executable = paths.find do |path| # cleanup paths before globbing gcc = Dir.glob("#{File.expand_path(path)}/#{pattern}").first break gcc if gcc end @mingw_gcc_executable end end end rake-compiler-0.9.5/lib/rake/baseextensiontask.rb0000644000004100000410000000325112457522125022064 0ustar www-datawww-data#!/usr/bin/env ruby require 'rake' require 'rake/clean' require 'rake/tasklib' require 'rbconfig' begin require 'psych' rescue LoadError end require 'yaml' require 'pathname' module Rake class BaseExtensionTask < TaskLib attr_accessor :name attr_accessor :gem_spec attr_accessor :tmp_dir attr_accessor :ext_dir attr_accessor :lib_dir attr_accessor :platform attr_accessor :config_options attr_accessor :source_pattern attr_accessor :extra_options def platform @platform ||= RUBY_PLATFORM end def initialize(name = nil, gem_spec = nil) init(name, gem_spec) yield self if block_given? define end def init(name = nil, gem_spec = nil) @name = name @gem_spec = gem_spec @tmp_dir = 'tmp' @ext_dir = "ext/#{@name}" @lib_dir = 'lib' @config_options = [] @extra_options = ARGV.select { |i| i =~ /\A--?/ } end def define fail "Extension name must be provided." if @name.nil? define_compile_tasks end private def define_compile_tasks raise NotImplementedError end def binary(platform = nil) ext = case platform when /darwin/ 'bundle' when /mingw|mswin|linux/ 'so' when /java/ 'jar' else RbConfig::CONFIG['DLEXT'] end "#{@name}.#{ext}" end def source_files FileList["#{@ext_dir}/#{@source_pattern}"] end def warn_once(message) @@already_warned ||= false return if @@already_warned @@already_warned = true warn message end def windows? Rake.application.windows? end end end rake-compiler-0.9.5/lib/rake/extensiontask.rb0000755000004100000410000004154312457522125021242 0ustar www-datawww-data#!/usr/bin/env ruby require 'rake/baseextensiontask' require "rubygems/package_task" # Define a series of tasks to aid in the compilation of C extensions for # gem developer/creators. module Rake class ExtensionTask < BaseExtensionTask attr_accessor :config_script attr_accessor :cross_compile attr_accessor :cross_platform attr_writer :cross_config_options attr_accessor :no_native attr_accessor :config_includes def init(name = nil, gem_spec = nil) super @config_script = 'extconf.rb' @source_pattern = "*.c" @compiled_pattern = "*.{o,obj,so,bundle,dSYM}" @cross_compile = false @cross_config_options = [] @cross_compiling = nil @no_native = false @config_includes = [] end def cross_platform @cross_platform ||= 'i386-mingw32' end def cross_compiling(&block) @cross_compiling = block if block_given? end def binary(platform = nil) if platform == "java" "#{name}.#{RbConfig::MAKEFILE_CONFIG['DLEXT']}" else super end end def define if (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby') warn_once <<-EOF 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. EOF return end super unless compiled_files.empty? warn "WARNING: rake-compiler found compiled files in '#{@ext_dir}' directory. Please remove them." end # only gems with 'ruby' platforms are allowed to define native tasks define_native_tasks if !@no_native && (@gem_spec && @gem_spec.platform == 'ruby') # only define cross platform functionality when enabled 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 def cross_config_options(for_platform=nil) return @cross_config_options unless for_platform # apply options for this platform, only @cross_config_options.map do |option| if option.kind_of?(Hash) option[for_platform] || [] else option end end.flatten end private # copy other gem files to staging directory def define_staging_file_tasks(files, lib_path, stage_path, platf, ruby_ver) files.each do |gem_file| # ignore directories and the binary extension next if File.directory?(gem_file) || gem_file == "#{lib_path}/#{binary(platf)}" stage_file = "#{stage_path}/#{gem_file}" # copy each file from base to stage directory unless Rake::Task.task_defined?(stage_file) then directory File.dirname(stage_file) file stage_file => [File.dirname(stage_file), gem_file] do cp gem_file, stage_file end end # append each file to the copy task task "copy:#{@name}:#{platf}:#{ruby_ver}" => [stage_file] end end 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}/#{ruby_ver}" stage_path = "#{@tmp_dir}/#{platf}/stage" # cleanup and clobbering CLEAN.include(tmp_path) CLEAN.include(stage_path) CLOBBER.include("#{lib_path}/#{binary(platf)}") CLOBBER.include("#{@tmp_dir}") # directories we need directory tmp_path directory "#{stage_path}/#{lib_path}" directory lib_dir # copy binary from temporary location to final lib # tmp/extension_name/extension_name.{so,bundle} => lib/ task "copy:#{@name}:#{platf}:#{ruby_ver}" => [lib_path, "#{tmp_path}/#{binary(platf)}"] do install "#{tmp_path}/#{binary(platf)}", "#{lib_path}/#{binary(platf)}" end # copy binary from temporary location to staging directory task "copy:#{@name}:#{platf}:#{ruby_ver}" => ["#{stage_path}/#{lib_path}", "#{tmp_path}/#{binary(platf)}"] do cp "#{tmp_path}/#{binary(platf)}", "#{stage_path}/#{lib_path}/#{binary(platf)}" end # copy other gem files to staging directory define_staging_file_tasks(@gem_spec.files, lib_path, stage_path, platf, ruby_ver) if @gem_spec # 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 jruby_compile_msg = <<-EOF Compiling a native C extension on JRuby. This is discouraged and a Java extension should be preferred. EOF warn_once(jruby_compile_msg) if defined?(JRUBY_VERSION) chdir tmp_path do sh make end end # makefile depends of tmp_dir and config_script # tmp/extension_name/Makefile file "#{tmp_path}/Makefile" => [tmp_path, extconf] do |t| options = @config_options.dup # include current directory include_dirs = ['.'].concat(@config_includes).uniq.join(File::PATH_SEPARATOR) cmd = [Gem.ruby, "-I#{include_dirs}"] # build a relative path to extconf script abs_tmp_path = (Pathname.new(Dir.pwd) + tmp_path).realpath abs_extconf = (Pathname.new(Dir.pwd) + extconf).realpath # now add the extconf script cmd << abs_extconf.relative_path_from(abs_tmp_path) # rbconfig.rb will be present if we are cross compiling if t.prerequisites.include?("#{tmp_path}/rbconfig.rb") then options.push(*cross_config_options(platf)) end # add options to command cmd.push(*options) # add any extra command line options unless extra_options.empty? cmd.push(*extra_options) end chdir tmp_path do # FIXME: Rake is broken for multiple arguments system() calls. # Add current directory to the search path of Ruby sh cmd.join(' ') end end # compile tasks unless Rake::Task.task_defined?('compile') then desc "Compile all the extensions" task "compile" end # compile:name unless Rake::Task.task_defined?("compile:#{@name}") then desc "Compile #{@name}" task "compile:#{@name}" end # Allow segmented compilation by platform (open door for 'cross compile') 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_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, ruby_ver = RUBY_VERSION, callback = nil) platf = for_platform || platform # tmp_path tmp_path = "#{@tmp_dir}/#{platf}/#{@name}/#{ruby_ver}" stage_path = "#{@tmp_dir}/#{platf}/stage" # 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: workaround Gem::Specification limitation around cache_file: # http://github.com/rubygems/rubygems/issues/78 spec = gem_spec.dup spec.instance_variable_set(:"@cache_file", nil) if spec.respond_to?(:cache_file) # adjust to specified platform spec.platform = Gem::Platform.new(platf) # clear the extensions defined in the specs spec.extensions.clear # add the binaries that this task depends on ext_files = [] # go through native prerequisites and grab the real extension files from there t.prerequisites.each do |ext| # strip stage path and keep lib/... only ext_files << ext.sub(stage_path+"/", '') end # include the files in the gem specification spec.files += ext_files # expose gem specification for customization callback.call(spec) if callback # Generate a package for this gem pkg = Gem::PackageTask.new(spec) do |pkg| pkg.need_zip = false pkg.need_tar = false # Do not copy any files per PackageTask, because # we need the files from the staging directory pkg.package_files.clear end # copy other gem files to staging directory if added by the callback define_staging_file_tasks(spec.files, lib_path, stage_path, platf, ruby_ver) # Copy from staging directory to gem package directory. # This is derived from the code of Gem::PackageTask # but uses stage_path as source directory. stage_files = spec.files.map do |gem_file| File.join(stage_path, gem_file) end file pkg.package_dir_path => stage_files do mkdir_p pkg.package_dir rescue nil spec.files.each do |ft| fn = File.join(stage_path, ft) f = File.join(pkg.package_dir_path, ft) fdir = File.dirname(f) mkdir_p(fdir) if !File.exist?(fdir) if File.directory?(fn) mkdir_p(f) else rm_f f safe_ln(fn, f) end end end end end # add binaries to the dependency chain task "native:#{@gem_spec.name}:#{platf}" => ["#{stage_path}/#{lib_dir}/#{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 file "#{stage_path}/#{lib_dir}/#{binary(platf)}" => ["copy:#{@name}:#{platf}:#{ruby_ver}"] # Allow segmented packaging by platform (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. if platf == RUBY_PLATFORM then task "native:#{@gem_spec.name}" => ["native:#{@gem_spec.name}:#{platf}"] 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(':') 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") # warn the user about the need of configuration to use cross compilation. unless File.exist?(config_path) define_dummy_cross_platform_tasks return end config_file = YAML.load_file(config_path) # tmp_path tmp_path = "#{@tmp_dir}/#{for_platform}/#{@name}/#{ruby_ver}" # lib_path lib_path = lib_dir unless rbconfig_file = config_file["rbconfig-#{for_platform}-#{ruby_ver}"] then warn "no configuration section for specified version of Ruby (rbconfig-#{for_platform}-#{ruby_ver})" return end # mkmf mkmf_file = File.expand_path(File.join(File.dirname(rbconfig_file), '..', 'mkmf.rb')) # define compilation tasks for cross platform! define_compile_tasks(for_platform, ruby_ver) # 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| File.open(t.name, 'w') do |f| f.write "require 'fake.rb'\n\n" f.write File.read(t.prerequisites.first) end end # copy mkmf from cross-ruby location file "#{tmp_path}/mkmf.rb" => [mkmf_file] do |t| cp t.prerequisites.first, t.name if ruby_ver < "1.9" && "1.9" <= RUBY_VERSION File.open(t.name, 'r+t') do |f| content = f.read content.sub!(/^( break )\*(defaults)$/, '\\1\\2.first') content.sub!(/^( return )\*(defaults)$/, '\\1\\2.first') content.sub!(/^( mfile\.)print( configuration\(srcprefix\))$/, '\\1puts\\2') f.rewind f.write content f.truncate(f.tell) end end 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(for_platform, ruby_ver) end end # now define native tasks for cross compiled files if @gem_spec && @gem_spec.platform == 'ruby' then define_native_tasks(for_platform, ruby_ver, @cross_compiling) end # create cross task task 'cross' do # clear compile dependencies Rake::Task['compile'].prerequisites.reject! { |t| !compiles_cross_platform.include?(t) } # 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_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_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 Rake::Task['native'].prerequisites.reject! { |t| !natives_cross_platform.include?(t) } task 'native' => ["native:#{for_platform}"] end end end def define_dummy_cross_platform_tasks task 'cross' do Rake::Task['compile'].clear task 'compile' do raise "rake-compiler must be configured first to enable cross-compilation" end end end def extconf "#{@ext_dir}/#{@config_script}" end def make unless @make @make = if RUBY_PLATFORM =~ /mswin/ then 'nmake' else ENV['MAKE'] || %w[gmake make].find { |c| system("#{c} -v >> #{dev_null} 2>&1") } end end unless @make raise "Couldn't find a suitable `make` tool. Use `MAKE` env to set an alternative." end @make end def dev_null windows? ? 'NUL' : '/dev/null' end def compiled_files FileList["#{@ext_dir}/#{@compiled_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(platform, version) <<-FAKE_RB # Pre-load resolver library before faking, in order to avoid error # "cannot load such file -- win32/resolv" when it is required later on. # See also: https://github.com/tjschuck/rake-compiler-dev-box/issues/5 require 'resolv' class Object remove_const :RUBY_PLATFORM remove_const :RUBY_VERSION remove_const :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION) RUBY_PLATFORM = "#{platform}" RUBY_VERSION = "#{version}" RUBY_DESCRIPTION = "ruby \#{RUBY_VERSION} (\#{RUBY_RELEASE_DATE}) [\#{RUBY_PLATFORM}]" end if RUBY_PLATFORM =~ /mswin|bccwin|mingw/ class File remove_const :ALT_SEPARATOR ALT_SEPARATOR = "\\\\" end end posthook = proc do $ruby = "#{Gem.ruby}" untrace_var(:$ruby, posthook) end trace_var(:$ruby, posthook) FAKE_RB end end end rake-compiler-0.9.5/lib/rake/javaextensiontask.rb0000644000004100000410000001606112457522125022076 0ustar www-datawww-data#!/usr/bin/env ruby require 'rake/baseextensiontask' # Define a series of tasks to aid in the compilation of Java extensions for # gem developer/creators. module Rake class JavaExtensionTask < BaseExtensionTask attr_accessor :classpath attr_accessor :debug # Provide source compatibility with specified release attr_accessor :source_version # Generate class files for specific VM version attr_accessor :target_version def platform @platform ||= 'java' end def java_compiling(&block) @java_compiling = block if block_given? end def init(name = nil, gem_spec = nil) super @source_pattern = '**/*.java' @classpath = nil @java_compiling = nil @debug = false @source_version = '1.5' @target_version = '1.5' end def define super define_java_platform_tasks end private 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}" # cleanup and clobbering CLEAN.include(tmp_path) 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_path, "#{tmp_path}/#{binary(platf)}"] do install "#{tmp_path}/#{binary(platf)}", "#{lib_path}/#{binary(platf)}" end file "#{tmp_path}/#{binary(platf)}" => "#{tmp_path}/.build" do class_files = FileList["#{tmp_path}/**/*.class"]. gsub("#{tmp_path}/", '') # avoid environment variable expansion using backslash class_files.gsub!('$', '\$') unless windows? args = class_files.map { |path| ["-C #{tmp_path}", path] }.flatten sh "jar cf #{tmp_path}/#{binary(platf)} #{args.join(' ')}" end file "#{tmp_path}/.build" => [tmp_path] + source_files do not_jruby_compile_msg = <<-EOF WARNING: You're cross-compiling a binary extension for JRuby, but are using another interpreter. If your Java classpath or extension dir settings are not correctly detected, then either check the appropriate environment variables or execute the Rake compilation task using the JRuby interpreter. (e.g. `jruby -S rake compile:java`) EOF warn_once(not_jruby_compile_msg) unless defined?(JRUBY_VERSION) classpath_arg = java_classpath_arg(@classpath) debug_arg = @debug ? '-g' : '' sh "javac #{java_extdirs_arg} -target #{@target_version} -source #{@source_version} -Xlint:unchecked #{debug_arg} #{classpath_arg} -d #{tmp_path} #{source_files.join(' ')}" # Checkpoint file touch "#{tmp_path}/.build" end # compile tasks unless Rake::Task.task_defined?('compile') then desc "Compile all the extensions" task "compile" end # compile:name unless Rake::Task.task_defined?("compile:#{@name}") then 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:#{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_path}/#{binary(platf)}" => ["copy:#{name}:#{platf}"] task "compile:#{@name}" => ["compile:#{@name}:#{platf}"] task "compile" => ["compile:#{platf}"] end end def define_java_platform_tasks # lib_path lib_path = lib_dir if @gem_spec && !Rake::Task.task_defined?("java:#{@gem_spec.name}") task "java:#{@gem_spec.name}" do |t| # FIXME: workaround Gem::Specification limitation around cache_file: # http://github.com/rubygems/rubygems/issues/78 spec = gem_spec.dup spec.instance_variable_set(:"@cache_file", nil) if spec.respond_to?(:cache_file) # adjust to specified platform spec.platform = Gem::Platform.new('java') # clear the extensions defined in the specs spec.extensions.clear # add the binaries that this task depends on 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 # expose gem specification for customization if @java_compiling @java_compiling.call(spec) end # Generate a package for this gem Gem::PackageTask.new(spec) do |pkg| pkg.need_zip = false pkg.need_tar = false end end # add binaries to the dependency chain task "java:#{@gem_spec.name}" => ["#{lib_path}/#{binary(platform)}"] # ensure the extension get copied unless Rake::Task.task_defined?("#{lib_path}/#{binary(platform)}") then file "#{lib_path}/#{binary(platform)}" => ["copy:#{name}:#{platform}"] end task 'java' => ["java:#{@gem_spec.name}"] end task 'java' do task 'compile' => 'compile:java' end end # # Discover Java Extension Directories and build an extdirs argument # def java_extdirs_arg extdirs = Java::java.lang.System.getProperty('java.ext.dirs') rescue nil extdirs = ENV['JAVA_EXT_DIR'] unless extdirs java_extdir = extdirs.nil? ? "" : "-extdirs \"#{extdirs}\"" end # # Discover the Java/JRuby classpath and build a classpath argument # # @params # *args:: Additional classpath arguments to append # # Copied verbatim from the ActiveRecord-JDBC project. There are a small myriad # of ways to discover the Java classpath correctly. # def java_classpath_arg(*args) jruby_cpath = nil if RUBY_PLATFORM =~ /java/ begin cpath = Java::java.lang.System.getProperty('java.class.path').split(File::PATH_SEPARATOR) cpath += Java::java.lang.System.getProperty('sun.boot.class.path').split(File::PATH_SEPARATOR) jruby_cpath = cpath.compact.join(File::PATH_SEPARATOR) rescue => e end end unless jruby_cpath jruby_cpath = ENV['JRUBY_PARENT_CLASSPATH'] || ENV['JRUBY_HOME'] && Dir.glob("#{File.expand_path(ENV['JRUBY_HOME'])}/lib/*.jar"). join(File::PATH_SEPARATOR) end raise "JRUBY_HOME or JRUBY_PARENT_CLASSPATH are not set" unless jruby_cpath jruby_cpath += File::PATH_SEPARATOR + args.join(File::PATH_SEPARATOR) unless args.empty? jruby_cpath ? "-cp \"#{jruby_cpath}\"" : "" end end end rake-compiler-0.9.5/cucumber.yml0000644000004100000410000000026012457522125016642 0ustar www-datawww-datadefault: --tags ~@java --format progress features java: --tags @java --format progress features all: --format progress features autotest: --format progress features rake-compiler-0.9.5/metadata.yml0000644000004100000410000000671512457522125016630 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: rake-compiler version: !ruby/object:Gem::Version version: 0.9.5 platform: ruby authors: - Kouhei Sutou - Luis Lavena autorequire: bindir: bin cert_chain: [] date: 2015-01-03 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rspec requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 2.8.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 2.8.0 - !ruby/object:Gem::Dependency name: cucumber requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 1.1.4 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 1.1.4 description: |- Provide a standard and simplified way to build and package Ruby extensions (C, Java) using Rake as glue. email: - kou@cozmixng.org - luislavena@gmail.com executables: - rake-compiler extensions: [] extra_rdoc_files: - README.rdoc - LICENSE.txt - History.txt files: - Gemfile - History.txt - LICENSE.txt - README.rdoc - Rakefile - appveyor.yml - bin/rake-compiler - cucumber.yml - features/compile.feature - features/cross-compile.feature - features/cross-package-multi.feature - features/cross-package.feature - features/java-compile.feature - features/java-no-native-compile.feature - features/java-package.feature - features/package.feature - features/step_definitions/compilation.rb - features/step_definitions/cross_compilation.rb - features/step_definitions/execution.rb - features/step_definitions/folders.rb - features/step_definitions/gem.rb - features/step_definitions/java_compilation.rb - features/support/env.rb - features/support/file_template_helpers.rb - features/support/generator_helpers.rb - features/support/platform_extension_helpers.rb - lib/rake/baseextensiontask.rb - lib/rake/extensioncompiler.rb - lib/rake/extensiontask.rb - lib/rake/javaextensiontask.rb - spec/lib/rake/extensiontask_spec.rb - spec/lib/rake/javaextensiontask_spec.rb - spec/spec.opts - spec/spec_helper.rb - spec/support/capture_output_helper.rb - tasks/bin/cross-ruby.rake - tasks/bootstrap.rake - tasks/common.rake - tasks/cucumber.rake - tasks/gem.rake - tasks/news.rake - tasks/release.rake - tasks/rspec.rake homepage: https://github.com/rake-compiler/rake-compiler licenses: - MIT metadata: {} post_install_message: rdoc_options: - "--main" - README.rdoc - "--title" - rake-compiler -- Documentation require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.8.7 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 1.8.23 requirements: [] rubyforge_project: rake-compiler rubygems_version: 2.2.2 signing_key: specification_version: 4 summary: Rake-based Ruby Extension (C, Java) task generator. test_files: [] rake-compiler-0.9.5/tasks/0000755000004100000410000000000012457522125015441 5ustar www-datawww-datarake-compiler-0.9.5/tasks/bin/0000755000004100000410000000000012457522125016211 5ustar www-datawww-datarake-compiler-0.9.5/tasks/bin/cross-ruby.rake0000644000004100000410000001521712457522125021173 0ustar www-datawww-data#-- # 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-p371") 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', '') # Unset any possible variable that might affect compilation ["CC", "CXX", "CPPFLAGS", "LDFLAGS", "RUBYOPT"].each do |var| ENV.delete(var) end # define a location where sources will be stored directory "#{USER_HOME}/sources/#{RUBY_CC_VERSION}" directory "#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}" # clean intermediate files and folders CLEAN.include("#{USER_HOME}/sources/#{RUBY_CC_VERSION}") CLEAN.include("#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}") # remove the final products and sources CLOBBER.include("#{USER_HOME}/sources") CLOBBER.include("#{USER_HOME}/builds") CLOBBER.include("#{USER_HOME}/ruby/#{MINGW_HOST}/#{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://cache.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/#{MINGW_HOST}/#{RUBY_CC_VERSION}/Makefile" => ["#{USER_HOME}/builds/#{MINGW_HOST}/#{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/#{MINGW_HOST}/#{RUBY_CC_VERSION}") options << "--prefix=#{prefix}" sh File.expand_path("../../../sources/#{RUBY_CC_VERSION}/configure"), *options end end # make file "#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/ruby.exe" => ["#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/Makefile"] do |t| chdir File.dirname(t.prerequisites.first) do sh MAKE end end # make install file "#{USER_HOME}/ruby/#{MINGW_HOST}/#{RUBY_CC_VERSION}/bin/ruby.exe" => ["#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/ruby.exe"] do |t| chdir File.dirname(t.prerequisites.first) do sh "#{MAKE} install" end end task :install => ["#{USER_HOME}/ruby/#{MINGW_HOST}/#{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, platform = rbconfig.match(/.*-(\d.\d.\d).*\/([-\w]+)\/rbconfig/)[1,2] platforms = [platform] # fake alternate (binary compatible) i386-mswin32-60 platform platform == "i386-mingw32" and platforms.push "i386-mswin32-60" platforms.each do |plat| config["rbconfig-#{plat}-#{version}"] = rbconfig # also store RubyGems-compatible version gem_platform = Gem::Platform.new(plat) config["rbconfig-#{gem_platform}-#{version}"] = rbconfig end puts "Found Ruby version #{version} for platform #{platform} (#{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'] rake-compiler-0.9.5/tasks/common.rake0000644000004100000410000000034212457522125017574 0ustar www-datawww-datarequire 'rake/clean' # common pattern cleanup CLOBBER.include('tmp') # set default task task :default => [:spec, :features] # make packing depend on success of running specs and features task :package => [:spec, :features] rake-compiler-0.9.5/tasks/cucumber.rake0000644000004100000410000000127712457522125020121 0ustar www-datawww-databegin require 'cucumber/rake/task' rescue LoadError warn "Cucumber gem is required, please install it. (gem install cucumber)" end if defined?(Cucumber) namespace :cucumber do Cucumber::Rake::Task.new('default', 'Run features testing C extension support') do |t| t.profile = 'default' t.cucumber_opts = '--format pretty --no-source' end Cucumber::Rake::Task.new('java', 'Run features testing Java extension support') do |t| t.profile = 'java' t.cucumber_opts = '--format pretty --no-source' end desc 'Run all features' task :all => [:default, :java] end desc 'Alias for cucumber:default' task :cucumber => 'cucumber:default' end rake-compiler-0.9.5/tasks/gem.rake0000644000004100000410000000320712457522125017057 0ustar www-datawww-datarequire 'rubygems/package_task' GEM_SPEC = Gem::Specification.new do |s| # basic information s.name = "rake-compiler" s.version = "0.9.5" s.platform = Gem::Platform::RUBY # description and details s.summary = 'Rake-based Ruby Extension (C, Java) task generator.' s.description = "Provide a standard and simplified way to build and package\nRuby extensions (C, Java) using Rake as glue." # requirements s.required_ruby_version = ">= 1.8.7" s.required_rubygems_version = ">= 1.8.23" # dependencies s.add_dependency 'rake' # development dependencies s.add_development_dependency 'rspec', '~> 2.8.0' s.add_development_dependency 'cucumber', '~> 1.1.4' # components, files and paths s.files = FileList["features/**/*.{feature,rb}", "bin/rake-compiler", "lib/**/*.rb", "spec/spec.opts", "spec/**/*.rb", "tasks/**/*.rake", "Rakefile", "Gemfile", "*.{rdoc,txt,yml}"] s.bindir = 'bin' s.executables = ['rake-compiler'] s.require_path = 'lib' # documentation s.rdoc_options << '--main' << 'README.rdoc' << '--title' << 'rake-compiler -- Documentation' s.extra_rdoc_files = %w(README.rdoc LICENSE.txt History.txt) # project information s.homepage = 'https://github.com/rake-compiler/rake-compiler' s.rubyforge_project = 'rake-compiler' s.licenses = ['MIT'] # author and contributors s.authors = ['Kouhei Sutou', 'Luis Lavena'] s.email = ['kou@cozmixng.org', 'luislavena@gmail.com'] end gem_package = Gem::PackageTask.new(GEM_SPEC) do |pkg| pkg.need_tar = false pkg.need_zip = false end rake-compiler-0.9.5/tasks/release.rake0000644000004100000410000000140012457522125017720 0ustar www-datawww-datadesc 'Package gems and upload to RubyGems' task :release, [:version] => [:package] do |t, args| args.with_defaults(:version => "") ver = args.version fail "no GEM_SPEC is found or defined. 'release' task cannot work without it." unless defined?(GEM_SPEC) # compare versions to avoid mistakes unless ver == GEM_SPEC.version.to_s then fail "Version mismatch (supplied and specification versions differ)." end files = FileList["pkg/#{GEM_SPEC.name}-#{GEM_SPEC.version}*.*"].to_a fail "No files found for the release." if files.empty? puts "Files to release:" files.each do |f| puts " * #{f}" end puts "Releasing #{GEM_SPEC.name} version #{GEM_SPEC.version}..." files.each do |f| system "gem push #{f}" end puts "Done." end rake-compiler-0.9.5/tasks/bootstrap.rake0000644000004100000410000000056712457522125020332 0ustar www-datawww-datadesc 'Ensure all the cross compiled versions are installed' task :bootstrap do fail "Sorry, this only works on OSX and Linux" if RUBY_PLATFORM =~ /mswin|mingw/ versions = %w(1.8.7-p371 1.9.3-p392 2.0.0-p0) versions.each do |version| puts "[INFO] Attempt to cross-compile Ruby #{version}" ruby "-Ilib bin/rake-compiler cross-ruby VERSION=#{version}" end end rake-compiler-0.9.5/tasks/rspec.rake0000644000004100000410000000032312457522125017417 0ustar www-datawww-databegin require "rspec/core/rake_task" rescue LoadError => e warn "RSpec gem is required, please install it (gem install rspec)." end if defined?(RSpec::Core::RakeTask) RSpec::Core::RakeTask.new(:spec) end rake-compiler-0.9.5/tasks/news.rake0000644000004100000410000000203512457522125017261 0ustar www-datawww-datadesc 'Generate email template to standard output' task :announce do fail "no GEM_SPEC is found or defined. 'announce' task cannot work without it." unless defined?(GEM_SPEC) # read project info and overview notes = begin r = File.read("README.rdoc") r.split(/^(=+ .*)/)[1..4].join.strip rescue warn "Missing README.rdoc" '' end # read changes changes = begin h = File.read("History.txt") h.split(/^(===+ .*)/)[1..2].join.strip rescue warn "Missing History.txt" '' end # standard fields subject = "#{GEM_SPEC.name} #{GEM_SPEC.version} Released" title = "#{GEM_SPEC.name} version #{GEM_SPEC.version} has been released!" body = "#{notes}\n\nChanges:\n\n#{changes}" urls = [GEM_SPEC.homepage].map { |u| "* <#{u.strip}>" }.join("\n") puts "=" * 80, "" puts "Subject: [ANN] #{subject}" puts puts title puts puts urls puts puts body puts puts "=" * 80, "" end