From d051bb2bacc4dd586c5ebc2dc1162b055620ec2c Mon Sep 17 00:00:00 2001 From: "MATSUMOTO, Katsuyoshi" Date: Fri, 15 Sep 2023 20:51:28 +0900 Subject: [PATCH] pass ci --- Rakefile | 2 +- lib/vaporware/compiler.rb | 45 +++++++--------------------- lib/vaporware/compiler/assembler.rb | 15 ++++++++-- lib/vaporware/compiler/linker.rb | 44 +++++++++++++++++++-------- sig/vaporware/compiler.rbs | 4 +++ sig/vaporware/compiler/assembler.rbs | 5 +++- sig/vaporware/compiler/linker.rbs | 15 ++++++++++ 7 files changed, 79 insertions(+), 51 deletions(-) create mode 100644 sig/vaporware/compiler/linker.rbs diff --git a/Rakefile b/Rakefile index 2d97dc4..4b0fee6 100644 --- a/Rakefile +++ b/Rakefile @@ -8,7 +8,7 @@ require "steep/cli" task default: %i[test] Rake::TestTask.new do |t| - t.test_files = FileList['test/test*.rb'] + t.test_files = FileList['test/test*.rb', 'test/**/test*.rb'] end namespace :steep do diff --git a/lib/vaporware/compiler.rb b/lib/vaporware/compiler.rb index 1ff8604..a3b1f7f 100644 --- a/lib/vaporware/compiler.rb +++ b/lib/vaporware/compiler.rb @@ -2,47 +2,24 @@ require_relative "compiler/generator" require_relative "compiler/assembler" +require_relative "compiler/linker" class Vaporware::Compiler def self.compile(source, compiler: "gcc", dest: "tmp", debug: false, compiler_options: ["-O0"], shared: false) - _precompile = "#{dest}.s" - s = new(input: source, output: _precompile, debug:, shared:) + s = new(input: source, output: dest, debug:, shared:) s.compile(compiler_options:) - obj_file = s.assemble(input: _precompile, assembler: "as", debug:) - output = File.basename(obj_file, ".o") - output = "lib#{output}.so" if shared && output !~ /^lib.+\.so$/ - s.link(input: obj_file, output:, shared:) - File.delete(obj_file) unless debug - File.delete(_precompile) unless debug - end - - def initialize(input:, output: File.basename(input, ".*") + ".s", debug: false, shared: false) - @generator = Vaporware::Compiler::Generator.new(input:, output:, debug:, shared:) - @assembler = Vaporware::Compiler::Assembler.new(input: @generator.precompile, debug:,) - end - - def assemble(input:, output: File.basename(input, ".*") + ".o", assembler: "as", assembler_options: [], debug: false) - if ["gcc", "as"].include?(assembler) - assemble = [assembler, *assembler_options, "-o", output, input].compact - call_command(assemble) - else - @assembler.assemble(input:, output:) - end - output + s.assemble(input: dest.to_s + ".s", assembler: "as", debug:) + s.link end - def link(input:, output: File.basename(input, ".*"), linker: "ld", linker_options: [], dyn_ld_path: ["-dynamic-linker", "/lib64/ld-linux-x86-64.so.2"], ld_path: ["/lib64/libc.so.6", "/usr/lib64/crt1.o"], shared: false) - if shared - dyn_ld_path = [] - ld_path = ["/usr/lib64/crti.o", "/usr/lib/gcc/x86_64-pc-linux-gnu/13/crtbeginS.o", "/usr/lib/gcc/x86_64-pc-linux-gnu/13/crtendS.o", "/usr/lib64/crtn.o",] - - linker_options = ["-shared"] - end - linker_commands = [linker, *linker_options, *dyn_ld_path, "-o", output, *ld_path, input].compact - call_command(linker_commands) + def initialize(input:, output: File.basename(input, ".*"), linker: "ld", assembler: "as", debug: false, shared: false) + @generator = Vaporware::Compiler::Generator.new(input:, output: output + ".s", debug:, shared:) + @assembler = Vaporware::Compiler::Assembler.new(input: @generator.precompile, output: output + ".o", assembler:, debug:) + output = "lib#{output}.so" if shared && output !~ /^lib.+\.so$/ + @linker = Vaporware::Compiler::Linker.new(input: @assembler.obj_file, output:, linker:, debug:, shared:) end - def call_command(commands) = IO.popen(commands.join(" ")).close - + def assemble(input:, output: File.basename(input, ".*") + ".o", assembler: "as", assembler_options: [], debug: false) = @assembler.assemble(input:, output:, assembler:, assembler_options:, debug:) + def link = @linker.link def compile(compiler_options: ["-O0"]) = @generator.compile end diff --git a/lib/vaporware/compiler/assembler.rb b/lib/vaporware/compiler/assembler.rb index dacc3d6..447d349 100644 --- a/lib/vaporware/compiler/assembler.rb +++ b/lib/vaporware/compiler/assembler.rb @@ -15,7 +15,7 @@ class Vaporware::Compiler::Assembler def self.assemble!(input, output = File.basename(input, ".*") + ".o") = new(input:, output:).assemble - def initialize(input:, output: File.basename(input, ".*") + ".o", type: :relocator, debug: false) + def initialize(input:, output: File.basename(input, ".*") + ".o", assembler: "as", type: :relocator, debug: false) @input, @output = input, output @elf_header = ELF::Header.new(type:) @sections = { @@ -31,7 +31,18 @@ def initialize(input:, output: File.basename(input, ".*") + ".o", type: :relocat @debug = debug end - def assemble(assemble_command: "as", assemble_options: [], input: @input, output: @output) + def assemble(assembler: "as", assembler_options: [], input: @input, output: @output, debug: false) + if ["gcc", "as"].include?(assembler) + IO.popen([assembler, *assembler_options, "-o", output, input].join(" ")).close + else + to_elf(input:, output:) + end + output + end + def obj_file = @output + + private + def to_elf(input: @input, output: @output, debug: false) f = File.open(output, "wb") read = { main: false } program_size = 0 diff --git a/lib/vaporware/compiler/linker.rb b/lib/vaporware/compiler/linker.rb index 6d0de19..2614300 100644 --- a/lib/vaporware/compiler/linker.rb +++ b/lib/vaporware/compiler/linker.rb @@ -1,20 +1,38 @@ # frozen_string_literal: true -module Vaporware - class Compiler - class Linker - DEFAULT_LIBRARY_PATH = %w(/lib64/libc.so.6 /usr/lib64/crt1.o /usr/lib64/crtn.o) - def self.link!(source, dest = "a.out", linker: "mold", lib_path: [], options: []) = new(source, dest, linker:, lib_path:, options:) +class Vaporware::Compiler::Linker + def self.link!(source, dest = "a.out", linker: "mold", options: []) = new(input: source, output: dest, linker:, options:).link - def initialize(input, output = "a.out", linker: "mold", lib_path: [], options: []) - @input, @output, @linker = input, output, linker - @lib_path = DEFAULT_LIBRARY_PATH + lib_path - @options = options - end + def initialize(input:, output: "a.out", linker: "mold", linker_options: [], shared: false, debug: false) + @input, @output, @linker = input, output, linker + @options = linker_options + @debug, @shared = debug, shared + end - def link = IO.popen(link_command).close + def link(input: @input, output: @output, debug: @debug, shared: @shared) = IO.popen(link_command).close - private - def link_command = %Q|#{@linker} -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o #{@output} #{@lib_path.join(' ')} #{@input}|.split(/\s+/) + def link_command + ld_path = [] + if @shared + ld_path << "--shared" + ld_path << "#{libpath}/crti.o" + ld_path << "#{gcc_libpath}/crtbeginS.o" + ld_path << "#{gcc_libpath}/crtendS.o" + else + ld_path << "-dynamic-linker" + ld_path << "/lib64/ld-linux-x86-64.so.2" + ld_path << "#{libpath}/crt1.o" + ld_path << "#{libpath}/crti.o" + ld_path << "#{gcc_libpath}/crtbegin.o" + # for not static compile + ld_path << "#{gcc_libpath}/crtend.o" end + ld_path << "#{libpath}/libc.so" + ld_path << "#{libpath}/crtn.o" + cmd = [@linker, "-o", @output, "-m", "elf_x86_64", *@options, *ld_path, @input].join(' ') + puts cmd if @debug + cmd end + + def libpath = @libpath ||= File.dirname(Dir.glob("/usr/lib*/**/crti.o").last) + def gcc_libpath = @gcc_libpath ||= File.dirname(Dir.glob("/usr/lib/gcc/x86_64-*/*/crtbegin.o").last) end diff --git a/sig/vaporware/compiler.rbs b/sig/vaporware/compiler.rbs index 39ca913..7402c62 100644 --- a/sig/vaporware/compiler.rbs +++ b/sig/vaporware/compiler.rbs @@ -1,4 +1,8 @@ class Vaporware::Compiler + GCC_LD_PATH: String + LD_PATH: String + DYN_LD_PATH: String + SHARED_LD_PATH: String # class methods def self.compile: (String, ?compiler: String, ?dest: String, ?debug: bool, ?compiler_options: Array[String], ?shared: bool) -> void def initialize: (input: String, ?output: String, ?debug: bool, ?shared: bool) -> void diff --git a/sig/vaporware/compiler/assembler.rbs b/sig/vaporware/compiler/assembler.rbs index 82a784b..de96fdf 100644 --- a/sig/vaporware/compiler/assembler.rbs +++ b/sig/vaporware/compiler/assembler.rbs @@ -5,5 +5,8 @@ class Vaporware::Compiler::Assembler @debug: bool def initialize: (input: String, ?output: String, ?type: Symbol, ?debug: bool) -> void - def assemble: (?assemble_command: String, ?assemble_options: Array[String], ?input: String, ?output: String) -> void + def assemble: (?assembler: String, ?assembler_options: Array[String] | [], ?input: String, ?output: String, ?debug: bool) -> String + def obj_file: () -> String + + private def to_elf: (?input: String, ?output: String, ?debug: bool) -> void end diff --git a/sig/vaporware/compiler/linker.rbs b/sig/vaporware/compiler/linker.rbs new file mode 100644 index 0000000..2c90bee --- /dev/null +++ b/sig/vaporware/compiler/linker.rbs @@ -0,0 +1,15 @@ +class Vaporware::Compiler::Linker + @input: String + @output: String + @linker: String + @options: Array[String] + @shared: bool + @debug: bool + + def initialize: (input: String, ?output: String, ?linker: String, ?linker_options: Array[String], ?shared: bool, ?debug: bool) -> void + def link: (input: String, ?output: String, ?shared: bool, ?debug: bool) -> void + + def link_command: () -> String + def libpath: () -> String + def gcc_libpath: () -> String +end