# **************************************************************************** # # Copyright (c) Microsoft Corporation. # # This source code is subject to terms and conditions of the Microsoft Public License. A # copy of the license can be found in the License.html file at the root of this distribution. If # you cannot locate the Microsoft Public License, please send an email to # ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound # by the terms of the Microsoft Public License. # # You must not remove this notice, or any other, from this software. # # # **************************************************************************** $rakefile_path = File.dirname(__FILE__) # Alias HOME to USERPROFILE under Windows if HOME is not defined ENV['HOME'] ||= ENV['USERPROFILE'] # IronRuby rakefile for build, test, and repository integration v2 require 'rubygems' gem 'pathname2' require 'pathname2' require 'tmpdir' require 'rexml/document' include REXML verbose(false) # default to non-verbose output # Paths to configure IRONRUBY_COMPILER = 'ir.exe' CS_COMPILER = ENV['mono'].nil? ? 'csc' : 'gmcs' EXCLUDED_EXTENSIONS = ['.old', '.suo', '.vspscc', '.vssscc', '.user', '.log', '.pdb', '.cache', '.swp'] EXCLUDED_DIRECTORIES = ['.svn', 'obj', '.', '..'] PACKAGE_DIR = 'c:\ironruby' # directory that binary package is created in require 'context' # Add some utility methods to Pathname to support filtered lists class Pathname def filtered_subdirs(extras = []) return [] unless exist? filtered_subdirs = subdirs.find_all { |dir| (dir.to_a & (EXCLUDED_DIRECTORIES + extras)) == [] } result = filtered_subdirs.map { |dir| self + dir } result.insert(0, self) end def subdirs glob("**/*", File::FNM_DOTMATCH).find_all { |path| (self + path).directory? } end def files raise "Cannot call files on a filename path: #{self}" if !directory? entries.find_all { |e| !(self + e).directory? }.sort end def filtered_files raise "Cannot call filtered_files on a filename path: #{self}" if !directory? files.find_all { |f| !EXCLUDED_EXTENSIONS.include?((self + f).extname) }.map { |f| f.downcase } end end # Source repository synchronization tasks def push IronRuby.source_context do rake_output_message "#{'=' * 78}\nTransforming source to target layout\n\n" # Copy to temporary directory and transform layout to match target layout # This lets us diff the temp target layout with the actual layout temp_dir = generate_temp_dir nodes = [:root, :gppg, :dlr_core, :dlr_libs, :ironruby, :libraries, :tests, :console, :generator, :test_runner, :scanner, :yaml, :stdlibs, :ironlibs] nodes.each do |node| # special case tests directory to avoid filtering sub-directories if node == :tests copy_to_temp_dir node, temp_dir else copy_to_temp_dir node, temp_dir, ['bin'] # always filter out bin subdirectories except in tests end end # Do some post-transform filtering of files if IronRuby.is_merlin? del temp_dir, 'Ruby.sln' else puts "copying #{IronRuby.source + 'IronRuby.sln'} to #{temp_dir + 'Merlin/Main/languages/ruby/IronRuby.sln'}" copy IronRuby.source + 'IronRuby.sln', temp_dir + 'Merlin/Main/languages/ruby/Ruby.sln' end # Special-cased one-way copy of app.config to external layout if IronRuby.is_merlin? transform_config_file 'Svn', get_source_dir(:lang_root) + 'app.config', temp_dir + 'app.config' end # Diff and push temp directory files to the target push_to_target temp_dir # Transform the project files transform_project :ironruby, 'ruby.csproj' transform_project :libraries, 'ironruby.libraries.csproj' transform_project(:dlr_core, 'microsoft.scripting.core.csproj') do |contents| if IronRuby.is_merlin? replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Debug\\', '..\..\build\debug\\' replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Release\\', '..\..\build\release\\' replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Debug\\', '..\..\build\silverlight debug\\' replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Release\\', '..\..\build\silverlight release\\' replace_import_project contents, '..\..\..\..\..\..\Merlin\Main\SpecSharp.targets', '..\..\SpecSharp.targets' replace_doc_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Debug\Microsoft.Scripting.Core.xml', '..\..\build\debug\Microsoft.Scripting.Core.xml' replace_doc_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Release\Microsoft.Scripting.Core.xml', '..\..\build\release\Microsoft.Scripting.Core.xml' replace_doc_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Debug\Microsoft.Scripting.Core.xml', '..\..\build\silverlight debug\Microsoft.Scripting.Core.xml' replace_doc_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Release\Microsoft.Scripting.Core.xml', '..\..\build\silverlight release\Microsoft.Scripting.Core.xml' contents.change_configuration! 'FxCop|AnyCPU', 'TRACE;MICROSOFT_SCRIPTING_CORE' contents.change_configuration! 'SpecSharp|AnyCPU', 'TRACE;DEBUG;MICROSOFT_SCRIPTING_CORE' contents.change_configuration! 'Debug|AnyCPU', 'TRACE;DEBUG;MICROSOFT_SCRIPTING_CORE' contents.change_configuration! 'Release|AnyCPU', 'TRACE;MICROSOFT_SCRIPTING_CORE' contents.change_configuration! 'Silverlight Debug|AnyCPU', 'TRACE;DEBUG;SILVERLIGHT;MICROSOFT_SCRIPTING_CORE' contents.change_configuration! 'Silverlight Release|AnyCPU', 'TRACE;SILVERLIGHT;MICROSOFT_SCRIPTING_CORE' else replace_output_path contents, '..\..\build\debug\\', '..\..\..\..\..\..\Merlin\Main\Bin\Debug\\' replace_output_path contents, '..\..\build\release\\', '..\..\..\..\..\..\Merlin\Main\Bin\Release\\' replace_output_path contents, '..\..\build\silverlight debug\\', '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Debug\\' replace_output_path contents, '..\..\build\silverlight release\\', '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Release\\' replace_import_project contents, '..\..\SpecSharp.targets', '..\..\..\..\..\..\Merlin\Main\SpecSharp.targets' replace_doc_path contents, '..\..\build\debug\microsoft.scripting.core.xml', '..\..\..\..\..\..\Merlin\Main\Bin\Debug\Microsoft.Scripting.Core.xml' replace_doc_path contents, '..\..\build\release\microsoft.scripting.core.xml', '..\..\..\..\..\..\Merlin\Main\Bin\Release\Microsoft.Scripting.Core.xml' replace_doc_path contents, '..\..\build\silverlight debug\microsoft.scripting.core.xml', '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Debug\Microsoft.Scripting.Core.xml' replace_doc_path contents, '..\..\build\silverlight release\microsoft.scripting.core.xml', '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Release\Microsoft.Scripting.Core.xml' contents.change_configuration! 'FxCop|AnyCPU', 'TRACE;MICROSOFT_SCRIPTING_CORE;SIGNED' contents.change_configuration! 'SpecSharp|AnyCPU', 'TRACE;DEBUG;MICROSOFT_SCRIPTING_CORE;SIGNED' contents.change_configuration! 'Debug|AnyCPU', 'TRACE;DEBUG;MICROSOFT_SCRIPTING_CORE;SIGNED' contents.change_configuration! 'Release|AnyCPU', 'TRACE;MICROSOFT_SCRIPTING_CORE;SIGNED' contents.change_configuration! 'Silverlight Debug|AnyCPU', 'TRACE;DEBUG;SILVERLIGHT;MICROSOFT_SCRIPTING_CORE;SIGNED' contents.change_configuration! 'Silverlight Release|AnyCPU', 'TRACE;SILVERLIGHT;MICROSOFT_SCRIPTING_CORE;SIGNED' end end transform_project(:dlr_libs, 'microsoft.scripting.csproj') do |contents| if IronRuby.is_merlin? replace_output_path contents, '..\..\Bin\Debug\\', '..\..\build\debug\\' replace_output_path contents, '..\..\Bin\Release\\', '..\..\build\release\\' replace_output_path contents, '..\..\Bin\Silverlight Debug\\', '..\..\build\silverlight debug\\' replace_output_path contents, '..\..\Bin\Silverlight Release\\', '..\..\build\silverlight release\\' replace_doc_path contents, '..\..\Bin\Debug\Microsoft.Scripting.xml', '..\..\build\debug\Microsoft.Scripting.xml' replace_doc_path contents, '..\..\Bin\Release\Microsoft.Scripting.xml', '..\..\build\release\Microsoft.Scripting.xml' replace_doc_path contents, '..\..\Bin\Silverlight Debug\Microsoft.Scripting.xml', '..\..\build\silverlight debug\Microsoft.Scripting.xml' replace_doc_path contents, '..\..\Bin\Silverlight Release\Microsoft.Scripting.xml', '..\..\build\silverlight release\Microsoft.Scripting.xml' contents.change_configuration! 'FxCop|AnyCPU', 'TRACE' contents.change_configuration! 'SpecSharp|AnyCPU', 'TRACE;DEBUG' contents.change_configuration! 'Debug|AnyCPU', 'TRACE;DEBUG' contents.change_configuration! 'Release|AnyCPU', 'TRACE' contents.change_configuration! 'Silverlight Debug|AnyCPU', 'TRACE;DEBUG;SILVERLIGHT' contents.change_configuration! 'Silverlight Release|AnyCPU', 'TRACE;SILVERLIGHT' else replace_output_path contents, '..\..\build\debug\\', '..\..\Bin\Debug\\' replace_output_path contents, '..\..\build\release\\', '..\..\Bin\Release\\' replace_output_path contents, '..\..\build\silverlight debug\\', '..\..\Bin\Silverlight Debug\\' replace_output_path contents, '..\..\build\silverlight release\\', '..\..\Bin\Silverlight Release\\' replace_doc_path contents, '..\..\build\debug\Microsoft.Scripting.xml', '..\..\Bin\Debug\Microsoft.Scripting.xml' replace_doc_path contents, '..\..\build\release\Microsoft.Scripting.xml', '..\..\Bin\Release\Microsoft.Scripting.xml' replace_doc_path contents, '..\..\build\silverlight debug\Microsoft.Scripting.xml', '..\..\Bin\Silverlight Debug\Microsoft.Scripting.xml' replace_doc_path contents, '..\..\build\silverlight release\Microsoft.Scripting.xml', '..\..\Bin\Silverlight Release\Microsoft.Scripting.xml' contents.change_configuration! 'FxCop|AnyCPU', 'TRACE;SIGNED' contents.change_configuration! 'SpecSharp|AnyCPU', 'TRACE;DEBUG;SIGNED' contents.change_configuration! 'Debug|AnyCPU', 'TRACE;DEBUG;SIGNED' contents.change_configuration! 'Release|AnyCPU', 'TRACE;SIGNED' contents.change_configuration! 'Silverlight Debug|AnyCPU', 'TRACE;DEBUG;SILVERLIGHT' contents.change_configuration! 'Silverlight Release|AnyCPU', 'TRACE;SILVERLIGHT' end end # TODO: add signing to this project transform_project(:yaml, 'IronRuby.Libraries.Yaml.csproj') do |contents| if IronRuby.is_merlin? replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Debug\\', '..\..\build\debug\\' replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Release\\', '..\..\build\release\\' replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Debug\\', '..\..\build\silverlight debug\\' replace_output_path contents, '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Release\\', '..\..\build\silverlight release\\' replace_import_project contents, '..\..\..\..\..\..\Merlin\Main\SpecSharp.targets', '..\..\SpecSharp.targets' else replace_output_path contents, '..\..\build\debug\\', '..\..\..\..\..\..\Merlin\Main\Bin\Debug\\' replace_output_path contents, '..\..\build\release\\', '..\..\..\..\..\..\Merlin\Main\Bin\Release\\' replace_output_path contents, '..\..\build\silverlight debug\\', '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Debug\\' replace_output_path contents, '..\..\build\silverlight release\\', '..\..\..\..\..\..\Merlin\Main\Bin\Silverlight Release\\' replace_import_project contents, '..\..\SpecSharp.targets', '..\..\..\..\..\..\Merlin\Main\SpecSharp.targets' end end transform_project :generator, 'classinitgenerator.csproj' transform_project(:console, 'ruby.console.csproj') do |contents| if IronRuby.is_merlin? replace_output_path contents, '..\..\..\Bin\Debug\\', '..\..\build\debug\\' replace_output_path contents, '..\..\..\Bin\Release\\', '..\..\build\release\\' replace_output_path contents, '..\..\..\Bin\Silverlight Debug\\', '..\..\build\silverlight debug\\' replace_output_path contents, '..\..\..\Bin\Silverlight Release\\', '..\..\build\silverlight release\\' replace_post_build_event contents, 'copy $(ProjectDir)..\merlin_ir.exe.config $(TargetDir)ir.exe.config', 'copy $(ProjectDir)..\..\external_ir.exe.config $(TargetDir)ir.exe.config' replace_app_config_path contents, '..\..\..\App.config', '..\..\App.config' else replace_output_path contents, '..\..\build\debug\\', '..\..\..\Bin\Debug\\' replace_output_path contents, '..\..\build\release\\', '..\..\..\Bin\Release\\' replace_output_path contents, '..\..\build\silverlight debug', '..\..\..\Bin\Silverlight Debug\\' replace_output_path contents, '..\..\build\silverlight release', '..\..\..\Bin\Silverlight Release\\' replace_post_build_event contents, 'copy $(ProjectDir)..\..\external_ir.exe.config $(TargetDir)ir.exe.config', 'copy $(ProjectDir)..\merlin_ir.exe.config $(TargetDir)ir.exe.config' replace_app_config_path contents, '..\..\App.config', '..\..\..\App.config' end end transform_project :test_runner, 'ironruby.tests.csproj' do |contents| if IronRuby.is_merlin? replace_output_path contents, '..\..\..\Bin\Debug\\', '..\..\build\debug\\' replace_output_path contents, '..\..\..\Bin\Release\\', '..\..\build\release\\' replace_output_path contents, '..\..\..\Bin\Silverlight Debug\\', '..\..\build\silverlight debug\\' replace_output_path contents, '..\..\..\Bin\Silverlight Release\\', '..\..\build\silverlight release\\' replace_app_config_path contents, '..\..\..\App.config', '..\..\App.config' else replace_output_path contents, '..\..\build\debug\\', '..\..\..\Bin\Debug\\' replace_output_path contents, '..\..\build\release\\', '..\..\..\Bin\Release\\' replace_output_path contents, '..\..\build\silverlight debug', '..\..\..\Bin\Silverlight Debug\\' replace_output_path contents, '..\..\build\silverlight release', '..\..\..\Bin\Silverlight Release\\' replace_key_path contents, '..\..\RubyTestKey.snk', '..\..\..\MSSharedLibKey.snk' replace_app_config_path contents, '..\..\App.config', '..\..\..\App.config' end end transform_project :scanner, 'ironruby.libraries.scanner.csproj' end end desc "push TFS source tree to Subversion" task :to_svn => [:happy, :clean_tests] do raise "must be in MERLIN enlistment to run to_svn" unless IronRuby.is_merlin? push end desc "push Subversion source tree to TFS" task :to_merlin => [:happy, :clean_tests] do raise "must be in SVN enlistment to run to_merlin" if IronRuby.is_merlin? push end # Compilation tasks desc "clean build directory" task :clean_build => [:happy] do IronRuby.source_context do rd build_path mkdir build_path end end desc "compile extension attribute assembly" task :compile_extension_attributes => [:clean_build] do IronRuby.source_context do compile :dlr_core, :referencess => ['!System.dll'], :switches => ['target:library'], :output => 'Microsoft.Scripting.ExtensionAttribute.dll', :csproj => 'Microsoft.Scripting.ExtensionAttribute.csproj' end end desc "compile DLR (Microsoft.Scripting.dll and Microsoft.Scripting.Core.dll)" task :compile_dlr => [:compile_extension_attributes] do IronRuby.source_context do compile :dlr_core, :references => ['!System.dll', '!System.Configuration.dll', 'Microsoft.Scripting.ExtensionAttribute.dll'], :switches => ['target:library', 'define:MICROSOFT_SCRIPTING_CORE'], :output => 'Microsoft.Scripting.Core.dll', :csproj => 'Microsoft.Scripting.Core.csproj' resources = { Pathname.new('math') + 'MathResources.resx' => Pathname.new('Microsoft.Scripting.Math.MathResources.resources') } compile :dlr_libs, :references => ['Microsoft.Scripting.Core.dll', '!System.Xml.dll', '!System.dll', '!System.Configuration.dll', 'Microsoft.Scripting.ExtensionAttribute.dll'], :switches => ['target:library'], :resources => resources, :output => 'Microsoft.Scripting.dll' end end desc "compile ClassInitGenerator.exe" task :compile_generator => [:compile_ruby] do IronRuby.source_context do compile :generator, :references => ['Microsoft.Scripting.Core.dll', 'Microsoft.Scripting.dll', 'Microsoft.Scripting.ExtensionAttribute.dll', 'IronRuby.dll', '!System.dll'], :output => 'ClassInitGenerator.exe' end end desc "compile IronRuby.dll" task :compile_ruby => [:compile_dlr] do IronRuby.source_context do compile :ironruby, :references => ['Microsoft.Scripting.Core.dll', 'Microsoft.Scripting.dll', 'Microsoft.Scripting.ExtensionAttribute.dll', '!System.dll', '!System.Configuration.dll'], :switches => ['target:library'], :output => 'IronRuby.dll' end end desc "compile IronRuby.Libraries.dll" task :compile_libraries => [:compile_ruby] do IronRuby.source_context do compile :libraries, :references => ['Microsoft.Scripting.Core.dll', 'Microsoft.Scripting.dll', 'Microsoft.Scripting.ExtensionAttribute.dll', 'IronRuby.dll', '!System.dll'], :switches => ['target:library'], :output => 'IronRuby.Libraries.dll' end end def transform_config(source_path, target_path, signed, paths) file = File.new source_path doc = Document.new file # disable signing unless signed configSections = XPath.each(doc, '/configuration/configSections/section') do |node| node.attributes['type'].gsub!(/31bf3856ad364e35/, 'null') end # disable signing in IronRuby and replace the paths languages = XPath.each(doc, '/configuration/microsoft.scripting/languages/language') do |node| if node.attributes['names'] == 'IronRuby;Ruby;rb' node.attributes['type'].gsub!(/31bf3856ad364e35/, 'null') end end end # replace LibraryPaths options = XPath.each(doc, '/configuration/microsoft.scripting/options/set') do |node| if node.attributes['language'] == 'Ruby' && node.attributes['option'] == 'LibraryPaths' node.attributes['value'] = paths end end File.open(target_path, 'w+') do |f| f.write doc.to_s end end def transform_config_file(configuration, source_path, target_build_path) # signing is on for IronRuby in Merlin, off for SVN and Binary layout = {'Merlin' => { :signing => false, :LibraryPaths => '..\..\Languages\Ruby\libs;..\..\..\External\Languages\Ruby\Ruby-1.8.6\lib\ruby\site_ruby\1.8;..\..\..\External\Languages\Ruby\Ruby-1.8.6\lib\ruby\site_ruby;..\..\..\External\Languages\Ruby\Ruby-1.8.6\lib\ruby\1.8' }, 'Svn' => { :signing => false, :LibraryPaths => '..\..\lib\IronRuby;..\..\lib\ruby\site_ruby\1.8;..\..\lib\ruby\site_ruby;..\..\lib\ruby\1.8' }, 'Binary' => { :signing => true, :LibraryPaths => '..\lib\IronRuby;..\lib\ruby\site_ruby\1.8;..\lib\ruby\site_ruby;..\lib\ruby\1.8' } } transform_config source_path, target_build_path, layout[configuration][:signing], layout[configuration][:LibraryPaths] end desc "compile IronRuby console" task :compile_console => [:compile_libraries] do IronRuby.source_context do compile :console, :references => ['Microsoft.Scripting.Core.dll', 'Microsoft.Scripting.dll', 'IronRuby.dll'], :output => IRONRUBY_COMPILER transform_config_file IronRuby.is_merlin? ? 'Merlin' : 'Svn', get_source_dir(:lang_root) + 'app.config', "#{build_path}\\ir.exe.config" end end desc "compile IronRuby.Tests" task :compile_testhost => [:compile_libraries] do IronRuby.source_context do compile :test_runner, :references => ['Microsoft.Scripting.Core.dll', 'Microsoft.Scripting.dll', 'IronRuby.dll', 'IronRuby.Libraries.dll', '!System.dll', '!System.Windows.Forms.dll'], :output => 'IronRuby.Tests.exe' end end desc "compile IronRuby.Libraries.Scanner" task :compile_scanner => [:compile_libraries] do IronRuby.source_context do compile :scanner, :references => ['Microsoft.Scripting.Core.dll', 'Microsoft.Scripting.dll', 'IronRuby.dll', 'IronRuby.Libraries.dll', '!System.Core.dll'], :output => 'IronRuby.Libraries.Scanner.exe' end end desc "compile Yaml" task :compile_yaml => [:compile_libraries] do IronRuby.source_context do compile :yaml, :references => ['Microsoft.Scripting.Core.dll', 'Microsoft.Scripting.dll', 'IronRuby.dll', 'IronRuby.Libraries.dll', '!System.dll'], :switches => ['target:library'], :output => 'IronRuby.Libraries.Yaml.dll' end end desc "compile everything" task :compile => [:happy, :clean_build, :compile_dlr, :compile_ruby, :compile_libraries, :compile_console, :compile_testhost, :compile_generator, :compile_yaml] do end # Unit test/spec tasks desc "[deprecated] run old school spec tests" task :test_libs do IronRuby.source_context do get_source_dir(:tests).filtered_subdirs.each do |dir| chdir(dir) { dir.glob('test_*.rb').each { |file| exec_net "\"#{build_path + IRONRUBY_COMPILER}\" \"#{file}\"" } } end end end desc "run compiler only tests using IronRuby.Tests.exe C# driver" task :test_compiler do IronRuby.source_context do exec_net "#{build_path + 'ironruby.tests.exe'}" # TODO: make run.rb do the right thing in external svn-only install chdir(:tests) { exec "ruby run.rb" } end end desc "Alias for mspec:core" task :mspec => "mspec:core" namespace :mspec do desc "Run RubySpec core suite" task :core => ["ruby_imp", :testhappy] do IronRuby.source_context { invoke_mspec($ruby_imp) } exit end desc "Run core suite with both CRuby and Ironruby" task :dual => [:testhappy] do IronRuby.source_context do rake_output_message "Ruby\n" invoke_mspec(UserEnvironment.mri_binary) rake_output_message "IronRuby\n" invoke_mspec(path_to_ir) exit end end desc "Run RubySpec language suite" task :lang => ["ruby_imp", :testhappy] do IronRuby.source_context { invoke_mspec($ruby_imp, 'language')} exit end desc "Run RubySpec library suite" task :lib => ["ruby_imp", :testhappy] do IronRuby.source_context { invoke_mspec($ruby_imp, 'library')} exit end end def split_args klass = ARGV.length == 1 ? '-' : ARGV[1] name = ARGV.length <= 2 ? '-' : ARGV[2] reporter = ARGV.length == 4 ? ARGV[3] : "summary" [klass, name, reporter] end def path_to_ir (build_path + IRONRUBY_COMPILER).gsub '\\', '/' end def extract_reporter(reporter) case reporter when 'dox' '-f specdoc' when 'fail' '-f fail' when 'cov' ['-f coverage','run -G critical'] when 'tag' ['-f dotted','tag -G critical'] when 'run' ['-f dotted','run -G critical'] else '-f dotted' end end def invoke_mspec(path_to_ruby, root_path = "core") unless root_path == "language" klass, name, reporter = split_args else name, reporter, _ = split_args end IronRuby.source_context do root = UserEnvironment.rubyspec spec_file = name == '-' ? '' : "#{name}_spec.rb" spec_dir = klass == '-' ? '' : "#{klass}/" spec_suite = spec_dir + spec_file run_spec = root + "/1.8/#{root_path}/#{spec_suite}" reporter,tag = extract_reporter(reporter) chdir(get_source_dir(:tests) +'util'){ cmd = "\"#{UserEnvironment.mri_binary}\" \"#{UserEnvironment.mspec}/bin/mspec\" #{tag || 'ci'} -t #{path_to_ruby} -B \"#{UserEnvironment.config}\" \"#{run_spec}\" #{reporter}" exec_net cmd } end end desc "remove output files and generated debugging info from tests directory" task :clean_tests do IronRuby.source_context do chdir(:tests) do exec "del /s *.log" exec "del /s *.pdb" exec "del /s *.exe" exec "del /s *.dll" end end end desc "generate initializers.generated.cs file for IronRuby.Libraries" task :gen do IronRuby.source_context do cmd = "#{build_path + 'ClassInitGenerator.exe'} #{build_path + 'IronRuby.Libraries.dll'} /libraries:IronRuby.Builtins;IronRuby.StandardLibrary.Threading;IronRuby.StandardLibrary.Sockets;IronRuby.StandardLibrary.OpenSsl;IronRuby.StandardLibrary.Digest;IronRuby.StandardLibrary.Zlib;IronRuby.StandardLibrary.StringIO;IronRuby.StandardLibrary.StringScanner;IronRuby.StandardLibrary.Enumerator;IronRuby.StandardLibrary.FunctionControl;IronRuby.StandardLibrary.FileControl;IronRuby.StandardLibrary.BigDecimal /out:#{get_source_dir(:libraries) + 'Initializers.Generated.cs'}" exec_net cmd end end desc "generate initializers.generated.cs file for IronRuby.Libraries.Yaml" task :gen_yaml do IronRuby.source_context do cmd = "#{build_path + 'ClassInitGenerator'} #{build_path + 'IronRuby.Libraries.Yaml.dll'} /libraries:IronRuby.StandardLibrary.Yaml /out:#{get_source_dir(:yaml) + 'Initializer.Generated.cs'}" exec_net cmd end end def path_exists?(paths, command) paths.each do |path| return true if (path + command).exists? end false end STDLIB_CLASSES = {} def walk_classes(klass) klass.constants.each do |constant| current_klass = klass.const_get(constant) if current_klass.is_a?(Module) return if STDLIB_CLASSES.has_key?(current_klass.name) STDLIB_CLASSES[current_klass.name] = true walk_classes(current_klass) end end end desc "perform gap analysis on app's library method usage and IronRuby" task :gap => [:compile_scanner] do IronRuby.source_context do libraries_file = Pathname.new(Dir.tmpdir) + "libraries.txt" exec "#{build_path + 'IronRuby.Libraries.Scanner.exe'} > \"#{libraries_file}\"" library_methods = {} IO.foreach(libraries_file) { |method| library_methods[method.strip] = true } # Generate list of methods used by program trace_output_stream = File.open(Pathname.new(Dir.tmpdir) + 'trace.txt', 'w') function_table = {} ARGV.delete_at 0 if ARGV.length < 1 rake_output_message "usage: rake gap program [args]" exit(-1) end app_name = ARGV.first ARGV.delete_at 0 walk_classes(self.class) set_trace_func proc { |event, file, line, id, binding, klass| if event == "c-call" || event == "call" method_name = klass.to_s + "#" + id.to_s function_table[method_name] = true end } at_exit do rake_output_message 'shutdown ...' function_table.keys.sort.each do |method_name| class_name = method_name.split("#").first if STDLIB_CLASSES.has_key?(class_name) && !library_methods.has_key?(method_name) # output methods that aren't in standard library trace_output_stream.puts method_name end end trace_output_stream.close end load app_name rake_output_message 'about to exit ...' exit end end desc "is the environment setup for an IronRuby dev?" task :happy do IronRuby.source_context do commands = ENV['mono'].nil? ? ['resgen.exe', 'csc.exe'] : ['resgen', 'gmcs'] commands += ['tf.exe', 'svn.exe'] if IronRuby.is_merlin? paths = ENV['PATH'].split(File::PATH_SEPARATOR).collect { |path| Pathname.new path } failure = false commands.each do |command| if !path_exists? paths, command rake_output_message "Cannot find #{command} on system path." failure = true end end if failure rake_output_message "\n" rake_output_message "***** Missing commands! You must have the .NET redist and the SDK" rake_output_message "***** (for resgen.exe) installed. If you are synchronizing source" rake_output_message "***** trees *inside* Microsoft, you must have both tfs.exe and" rake_output_message "***** svn.exe on your path." abort end end end # New mspec tasks for developers - these set a new regression baseline, run the # regression tests, reports why a regression test failed, and test a specific class # while ignoring exclusions. def run_specs(method_name) ARGV.delete_at 0 runner = MSpecRunner.new IronRuby.source_context do iruby = $ruby_imp if ARGV.length == 0 runner.all_core(method_name, iruby) elsif ARGV.length == 1 runner.send(:"#{method_name}", iruby, ARGV.first) elsif ARGV.length == 2 runner.send(:"#{method_name}", iruby, ARGV[0], ARGV[1]) else rake_output_message "usage: rake #{method_name} [class] [method]" exit(-1) end end runner end desc "yell if the rubyspec test environment is not setup" task :testhappy do spec_env_ready = UserEnvironment.rubyspec? && UserEnvironment.mspec? && UserEnvironment.tags? && UserEnvironment.config? if not spec_env_ready rake_output_message "\n" rake_output_message "***** Missing rubyspec test environment! You must have rubyspec, mspec, ironruby-tags and default.mspec" rake_output_message "***** 1. get GIT from http://code.google.com/p/msysgit/" rake_output_message "***** 2. run: git clone git://github.com/ironruby/ironruby-tags.git" rake_output_message "***** 3. run: git clone git://github.com/ironruby/mspec.git" rake_output_message "***** 4. run: git clone git://github.com/ironruby/rubyspec.git" rake_output_message "***** 5. run: runfirst.cmd" rake_output_message "***** 6. edit: #{ENV['USERPROFILE']}\\.irconfig.rb" rake_output_message "***** 7. edit: #{ENV['USERPROFILE']}\\default.mspec" exit(-1) end end desc "generate new baseline against a class" task :baseline => [:testhappy, :ruby_imp] do run_specs(:baseline) exit end desc "run specs against a class, ignoring all exclusions" task :test => [:testhappy, :ruby_imp] do run_specs :test exit end desc "show report of why a regression test failed" task :why_regression => [:testhappy, :ruby_imp] do run_specs :why_regression exit end desc "run regression tests using mspec" task :regression => [:testhappy, :ruby_imp] do run_specs(:regression).report exit end desc "regenerate critical tags" task :regen_tags => [:testhappy] do IronRuby.source_context { MSpecRunner.new.generate_critical_tags } end desc "Set ruby runner to CRuby" task :ruby do begin old_verbose,$VERBOSE = $VERBOSE,nil $ruby_imp = [UserEnvironment.mri_binary] ARGV = [ARGV[0],*ARGV[2..-1]] ensure $VERBOSE = old_verbose end end task :ruby_imp do IronRuby.source_context do $ruby_imp ||= %Q{#{path_to_ir} -T "-X:Interpret"} end end desc "Run PEVerify on the generated IL" task :peverify do begin old_verbose, $VERBOSE = $VERBOSE, nil IronRuby.source_context {$ruby_imp ||= %Q{#{path_to_ir} -T "-X:SaveAssemblies"} } ARGV = [ARGV[0], *ARGV[2..-1]] ensure $VERBOSE = old_verbose end end desc "Generate an IronRuby binary redist package from the layout" task :package do IronRuby.source_context do # Directory layouts system %Q{rmdir /S /Q #{PACKAGE_DIR}} mkdir_p PACKAGE_DIR mkdir_p "#{PACKAGE_DIR}\\bin" # Copy binaries system %Q{copy "#{ENV['MERLIN_ROOT']}\\Languages\\Ruby\\IronRuby.BinaryLayout.config" "#{PACKAGE_DIR}\\bin\\ir.exe.config"} system %Q{copy "#{ENV['MERLIN_ROOT']}\\bin\\release\\ir.exe" #{PACKAGE_DIR}\\bin\\} system %Q{copy "#{ENV['MERLIN_ROOT']}\\bin\\release\\IronRuby*.dll" #{PACKAGE_DIR}\\bin\\} system %Q{copy "#{ENV['MERLIN_ROOT']}\\bin\\release\\Microsoft.Scripting.Core.dll" #{PACKAGE_DIR}\\bin\\} system %Q{copy "#{ENV['MERLIN_ROOT']}\\bin\\release\\Microsoft.Scripting.dll" #{PACKAGE_DIR}\\bin\\} # Generate ir.exe.config transform_config_file 'Binary', get_source_dir(:lang_root) + 'app.config', "#{PACKAGE_DIR}\\bin\\ir.exe.config" # Copy standard library system %Q{xcopy /E /I "#{ENV['MERLIN_ROOT']}\\..\\External\\Languages\\Ruby\\redist-libs\\ruby" #{PACKAGE_DIR}\\lib\\ruby} system %Q{xcopy /E /I "#{ENV['MERLIN_ROOT']}\\Languages\\Ruby\\Libs" #{PACKAGE_DIR}\\lib\\IronRuby} # Generate compressed package system %Q{del "#{ENV['TEMP']}\\ironruby.7z"} system %Q{"#{ENV['PROGRAM_FILES_32']}/7-Zip/7z.exe" a -bd -t7z -mx9 "#{ENV['TEMP']}\\ironruby.7z" "#{PACKAGE_DIR}\\"} system %Q{"#{ENV['PROGRAM_FILES_32']}/7-Zip/7z.exe" a -bd -tzip -mx9 "c:\\ironruby.zip" "#{PACKAGE_DIR}\\"} system %Q{copy /b /Y "#{ENV['PROGRAM_FILES_32']}\\7-Zip\\7zSD.sfx" + "#{ENV['MERLIN_ROOT']}\\Languages\\Ruby\\sfx_config.txt" + "#{ENV['TEMP']}\\ironruby.7z" "c:\\ironruby.exe"} end end task :default => [:happy] do Rake.application.options.show_tasks = true Rake.application.options.show_task_pattern = Regexp.new('.') Rake.application.display_tasks_and_comments end