~ruther/guix-local

8be59a7e3e1c6f39a4c4c2982483df58683a0b06 — Lilah Tascheter 8 months ago f219acd
gnu: hare: Add hare.

* gnu/packages/hare.scm (hare): New variable.
* gnu/packages/patches/hare-fallback-cache.patch: New file.
* gnu/packages/patches/hare-toolpath.patch: New file.

Change-Id: I5d29841c3dab0f1d50876415a4f62961bfd7a467
Signed-off-by: Liliana Marie Prikler <liliana.prikler@gmail.com>
M gnu/packages/hare.scm => gnu/packages/hare.scm +67 -0
@@ 105,3 105,70 @@
programming language. For general Hare programming, see the @code{hare}
package.")
    (license license:gpl3)))

(define-public hare
  (package
    (name "hare")
    (version "0.25.2")
    (source (origin
              (method git-fetch)
              (uri (git-reference
                     (url "https://git.sr.ht/~sircmpwn/hare")
                     (commit version)))
              (file-name (git-file-name name version))
              (patches (search-patches "hare-fallback-cache.patch"
                                       "hare-toolpath.patch"))
              (sha256
                (base32
                  "1kfvf1xk36w49dnqrkcahh35xdgilhgdn3q84r2101rz2iy4pbba"))))
    (build-system gnu-build-system)
    (arguments
      (list #:modules `((ice-9 format) ,@%default-gnu-modules)
            #:make-flags #~(list (string-append "PREFIX=" #$output)
                                 (string-append "VERSION=" #$version))
            #:phases
            #~(modify-phases %standard-phases
                ;; technically hare does programmatically generate some
                ;; makefiles as part of a bootstrap phase. however, regenning
                ;; these files requires an installation of hare in the first
                ;; place. seeing as the files are pretty short and
                ;; human-readable, I think it's fine to leave them as-is.
                (replace 'configure
                  (lambda* (#:key inputs #:allow-other-keys)
                    (copy-file #$hare-config "config.mk")
                    ;; need to unhardcode some shit manually
                    (let ((file (lambda (s) (search-input-file inputs s)))
                          (dir (lambda (s) (search-input-directory inputs s))))
                      (substitute* "cmd/hare/build.ha"
                        (("\"harec\"") (format #f "\"~a\"" (file "bin/harec")))
                        (("\"qbe\"") (format #f "\"~a\"" (file "bin/qbe"))))
                      (substitute* "cmd/haredoc/main.ha"
                        (("\"less\"") (format #f "\"~a\"" (file "bin/less"))))
                      (substitute* "wordexp/wordexp.ha"
                        (("/bin/sh") (file "bin/sh")))
                      (substitute* "time/chrono/+linux.ha"
                        (("/usr/share/zoneinfo/leap-seconds.list")
                         (file "share/zoneinfo/leap-seconds.list")))
                      (substitute* "time/date/+linux.ha"
                        (("/usr/share/zoneinfo") (dir "share/zoneinfo")))))))))
    (inputs
      (let ((tc (lambda (t) (and (cross-target? t) (cross-gcc-toolchain t)))))
        (filter ->bool (list gcc-toolchain less tzdata/leap-seconds harec qbe
                             ;; provide cross toolchains for all
                             ;; non-native possible targets
                             (tc "aarch64-linux-gnu")
                             (tc "riscv64-linux-gnu")
                             (tc "x86_64-linux-gnu")))))
    (native-inputs (list harec qbe scdoc))
    (supported-systems hare-supported-systems)
    (search-paths (list (search-path-specification
                          (variable "HAREPATH")
                          (files '("share/hare")))))
    (native-search-paths (list (search-path-specification
                                 (variable "HARE_TOOLPATH")
                                 (files '("libexec/hare")))))
    (home-page "https://harelang.org")
    (synopsis "Harelang compiler tooling and stdlib")
    (description "Hare is a simple systems programming language, featuring
static typing, manual memory management, and a minimal runtime.")
    (license (list license:gpl3 license:mpl2.0))))

A gnu/packages/patches/hare-fallback-cache.patch => gnu/packages/patches/hare-fallback-cache.patch +33 -0
@@ 0,0 1,33 @@
From 04fb25e334492432c0c1a09e1abb4c506fb1e710 Mon Sep 17 00:00:00 2001
Message-ID: <04fb25e334492432c0c1a09e1abb4c506fb1e710.1754429792.git.lilah@lunabee.space>
From: Lilah Tascheter <lilah@lunabee.space>
Date: Tue, 5 Aug 2025 16:35:24 -0500
Subject: [PATCH] dirs::xdg: Fallback to cwd.

Guix builds take place without a valid HOME, which will immediately prevent hare
from functioning. Provide a usable, if unfortunate, default.
---
 dirs/xdg.ha | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/dirs/xdg.ha b/dirs/xdg.ha
index 9dc6c3b9..65eb92db 100644
--- a/dirs/xdg.ha
+++ b/dirs/xdg.ha
@@ -29,7 +29,12 @@ fn lookup(prog: str, var: str, default: str) str = {
 	case void => void;
 	};
 
-	const home = os::getenv("HOME") as str;
+	let home = os::getenv("HOME") as str;
+	if(match(os::stat(home)) {
+	case let err: fs::error => yield true;
+	case let st: fs::filestat => yield !fs::isdir(st.mode);
+	}){ home = "."; };
+
 	const path = path::set(&buf, home, default, prog)!;
 	match (os::mkdirs(path, 0o755)) {
 	case let err: fs::error =>
-- 
2.50.0


A gnu/packages/patches/hare-toolpath.patch => gnu/packages/patches/hare-toolpath.patch +72 -0
@@ 0,0 1,72 @@
From 98677305eba7acd487803b6670a1bd67e1fc2796 Mon Sep 17 00:00:00 2001
Message-ID: <98677305eba7acd487803b6670a1bd67e1fc2796.1754431105.git.lilah@lunabee.space>
From: Lilah Tascheter <lilah@lunabee.space>
Date: Tue, 5 Aug 2025 16:42:50 -0500
Subject: [PATCH] cmd::hare::tool: Use HARE_TOOLPATH when available.

Some distros, like Guix, do not have set search paths, and instead rely on
environment variables. Allow tools to be specified through a new variable,
HARE_TOOLPATH.
---
 cmd/hare/tool.ha | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/cmd/hare/tool.ha b/cmd/hare/tool.ha
index b14250fc..b7e4e2ff 100644
--- a/cmd/hare/tool.ha
+++ b/cmd/hare/tool.ha
@@ -7,6 +7,7 @@ use getopt;
 use os;
 use os::exec;
 use path;
+use strings;
 
 fn tool(name: str, cmd: *getopt::command) (void | error) = {
 	if (len(cmd.args) < 1) {
@@ -19,23 +20,29 @@ fn tool(name: str, cmd: *getopt::command) (void | error) = {
 		args = cmd.args[1..];
 	};
 
-	const path = path::init(TOOLDIR)?;
+	const paths = strings::tokenize(os::tryenv("HARE_TOOLPATH", TOOLDIR), ":");
 	const tool = cmd.args[0];
 	const name = fmt::asprintf("hare-{}", tool)!;
 	defer free(name);
-	path::push(&path, name)?;
-
-	const cmd = match (exec::cmd(path::string(&path), args...)) {
-	case let cmd: exec::command =>
-		yield cmd;
-	case errors::noentry =>
-		fmt::fatalf("hare tool {}: tool not found", tool);
-	case let err: exec::error =>
-		return err;
+
+	for(const segment => strings::next_token(&paths)) {
+		const path = path::init(segment)?;
+		path::push(&path, name)?;
+
+		const cmd = match (exec::cmd(path::string(&path), args...)) {
+		case let cmd: exec::command =>
+			yield cmd;
+		case errors::noentry =>
+			continue;
+		case let err: exec::error =>
+			return err;
+		};
+
+		const argv0 = fmt::asprintf("hare tool {}", tool)!;
+		exec::setname(&cmd, argv0)!;
+		const err = exec::exec(&cmd);
+		fmt::fatalf("exec {}: {}", path::string(&path), exec::strerror(err));
 	};
 
-	const argv0 = fmt::asprintf("hare tool {}", tool)!;
-	exec::setname(&cmd, argv0)!;
-	const err = exec::exec(&cmd);
-	fmt::fatalf("exec {}: {}", path::string(&path), exec::strerror(err));
+	fmt::fatalf("hare tool {}: tool not found", tool);
 };
-- 
2.50.0