From d8b5ec8204b0013739c0250bfd08215754672802 Mon Sep 17 00:00:00 2001 From: yfblock <321353225@qq.com> Date: Fri, 1 Nov 2024 02:39:34 +0800 Subject: [PATCH] feat: trying to use deno as build script. --- .vscode/settings.json | 3 +- byteos | 32 ++++++++++++++++++ scripts/cli-build.ts | 76 +++++++++++++++++++++++++++++++++++++++++++ scripts/cli-qemu.ts | 61 ++++++++++++++++++++++++++++++++++ scripts/cli-types.ts | 9 +++++ 5 files changed, 180 insertions(+), 1 deletion(-) create mode 100755 byteos create mode 100644 scripts/cli-build.ts create mode 100644 scripts/cli-qemu.ts create mode 100644 scripts/cli-types.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index c4d11d7..3084eff 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "rust-analyzer.check.allTargets": false, "rust-analyzer.check.extraArgs": [], - "rust-analyzer.procMacro.enable": true + "rust-analyzer.procMacro.enable": true, + "deno.enable": true } \ No newline at end of file diff --git a/byteos b/byteos new file mode 100755 index 0000000..cfcd32a --- /dev/null +++ b/byteos @@ -0,0 +1,32 @@ +#!/usr/bin/env -S deno --ext=ts --allow-run --allow-read --allow-env + +import { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; +import { cliCommand as buildCommand } from './scripts/cli-build.ts'; +import { cliCommand as qemuCommand } from './scripts/cli-qemu.ts'; +import { logLevelEnum, archEnum } from './scripts/cli-types.ts'; +import { parse } from "jsr:@std/yaml"; + +const command = new Command() + .name("byteos") + .version("0.1.0") + .description("Building tools for the byteos.") + + .globalType("log-level", logLevelEnum) + .globalOption("-l, --log-level ", "Set Log Level", { default: 'info' }) + .globalType("architecture", archEnum) + .globalOption("-a, --arch [arch:architecture]", "Set the architecture", { required: true }) + + // Sub Command build + .command("build", buildCommand) + .command("qemu", qemuCommand); + +// parse yaml file +const data = parse(new TextDecoder("utf-8").decode(await Deno.readFile("byteos.yaml"))); +console.log(data); + +try { + // Parse the command. + await command.parse(Deno.args); +} catch (e) { + console.error("Error", e); +} diff --git a/scripts/cli-build.ts b/scripts/cli-build.ts new file mode 100644 index 0000000..52e8fc3 --- /dev/null +++ b/scripts/cli-build.ts @@ -0,0 +1,76 @@ +import { Command, CommandOptions } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; +import { globalArgType } from "./cli-types.ts"; + +const targetMap: Record = { + "riscv64": 'riscv64gc-unknown-none-elf', + "x86_64": 'x86_64-unknown-none', + "aarch64": 'aarch64-unknown-none-softfloat', + "loongarch64": 'loongarch64-unknown-none' +}; + +/** + * Get the path of the kernel elf file. + * @param arch the architecture + * @returns path to the file + */ +export function getKernelElf(arch: string): string { + return `${Deno.cwd()}/target/${targetMap[arch]}/release/kernel`; +} + +/** + * Get the path of the kernel Binary file. + * @param arch the architecture + * @returns path to the file + */ +export function getKernelBin(arch: string): string { + return `${getKernelElf(arch)}.bin`; +} + +export const cargoBuild = async function(options: CommandOptions) { + + const rustflags = [ + "-Cforce-frame-pointers=yes", + "-Clink-arg=-no-pie", + "-Ztls-model=local-exec", + `--cfg=root_fs="ext4_rs"` + ]; + + const buildProc = new Deno.Command("cargo", { + args: [ + "build", + "--release", + "--target", + targetMap[options.arch], + ], + env: { + ROOT_MANIFEST_DIR: Deno.cwd() + "/", + MOUNT_IMG_PATH: "mount.img", + HEAP_SIZE: "0x0180_0000", + RUSTFLAGS: (Deno.env.get("RUSTFLAGS") || "") + ' ' + rustflags.join(' ') + }, + }); + const code = await buildProc.spawn().status; + if(!code.success) { + console.error("Failed to build the kernel"); + Deno.exit(1); + } + + const objcopyProc = new Deno.Command("rust-objcopy", { + args: [ + `--binary-architecture=${options.arch}`, + getKernelElf(options.arch), + "--strip-all", + "-O", + "binary", + getKernelBin(options.arch) + ] + }); + await objcopyProc.spawn().status; + + console.log("options", options); + console.log("code: ", code); +} + +export const cliCommand = new Command() + .description("Build Rust Kernel") + .action(cargoBuild); diff --git a/scripts/cli-qemu.ts b/scripts/cli-qemu.ts new file mode 100644 index 0000000..d3f9377 --- /dev/null +++ b/scripts/cli-qemu.ts @@ -0,0 +1,61 @@ +import { Command, CommandOptions } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; +import { globalArgType } from "./cli-types.ts"; +import { cargoBuild, getKernelBin, getKernelElf } from "./cli-build.ts"; + +async function runQemu(options: CommandOptions) { + await cargoBuild(options); + + const qemuExecArch = { + x86_64: [ + "-machine", + "q35", + "-kernel", + getKernelElf(options.arch), + "-cpu", + "IvyBridge-v2" + ], + riscv64: [ + "-machine", + "virt", + "-kernel", + getKernelBin(options.arch) + ], + aarch64: [ + "-cpu", + "cortex-a72", + "-machine", + "virt", + "-kernel", + getKernelBin(options.arch) + ], + loongarch64: [ + "-kernel", + getKernelElf(options.arch) + ] + }; + + const qemuCommand = new Deno.Command(`qemu-system-${options.arch}`, { + args: [ + ...qemuExecArch[options.arch], + "-m", + "1G", + "-nographic", + "-smp", + "1", + "-D", + "qemu.log", + "-d", + "in_asm,int,pcall,cpu_reset,guest_errors", + + "-drive", + "file=mount.img,if=none,format=raw,id=x0", + "-device", + "virtio-blk-device,drive=x0" + ] + }); + await qemuCommand.spawn().status; +} + +export const cliCommand = new Command() + .description("Run kernel in the qemu") + .action(runQemu); diff --git a/scripts/cli-types.ts b/scripts/cli-types.ts new file mode 100644 index 0000000..167dacd --- /dev/null +++ b/scripts/cli-types.ts @@ -0,0 +1,9 @@ +import { EnumType } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; + +export const logLevelEnum = new EnumType(["debug", "info", "warn", "error"]); +export const archEnum = new EnumType(['x86_64', "aarch64", "riscv64", "loongarch64"]); + +export type globalArgType = { + logLevel: typeof logLevelEnum, + arch: typeof archEnum +};