Hi Steve,

  Thanks for sharing that ClojureVerse thread (and taking the time to initiate 
it and carry it through to its conclusion). I read through the conversation you 
and Ian had with Sean and Alex, and I understand the perspectives being 
presented on all sides. I've been using Guix System as my sole OS for quite a 
few years now, and I am a professional Clojure programmer, running the (largely 
Clojure-based) software development team at my company.

At work, I use Guix for developing lightweight, reproducible, containerized 
build/run environments for our various software projects as well as full system 
containers for their deployment on development and production servers. I've 
packaged a few of my Clojure applications with Guix, but since the 
clojure-build-system is quite limited in being unable to resolve dependencies 
or create UberJARs, I've only had limited success in this arena.

Instead, I've found several non-package-building use cases for Guix in the 
development and deployment of Clojure applications:

1. Use `guix shell` to create development environments that contain specific 
versions of Java and the clojure-tools package along with any other non-Clojure 
tools that are needed in the development environment.
   - Clojure REPLs can be run in these shell environments to ensure that all 
developers are using the same set of tools.
   - JARs and UberJARs can be built reproducibly in these environments by using 
`guix shell --container --network --share=$HOME/.m2 --share=$HOME/.gitlibs 
--manifest=manifest.scm`.

2. Use `guix system container` to define OS environments for Clojure 
applications to run in. They can be run from source if the container includes a 
version of Java and the clojure-tools package from Guix. If they are packaged 
as UberJARs, they can simply be run with a version of Java provided by Guix. If 
these Clojure applications call out to any other non-Clojure programs on the 
system, they can also be provided in the environment by Guix. Naturally, both 
source and UberJAR applications can be launched with Shepherd services.

3. Using the `-Sdeps` option of the clojure-tools command, we can write 
Shepherd services that download and run a Clojure application (and all of its 
dependencies) directly from Maven, Clojure, or a public Git repository when we 
call `herd start` on that service. This is extremely powerful as it completely 
sidesteps the need for any JAR or UberJAR packaging ahead of time. Here's an 
example of this approach using my Gemini protocol server, Space-Age. In this 
example though, we assume you have a Gemini site in $HOME/my-gemini-site and an 
SSL certificate stored in PKCS12 format in $HOME/.space-age/keystore.pkcs12 
with password "moonshot". In the Guix environment where I use this service 
currently (Guix Home), I set these files up by using the 
home-files-service-type.

