help-guix
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Need some help packaging parts of a scientific workflow


From: Philip McGrath
Subject: Re: Need some help packaging parts of a scientific workflow
Date: Thu, 23 Mar 2023 17:30:11 -0400
User-agent: Cyrus-JMAP/3.9.0-alpha0-236-g06c0f70e43-fm-20230313.001-g06c0f70e

Hi Kyle,

On Wed, Mar 22, 2023, at 5:29 PM, Kyle Andrews wrote:
> Dear Guix,
>
> Part of my scientific workflow involves compiling a small Racket script
> for a command line program into its executable and placing that on
> PATH.

I am always glad to hear of more people using Guix and Racket together!

> I had bundled this script inside an R package which made sure it
> got compiled and everything was correctly configured at library load
> time.
>

Tangential to your actual question, I think this is not necessarily a terrible 
practice. There is not much difference between running `my-script` and running 
`racket -y "path/to/my-script.rkt"`, and, if you do that or `raco make` during 
the build process of your R package, you'll get compiled files properly. There 
are tradeoffs to weigh, including support for R users without Guix. But there 
are also good reasons to decide to separate the Racket script from the R 
library, so that's what I'll explain below.

> From reading the documentation a lot, I think the actual compilation
> step can be done using the "invoke" procedure like so:
>
> ```
> (invoke "raco" "exe" "{package_location}/custom-shell-tool.rkt")
> ```
>
> What I'm struggling with the most is understanding all the boilerplate
> code I need to place around that fundamental call.
>

I'll start with a working example suitable for `guix build -f`, then answer 
your specific questions.

```
;; SPDX-License-Identifier: (CC0-1.0 OR (Apache-2.0 OR MIT))
;; SPDX-FileCopyrightText: Philip McGrath <philip@philipmcgrath.com>

(use-modules
 (gnu packages racket)
 (guix build-system copy)
 (guix gexp)
 (guix packages))

(package
  (name "racket-hello")
  (version "1.0")
  (source (plain-file "hello.rkt"
                      "#lang racket (displayln '|Hello from Racket!|)"))
  (inputs (list racket))
  (build-system copy-build-system)
  (arguments
   (list
    #:install-plan #~'(("hello" "bin/"))
    #:phases
    #~(modify-phases %standard-phases
        (add-before 'install 'build
          (lambda args
            (invoke "raco" "exe" "hello.rkt"))))))
  (home-page #f)
  (synopsis "Hello world in Racket")
  (description
   "This is a trivial example of using @code{raco exe} with Guix.")
  (license #f))
```

In fact this package would be a reasonable candidate for 
`trivial-build-system`, but I've stuck with `copy-build-system` because the 
boilerplate for `trivial-build-system` is very different than for all other 
build systems.

Likewise, I'm assuming you know how you want to build your executable, but you 
might consider the `--launcher` flag for `raco exe` and an explicit call to 
`raco make`: in particular, it might take use less total disk space than an ELF 
executable.

Note that you do have to use `racket`, not `racket-minimal`, because 
`racket-minimal` doesn't include the `raco exe` command.

>  (source
>   (local-file "package_location")) ; how to refer to local files?

In general, `local-file` is the right mechanism; specifics depend on your 
situation, including how you are expecting your package definition to be used. 
For a single file, `(local-file "path/to/script.rkt")` is probably what you 
want, where the path is relative to the Guile file containing the `local-file` 
expression. For a directory, consider the `#:recursive?` and `#:select?` 
arguments.

>         (invoke "raco" "exe"
>          (string-append
>           #$package-folder ; how to refer to the build itself?
>           "custom-shell-tool.rkt"))))))

The `unpack` phase from `gnu-build-system` handles this: if the package source 
is a directory, you're inside a copy of it; if it's a file, you're in a 
temporary directory containing it.

>
> I'm especially interested in figuring out how I can productively learn
> to experiment productively with this stuff for myself.
>

Personally, I often insert a phase that calls `error` to stop the build, 
perhaps printing out interesting values first, and use `guix build 
--keep-failed` to explore the build environment.

-Philip



reply via email to

[Prev in Thread] Current Thread [Next in Thread]