about summary refs log tree commit diff
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2022-02-13T18·30+0100
committersterni <sternenseemann@systemli.org>2022-02-18T12·06+0000
commit01b25ebd8e21692bddf724b5c02a9849c2a5427c (patch)
tree8c7829ab7463642ea7f03c8be76587f6f4f8433d
parent71d6a02ca19857a06bc789f09c885e5cd77f7212 (diff)
feat(tools/magrathea): implement run command r/3857
This command builds the desired target and runs the executable produced
by it. If a directory is produced, it looks for a single (!) executable
in the bin directory. Dot files are ignored, so wrappers should
generally work. In the future we could provide a flag to select one of
multiple executables.

All arguments following the target are passed to the executable as is.

Examples:

    mg run ops/mq_cli ls
    mg run web/bubblegum:examples

Change-Id: I6490668af68e028520973196d9daa5f1d58969ee
Reviewed-on: https://cl.tvl.fyi/c/depot/+/5277
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
-rw-r--r--tools/magrathea/mg.scm48
1 files changed, 48 insertions, 0 deletions
diff --git a/tools/magrathea/mg.scm b/tools/magrathea/mg.scm
index 86fed6fc2490..a453da2ccd28 100644
--- a/tools/magrathea/mg.scm
+++ b/tools/magrathea/mg.scm
@@ -11,6 +11,8 @@
         (chicken format)
         (chicken irregex)
         (chicken port)
+        (chicken file)
+        (chicken file posix)
         (chicken process)
         (chicken process-context)
         (chicken string)
@@ -37,6 +39,7 @@ commands:
   build - build a target
   shell - enter a shell with the target's build dependencies
   path  - print source folder for the target
+  run   - build a target and execute its output
 
 file all feedback on b.tvl.fyi
 USAGE
@@ -243,6 +246,50 @@ USAGE
                  (guarantee-success (parse-target arg)))]
          [other (print "not yet implemented")]))
 
+(define (execute-run t #!optional cmd-args)
+  (fprintf (current-error-port) "[mg] building target ~A~%" t)
+  (let* ((expr (nix-expr-for t))
+         (out (call-with-input-pipe
+               (apply string-append
+                      ;; TODO(sterni): temporary gc root
+                      (intersperse `("nix-build" "-E" ,(qs expr) "--no-out-link")
+                                   " "))
+               (lambda (p)
+                 (string-chomp (let ((s (read-string #f p)))
+                                 (if (eq? s #!eof) "" s)))))))
+
+    ;; TODO(sterni): can we get the exit code of nix-build somehow?
+    (when (= (string-length out) 0)
+      (mg-error (string-append "Couldn't build target " (format "~A" t)))
+      (exit 1))
+
+    (fprintf (current-error-port) "[mg] running target ~A~%" t)
+    (process-execute
+     ;; If the output is a file, we assume it's an executable à la writeExecline,
+     ;; otherwise we look in the bin subdirectory and pick the only executable.
+     ;; Handling multiple executables is not possible at the moment, the choice
+     ;; could be made via a command line flag in the future.
+     (if (regular-file? out)
+         out
+         (let* ((dir-path (string-append out "/bin"))
+                (dir-contents (if (directory-exists? dir-path)
+                                  (directory dir-path #f)
+                                  '())))
+           (case (length dir-contents)
+             ((0) (mg-error "no executables in build output")
+                  (exit 1))
+             ((1) (string-append dir-path "/" (car dir-contents)))
+             (else (mg-error "more than one executable in build output")
+                   (exit 1)))))
+     cmd-args)))
+
+(define (run args)
+  (match args
+         [() (execute-run (empty-target))]
+         ;; TODO(sterni): flag for selecting binary name
+         [other (execute-run (guarantee-success (parse-target (car args)))
+                             (cdr args))]))
+
 (define (path args)
   (match args
          [(arg)
@@ -262,6 +309,7 @@ USAGE
          [("build" . _) (build (cdr args))]
          [("shell" . _) (shell (cdr args))]
          [("path" . _) (path (cdr args))]
+         [("run" . _) (run (cdr args))]
          [other (begin (print "unknown command: mg " args)
                        (print usage))]))