diff --git a/Rakefile b/Rakefile index 81d54a2..e02aa4a 100755 --- a/Rakefile +++ b/Rakefile @@ -9,7 +9,6 @@ require 'uri' require 'net/http' require 'open3' require 'etc' -require 'fileutils' require 'pathname' require 'rake/clean' @@ -57,10 +56,12 @@ class BuildTarget .split(' ').last.strip end - def configuration + def configuration(prefix) case @architecture when :rv32 - ['--with-arch=rv32imafdc', '--with-abi=ilp32d', '--with-tune=rocket', '--with-isa-spec=20191213'] + ['arch=rv32imafdc', 'abi=ilp32d', 'tune=rocket', 'isa-spec=20191213'].map do |option| + "-#{prefix}#{option}" + end else [] end @@ -109,9 +110,9 @@ end def configure_make_install(source_directory, configure_options, env, cwd) configure = source_directory.relative_path_from(cwd) + 'configure' - system env, configure.to_path, *configure_options, chdir: cwd.to_path, exception: true - system 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path, exception: true - system env, 'make', 'install', chdir: cwd.to_path, exception: true + sh env, configure.to_path, *configure_options, chdir: cwd.to_path + sh 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path + sh env, 'make', 'install', chdir: cwd.to_path end directory(TMP + 'tools') @@ -168,8 +169,8 @@ namespace :cross do options.rootfs.mkpath options.sysroot.mkpath - system 'contrib/download_prerequisites', chdir: source_directory.to_path, exception: true - configure_options = options.configuration + [ + sh 'contrib/download_prerequisites', chdir: source_directory.to_path + configure_options = options.configuration('-with-') + [ "--prefix=#{options.rootfs.realpath}", "--with-sysroot=#{options.sysroot.realpath}", '--enable-languages=c,c++', @@ -211,7 +212,7 @@ namespace :cross do include_directory = TMP + 'tools/include' include_directory.mkpath - FileUtils.cp (source_directory + 'elf/elf.h'), (include_directory + 'elf.h') + cp (source_directory + 'elf/elf.h'), (include_directory + 'elf.h') end desc 'Build linux kernel' @@ -226,14 +227,14 @@ namespace :cross do 'PATH' => "#{options.rootfs.realpath + 'bin'}:#{ENV['PATH']}", 'HOSTCFLAGS' => "-D_UUID_T -D__GETHOSTUUID_H -I#{TMP + 'tools/include'}" } - system env, 'make', 'rv32_defconfig', chdir: cwd.to_path, exception: true - system env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path, exception: true - system env, 'make', 'headers', chdir: cwd.to_path, exception: true + sh env, 'make', 'rv32_defconfig', chdir: cwd.to_path + sh env, 'make', '-j', Etc.nprocessors.to_s, chdir: cwd.to_path + sh env, 'make', 'headers', chdir: cwd.to_path user_directory = options.sysroot + 'usr' user_directory.mkpath - FileUtils.cp_r (cwd + 'usr/include'), (user_directory + 'include') + cp_r (cwd + 'usr/include'), (user_directory + 'include') end desc 'Build glibc' @@ -275,13 +276,14 @@ namespace :cross do source_directory = TMP + "tools/gcc-#{GCC_VERSION}" cwd = TMP + 'tools/build-gcc' - FileUtils.rm_rf cwd + rm_rf cwd cwd.mkpath + cp_r '../elna', source_directory + 'gcc' - configure_options = options.configuration + [ + configure_options = options.configuration('-with-') + [ "--prefix=#{options.rootfs.realpath}", "--with-sysroot=#{options.sysroot.realpath}", - '--enable-languages=c,c++,lto', + '--enable-languages=c,c++,lto,elna', '--enable-lto', '--enable-shared', '--disable-bootstrap', @@ -308,7 +310,7 @@ end task cross: TMP + 'tools' task :cross, :target do |t, args| - args.with_defaults(target: 'riscv32-unknown-linux-gnu') + args.with_defaults target: 'riscv32' Rake::Task['cross:binutils'].invoke args[:target] Rake::Task['cross:gcc1'].invoke args[:target] @@ -318,27 +320,55 @@ task :cross, :target do |t, args| Rake::Task['cross:gcc2'].invoke args[:target] end -FLAGS = ['-O2', '-g3', '-Wall', '-march=rv32imzicsr', '-mabi=ilp32', '-fno-stack-protector', '-ffreestanding', '-nostdlib', '-static'] - -CLEAN.include 'kernel.elf', 'build/riscv32' +def relative_from_tmp(path) + Pathname.new(path).relative_path_from(TMP).each_filename +end +CLEAN.include(TMP + 'riscv32') directory(TMP + 'riscv32') -rule(/^#{TMP}\/[[:alnum:]]+\/[[:alnum:]]+\.o$/ => ->(match) { - [Pathname.new(match).basename.sub_ext('.s'), TMP + 'riscv32'] -}) do |t| - ENV['CC'] = 'build/rootfs/bin/riscv32-unknown-linux-gnu-gcc' +rule '.s.o' => ->(match) { + architecture, *path_components = relative_from_tmp(match).to_a + path_components[-1] = path_components.last.ext('') - system ENV['CC'], *FLAGS, '-c', '-o', t.name, *t.prerequisites.select { |prerequisite| prerequisite.end_with? '.s' } + [File.join(path_components), TMP + architecture] +} do |t| + options = BuildTarget.new relative_from_tmp(t.name).first + compiler = options.rootfs + "bin/#{options.target}-gcc" + flags = ['-ffreestanding'] + options.configuration('m') + sources = t.prerequisites.select { |prerequisite| File.extname(prerequisite) == '.s' } + + system compiler.to_s, *flags, '-c', '-o', t.name, *sources, exception: true end -file 'kernel.elf' => FileList['*.s'].map { |source| (TMP + 'riscv32' + source).sub_ext('.o') } do |t| - ENV['CC'] = 'build/rootfs/bin/riscv32-unknown-linux-gnu-gcc' +rule '.elna.o' => ->(match) { + architecture, *path_components = relative_from_tmp(match).to_a + path_components[-1] = path_components.last.ext('') - system ENV['CC'], *FLAGS, '-T', 'kernel.ld', '-Wl,-Map=kernel.map', '-o', 'kernel.elf', *t.prerequisites + [File.join(path_components), TMP + architecture] +} do |t| + options = BuildTarget.new relative_from_tmp(t.name).first + compiler = options.rootfs + "bin/#{options.target}-gcc" + flags = ['-O2', '-g3', '-fno-stack-protector'] + options.configuration('m') + sources = t.prerequisites.select { |prerequisite| File.extname(prerequisite) == '.elna' } + + system compiler.to_s, *flags, '-c', '-o', t.name, *sources, exception: true end -task default: 'kernel.elf' +rule 'kernel.elf' => ->(match) { + architecture_tmp = TMP + relative_from_tmp(match).first + + FileList['*.s', '*.elna'].map { |source| (architecture_tmp + source).to_path + '.o' } << 'kernel.ld' +} do |t| + options = BuildTarget.new relative_from_tmp(t.name).first + compiler = options.rootfs + "bin/#{options.target}-gcc" + flags = options.configuration('m') + objects, linker_script = t.prerequisites.partition { |prerequisite| File.extname(prerequisite) == '.o' } + + system compiler.to_s, '-nostdlib', '-T', *linker_script, '-o', t.name, *objects, exception: true +end + +task default: 'build/riscv32/kernel.elf' task :default do |t| QEMU = 'qemu-system-riscv32' diff --git a/kernel.s b/kernel.s index c069cd8..9ff500b 100644 --- a/kernel.s +++ b/kernel.s @@ -140,13 +140,13 @@ handle_trap: csrr a0, scause call write_i - li a0, ',' + call separator call write_c csrr a0, stval call write_i - li a0, ',' + call separator call write_c csrr a0, sepc diff --git a/source.elna b/source.elna new file mode 100644 index 0000000..55052a4 --- /dev/null +++ b/source.elna @@ -0,0 +1,7 @@ +module; + +proc separator*() -> Char; + return ',' +end; + +end.