require 'pathname' require 'rake/clean' require 'open3' M2C = 'gm2' # Modula-2 compiler. BOOT_OBJECTS = FileList['source/*.elna'] .map do |source| Pathname.new(source).basename.sub_ext('.o') end directory 'build/boot' directory 'build/self' CLEAN.include 'build' rule(/build\/boot\/.+\.o$/ => ->(file) { path = Pathname.new('source') + Pathname.new(file).basename ['build/boot', path.sub_ext('.def'), path.sub_ext('.elna')] }) do |t| sources = t.prerequisites.filter { |f| f.end_with? '.elna' } sh M2C, '-fmod=.elna', '-c', '-I', 'source', '-o', t.name, *sources end rule(/build\/self\/.+\.o$/ => ->(file) { path = Pathname.new(file).relative_path_from('build') result = [] result << File.join('source', path.basename.sub_ext('.def')) result << File.join('build', path.sub_ext('.mod')) }) do |t| sources = t.prerequisites.filter { |f| f.end_with? '.mod' } sh M2C, '-c', '-I', 'source', '-o', t.name, *sources end rule(/build\/self\/.+\.mod$/ => [ 'build/self', 'build/boot/Compiler', ->(file) { File.join('source', Pathname.new(file).basename.sub_ext('.elna')) } ]) do |t| sources, compiler = t.prerequisites .reject { |f| File.directory? f } .partition { |f| f.end_with? '.elna' } File.open t.name, 'w' do |output| puts puts(compiler * ' ') Open3.popen2(*compiler) do |cl_in, cl_out| cl_in.write File.read(*sources) cl_in.close IO.copy_stream cl_out, output cl_out.close end end end ['boot', 'self'].each do |sub| compiler_binary = Pathname.new('build') + sub + 'Compiler' file compiler_binary.to_path => BOOT_OBJECTS.map { |file| File.join('build', sub, file) } do |t| sh M2C, '-o', t.name, *t.prerequisites end compiler_object = compiler_binary.sub_ext('.o') end file 'build/boot/Compiler.o' => ['build/boot', 'source/Compiler.elna'] do |t| sources = t.prerequisites.filter { |f| f.end_with? '.elna' } sh M2C, '-fscaffold-main', '-fmod=.elna', '-c', '-I', 'source', '-o', t.name, *sources end file 'build/self/Compiler.o' => ['build/self/Compiler.mod'] do |t| sources = t.prerequisites.filter { |f| f.end_with? '.mod' } sh M2C, '-fscaffold-main', '-c', '-I', 'source', '-o', t.name, *sources end task default: 'build/self/Compiler' task default: 'build/self/Compiler.mod' task default: 'source/Compiler.elna' task :default do |t| exe, previous_output, source = t.prerequisites cat_arguments = ['cat', source] diff_arguments = ['diff', '-Nur', '--text', previous_output, '-'] puts [cat_arguments * ' ', exe, diff_arguments * ' '].join(' | ') Open3.pipeline(cat_arguments, exe, diff_arguments) end