(define space-age-service
  (shepherd-service
   (documentation "A service to start the Space-Age Gemini server on port 1965")
   (provision '(space-age))
   (requirement '())
   (auto-start? #f)
   (one-shot? #f)
   (respawn? #t)
   (modules %default-modules)
   (start #~(lambda args
              (let* ((home-dir       (getenv "HOME"))
                     (home-profile   (string-append home-dir 
"/.guix-home/profile"))
                     (document-root  (string-append home-dir "/my-gemini-site"))
                     (space-age-dir  (string-append home-dir "/.space-age"))
                     ;; Compose the space-age deps map
                     (space-age-url  
"https://gitlab.com/lambdatronic/space-age.git";)
                     (space-age-sha  "35a431b783ef6d9c3c8d1706ecfb66d34c0d8ec3")
                     (space-age-deps (format #f
                                             "{:deps {lambdatronic/space-age 
{:git/url ~s :git/sha ~s}}}"
                                             space-age-url
                                             space-age-sha))
                     ;; Add the necessary environment variables for clojure to 
run successfully
                     (path-env       (car (default-environment-variables)))
                     (path-value     (list-ref (string-split path-env #\=) 1))
                     (environment    (cons (string-append "PATH=" home-profile 
"/bin:" path-value)
                                            (cdr 
(default-environment-variables)))))
                ;; Ensure that document-root and space-age-dir both exist
                (unless (file-exists? document-root) (mkdir document-root))
                (unless (file-exists? space-age-dir) (mkdir space-age-dir))
                ;; Launch clojure in a subprocess
                (display "Launching the Space-Age Gemini server on port 1965\n")
                (fork+exec-command (list "clojure"
                                         
"-J-Djavax.net.ssl.keyStore=keystore.pkcs12"
                                         
"-J-Djavax.net.ssl.keyStorePassword=moonshot"
                                         "-J-Dsni.hostname=localhost"
                                         "-Sdeps" space-age-deps
                                         "-M" "-m" "space-age.server"
                                         document-root)
                                   #:directory space-age-dir
                                   #:environment-variables environment
                                   #:log-file (string-append space-age-dir 
"/space-age.log")))))
   (stop #~(make-kill-destructor))
   (actions '())))


At any rate, for all of these examples to work, I do need a correctly 
functioning (and preferably recent) version of the clojure-tools package in 
Guix. And while building this does, of course, require Guix to package the 
handful of dependency libraries that underpin it, we fortunately don't need to 
repackage the entire Clojure library ecosystem to be able to benefit from 
Guix's reproducibility guarantees in the Clojure space. This is largely due to 
the fact that Clojure libraries are usually only distributed via two mechanisms:

1. As immutable, versioned JARs that have been uploaded to the Maven or Clojars 
repositories.  <-- like url-fetch
2. As references to a public Git repository and an immutable commit from that 
repository.      <-- like git-fetch

These two options mirror those available to Guix package developers in the 
`origin` record. And because their contents are immutable (as are their 
dependencies, which can be resolved dynamically by the clojure-tools command), 
we should be guaranteed that any Guix user who has specified their Java and 
clojure-tools versions will get the same Clojure environment when they build 
and run any Clojure application that is composed from libraries drawn from 
these sources (modulo the bytecode generation order bug in the Clojure 
compiler, which shouldn't impact the program's runtime).

To wrap up, I just want to thank all of the Guix developers again for their 
hard work on this amazing, ever-evolving system for creating reproducible 
environments from the delightful comfort of parentheses. It may very well be 
that the path of least friction to better adoption of Guix by Clojure 
developers is to allow them to continue leveraging their existing tooling for 
library dependency resolution and application/UberJAR packaging as Guix still 
lacks this functionality (in particular, we don't have a clojure importer). 
Instead (or at least until a satisfactory solution is developed to simplify 
these processes for Clojure developers in Guix), I think we can and should 
still advocate for Guix's use in many of the ways that I've described above, 
which existing Clojure tooling by itself unfortunately does not solve.

Of course, for any of these solutions to work, the Guix clojure-tools package 
has to be fixed and kept (reasonably) up to date with releases from 
https://clojure.org/guides/install_clojure. If there's something I can do to 
help with this effort, please let me know as I do rely on it heavily at work 
and in my personal projects.

Thanks and happy hacking!
  Gary


Steve George <[email protected]> writes:

> Hi Gary,
>
> As you probably know there are hundreds of patches and PR's that aren't 
> merged. There's a small number of committers spread across a lot of packages. 
> People tend to work on packages that they are interested in using.
>
> If you'd like to run it yourself then the easiest way will be to use
> guix's load-path ability and then you can build and run the packages
> locally. Obviously, this takes effort but the fact that Guix supports
> this and channels means that people aren't completely dependent on the
> central repository.
>
> Java and Clojure don't get that much attention overall in Guix. I did
> look at Clojure a bit, as I enjoy it, but in the end I didn't feel it
> was massively useful packaging it and the Clojure communities general
> opinion was that users should download tools and libraries directly
> (for example see Sean Cornfields comments [0].
>
> Steve / Futurile
>
> [0] 
> https://clojureverse.org/t/should-linux-distributions-ship-clojure-byte-compiled-aot-or-not/10595/7
>
>
> On Wed, Oct 22, 2025 at 01:04:23PM +0700, Gary Johnson via wrote:
>> I read through the issue thread, and I don't understand why this hasn't been 
>> resolved. It looks like a patch was submitted a year ago. Can someone on the 
>> Guix dev team merge this or share why it wasn't merged?
>> 
>> Thanks,
>>   Gary
>> 
>> On 22 October 2025 12:07:44 GMT+07:00, Ben Sturmfels <[email protected]> 
>> wrote:
>> >Hi Andres
>> >
>> >Just spotted your help-guix post. Just FYI this is discussed further in the 
>> >following issue (no resolution yet):
>> >
>> >https://issues.guix.gnu.org/73432
>> >
>> >I'm similarly affected and am currently having to use upstream Clojure with 
>> >selected projects, rather than "clojure-tools" - including a project based 
>> >on Kit.
>> >
>> >Regards,
>> >Ben
>> >
>> >On 1/7/24 01:16, Andres Moreno wrote:
>> >> I started to play with the Kit Web Framework and followed the instructions
>> >> to build the default example,
>> >> https://kit-clj.github.io/docs/guestbook.html#guestbook_application
>> >> 
>> >>> clojure -Ttools install com.github.seancorfield/clj-new '{:git/tag
>> >> "v1.2.404"}' :as clj-new
>> >>> clojure -Tclj-new create :template io.github.kit-clj :name kit/guestbook
>> >>> cd guestbook
>> >> 
>> >> I then try to start a CIDER repl by typing:
>> >> 
>> >>> clj -M:dev:cider
>> >> 
>> >> This fails with a class-not-found error:
>> >> 
>> >> java.lang.NoClassDefFoundError: org/xnio/channels/StreamSourceChannel
>> >> 
>> >> The complaint comes from
>> >> 
>> >> Exception in thread "main" Syntax error compiling . at
>> >> (ring/adapter/undertow/request.clj:10:17)
>> >> 
>> >> I can get rid of this issue by adding
>> >> 
>> >> org.jboss.xnio/xnio-api {:mvn/version "3.8.16.Final"}
>> >> org.jboss.xnio/xnio-nio {:mvn/version "3.8.16.Final"}
>> >> 
>> >> to my deps.edn file.
>> >> 
>> >> Eventually, I succeeded and got a REPL working, but there were a few
>> >> additional classes that threw errors when I invoked the (go) function at
>> >> the REPL: those erors were fixed by adding the below to the deps.edn file:
>> >> 
>> >> org.wildfly.common/wildfly-common {:mvn/version "2.0.0"}
>> >> org.jboss.logging/jboss-logging {:mvn/version "3.6.0.Final"}
>> >> io.smallrye.config/smallrye-config-common {:mvn/version "3.8.3"}
>> >> io.smallrye.common/smallrye-common-net {:mvn/version "2.4.0"}
>> >> org.jboss.threads/jboss-threads {:mvn/version "3.6.1.Final"}
>> >> io.smallrye.common/smallrye-common-cpu {:mvn/version "2.4.0"}
>> >> 
>> >> Set-up on Guix System:
>> >> 
>> >> - openjdk 21.0.2 (also tested: openjdk 11.0.22)
>> >> - clojure-tools 1.11.2.1446
>> >> 
>> >> Note that I can run the above on Debian 12.6 just as the documentation
>> >> suggests, with no need to add any additional classes to the deps.edn file
>> >> when I have clojure-tools manually installed on Debian per the script on
>> >> the Clojure website.
>> >> 
>> >> Additionally, I got the same errors when I used clojure-tools on Debian
>> >> using the Guix package manager. This suggests that the issue is related to
>> >> clojure-tools.
>> >> 
>> >> I have a work-around so this issue is in no way critical. Nevertheless, I
>> >> thought that I should report it should the folks that look after the
>> >> clojure-tools package want to look into it. I don't know my way around the
>> >> Clojure web stack so I couldn't figure out how to provide a simpler 
>> >> example.
>> >> 
>> >> I will try to find something simpler in a different domain in the 
>> >> meantime.
>> >> 
>> >> Regards, afm
>> >
>> >
>> 

-- 
GPG Key ID: C4FBEDBD
Use `gpg --search-keys [email protected]' to find me
Protect yourself from surveillance: https://emailselfdefense.fsf.org
=======================================================================
()  ascii ribbon campaign - against html e-mail
/\  www.asciiribbon.org   - against proprietary attachments

Why is HTML email a security nightmare? See https://useplaintext.email/

Please avoid sending me MS-Office attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html

Reply via email to