commit 3cf277739c142cdc611415ca605639aa39c38d20
parent dbd2d7a542ae38337ff7e34758262bd0a1cebcb0
Author: Lorenz (xha) <me@xha.li>
Date: Sat, 9 Dec 2023 18:20:24 +0100
cmd::hare add comments and cleanup
Signed-off-by: Lorenz (xha) <me@xha.li>
Diffstat:
4 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/cmd/hare/build.ha b/cmd/hare/build.ha
@@ -123,25 +123,29 @@ fn build(name: str, cmd: *getopt::command) (void | error) = {
case 'v' =>
if (ctx.mode == build::output::VERBOSE) {
ctx.mode = build::output::VVERBOSE;
- } else {
+ } else if (ctx.mode != build::output::VVERBOSE) {
ctx.mode = build::output::VERBOSE;
+ } else {
+ fmt::fatal("Number of verbose levels must be <= 2");
};
case =>
abort();
};
};
- if (len(cmd.args) > 1 && name == "build") {
+
+ if (name == "build" && len(cmd.args) > 1) {
getopt::printusage(os::stderr, name, cmd.help...)!;
os::exit(os::status::FAILURE);
};
+ set_arch_tags(&ctx.ctx.tags, arch);
+
ctx.cmds = ["",
os::tryenv("HAREC", "harec"),
os::tryenv("QBE", "qbe"),
os::tryenv("AS", arch.as_cmd),
os::tryenv("LD", arch.ld_cmd),
];
- set_arch_tags(&ctx.ctx.tags, arch);
if (len(ctx.libs) > 0 || ctx.platform.need_libc) {
ctx.libc = true;
merge_tags(&ctx.ctx.tags, "+libc")?;
@@ -169,6 +173,9 @@ fn build(name: str, cmd: *getopt::command) (void | error) = {
if (ctx.goal == build::stage::BIN) {
mode |= 0o111;
};
+ // in the case that we are outputting to a binary that is
+ // currently beeing executed, we need to remove it first or
+ // otherwise os::create() will fail
os::remove(output): void;
dest = match (os::create(output, mode)) {
case let f: io::file =>
@@ -178,6 +185,7 @@ fn build(name: str, cmd: *getopt::command) (void | error) = {
};
};
defer io::close(dest)!;
+
let src = os::open(built)?;
defer io::close(src)!;
io::copy(dest, src)?;
@@ -204,6 +212,7 @@ fn get_output(goal: build::stage, input: str) (str | error) = {
if (!fs::isdir(stat.mode)) {
path::pop(&buf);
};
+ // don't add the .bin extension if the goal is to create a binary
if (goal != build::stage::BIN) {
path::push_ext(&buf, build::stage_ext[goal])?;
};
diff --git a/cmd/hare/build/queue.ha b/cmd/hare/build/queue.ha
@@ -34,6 +34,8 @@ export fn execute(ctx: *context) (str | error) = {
defer for (let i = 0z; i < len(q); i += 1) {
free_task(q[i]);
};
+
+ // stage::TD (typedef files) are generated by the SSA stage (harec)
const goal = if (ctx.goal == stage::TD) stage::SSA else ctx.goal;
queue(ctx, &q, goal, ctx.top);
// sort by stage, harec then qbe then as then ld, and keep reverse
@@ -74,6 +76,7 @@ fn task_cmp(a: const *opaque, b: const *opaque) int = {
};
fn queue(ctx: *context, q: *[]*task, kind: stage, idx: size) *task = {
+ // return already existing task to avoid creating duplicates
for (let i = 0z; i < len(q); i += 1) {
if (q[i].kind == kind && q[i].idx == idx) {
return q[i];
@@ -95,9 +98,9 @@ fn queue(ctx: *context, q: *[]*task, kind: stage, idx: size) *task = {
append(queue(ctx, q, kind - 1, idx).rdeps, t);
case stage::SSA =>
t.ndeps = len(ctx.mods[idx].deps);
- for (let i = 0z; i < len(ctx.mods[idx].deps); i += 1) {
- let j = ctx.mods[idx].deps[i].0;
- append(queue(ctx, q, stage::SSA, j).rdeps, t);
+ for (let i = 0z; i < t.ndeps; i += 1) {
+ let dep_idx = ctx.mods[idx].deps[i].0;
+ append(queue(ctx, q, stage::SSA, dep_idx).rdeps, t);
};
case stage::TD => abort();
};
@@ -105,11 +108,13 @@ fn queue(ctx: *context, q: *[]*task, kind: stage, idx: size) *task = {
return t;
};
+// returns true if the task was executed. returns false if the task cannot be
+// executed (because it is waiting for dependencies) or if the task is already
+// running (possibly in another instance of this build driver)
fn run_task(ctx: *context, jobs: *[]job, t: *task) (bool | error) = {
if (len(jobs) == ctx.jobs) {
await_task(ctx, jobs)?;
};
- assert(len(jobs) < ctx.jobs);
if (t.ndeps != 0) {
return false;
};
@@ -156,7 +161,6 @@ fn run_task(ctx: *context, jobs: *[]job, t: *task) (bool | error) = {
return true;
};
-
switch (ctx.mode) {
case output::DEFAULT, output::SILENT => void;
case output::VERBOSE =>
diff --git a/cmd/hare/build/util.ha b/cmd/hare/build/util.ha
@@ -74,6 +74,9 @@ fn get_deps(ctx: *context, t: *task) []str = {
};
};
+// returns the arguments that don't depend on the result of the hash. these will
+// be used to create the hash. see [[get_args]] for the arguments that depend
+// on the result of the hash
fn get_flags(ctx: *context, t: *task) ([]str | error) = {
let flags: []str = strings::dupall(ctx.platform.default_flags[t.kind]);
@@ -226,6 +229,8 @@ fn get_hash(
return prefix;
};
+// returns the value of flags plus the arguments that depend on the result of
+// the hash. see [[get_flags]] for the arguments that don't depend on the hash
fn get_args(ctx: *context, tmp: str, flags: []str, t: *task) []str = {
let args = strings::dupall(flags);
append(args, strings::dup("-o"));
@@ -258,6 +263,10 @@ fn get_args(ctx: *context, tmp: str, flags: []str, t: *task) []str = {
append(args, strings::dup(srcs.o[i]));
};
};
+ // XXX: when dynamically linking on Linux, we have to disable
+ // gc-sections again after enabling it in get_flags(); it looks
+ // like leaving this enabled gets us SIGILL in libc (musl). this
+ // is not broken on other platforms such as OpenBSD
if (ctx.libc) {
append(args, strings::dup("-Wl,--no-gc-sections"));
};
diff --git a/hare/module/deps.ha b/hare/module/deps.ha
@@ -22,6 +22,7 @@ export type module = struct {
ns: ast::ident,
path: str,
srcs: srcset,
+ // [](Index to the module, Identifier of of the module)
deps: [](size, ast::ident),
};