simple tool for compiling Clojure .clj into .class / .jar - clojure

I've found two ways of compiling Clojure *.clj files into *.class files, and while they both work, I have some gripes with both of them.
The first one uses a REPL and so cannot be automated (or can it?)
The second one uses lein. To be frank I don't see why I should use a dependency management tool for something that should be part of the core tool-chain of the language. But in any case, using lein soon forces you to use a local Maven repository if your Clojure code needs to access local jars (which is highly likely).
Is there a better way to generate *.class or *.jar files from Clojure code that involves only core Clojure tools and that can be employed in a scripted, non-interactive way?

Clojure provides clojure.core.Compile, which can be used to compile Clojure code from the command-line.
java -Dclojure.compile.path=<targetdir> -cp <targetdir>;clojure.jar <list of namespaces>
For an example of how to use this from ant, look at the compile-clojure task in Clojure's own build.xml file.

clojure.core/compile can be automated via Clojure

Related

What is the benefit of having a Clojure project before starting the REPL? Why Cider keeps asking and nudging the user about it?

I am using Emacs and every time I start a Clojure REPL with cider-jack-in
, the minibuffer echoes the following:
Are you sure you want to run `cider-jack-in' without a Clojure project? (y or n)
I have a prior experience with Common Lisp and Slime. In this other lisp ecosystem, there is not such a thing. You just start Common Lisp without questions asked.
I do not get the purpose of this message from Cider. Probably, because I am missing something.
It is important to highlight that I do know how to create a Clojure project using lein command. I just do not get its relevance.
What am I missing for not using a Clojure project before starting the REPL?
Why is it so relevant?
What is the downside of developing a Clojure program with the .clj file, the REPL, doing some interactive programming, and re-compiling things as the program evolves with editions?
Just preventing problems with namespace?
Thanks
The main reason for using a "project", whether it is via a deps.edn file (for Clojure CLI tooling) or a project.clj file (for lein), is to provide the dependencies and hence the CLASSPATH. Since Clojure runs on the JVM, the CLASSPATH has to be set before the Java process is started. As an aside, this is not strictly true, but I'll ignore that complexity for now. The CLASSPATH is used by the JVM to find and then load classes during runtime.
If you're not using any dependencies then you can probably get away with not using a project.
I use emacs with cider and the Clojure CLI tooling myself. You might also want to look into the inf-clojure emacs package.
I am also coming from Common Lisp to Clojure and was confused a lot at the beginning.
And we use lein new because BraveClojure etc. shows this as the only way. Despite of its truths, it is too old. The Clojure community should write more up-to-date tutorials and books.
There is e.g. boot - the other build tooling tool than lein:
https://github.com/boot-clj/boot
Short intro:
https://jjmojojjmojo.github.io/boot-getting-started-with-clojure-in-10-minutes.html
Which allows you to start a repl with $ boot repl a repl with boot.user as the namespace
similar to CLUSER.
It is as powerful as lein.
And for command line scripting, there is babashka https://github.com/babashka/babashka
which is interpreted Clojure for scripting - callable even from the command line.

Is there a way to look into jvm/Clojure source code from repl?

As some parts of Clojure are written in Java is there a way to look into these parts of source code from repl? I'm looking for something like this :
(source clojure.lang.Numbers/add)
As this part is implemented with Java
source prints Source not found and returns nil.
It depends on the environment you're using.
With plain REPL, you are quite limited.
Two most popular IDEs are Cursive and Emacs Cider.
As #Carcigenicate already pointed out, Cursive has an excellent Java support and allows you to jump to clojure java sources (or any other 3rd party lib sources - providing the sources have been published) easily.
It also allows you to debug Clojure compiler itself quite easily.
Emacs Cider has some support for Java.
Out of the box you can jump to JDK sources (with some caveats, see https://github.com/clojure-emacs/cider/issues/2687).
For other artifacts (like clojure.lang itself or other 3rd party java libs) you should be able to jump to the source code as long as you add the corresponding source jar to :resource-paths (assuming leiningen-based project here).
See here for more info about Cider's support.

Analogue for maven-resources-plugin or maven-antrun-plugin for leiningen

I use leiningen to manage my clojure project and I want to copy jar file along with some other files into a certain directory as a final part of a build process. Leiningen treats 'resources' as something which should be included into the jar file, and it is unacceptable for me. If I used maven, I could configure it for such task using maven-resource-plugin or fall back to Ant using maven-antrun-plugin, but leiningen is far more convenient tool for clojure projects.
Strangely, I couldn't manage to find anything about similar functionality in leiningen on the internet. This is curious, because one of major clojure applications is web sites, and web sites usually do not include their resources (js, css, etc) into the jar (or do they? That would be weird since slight css tweak will require rather lenghty recompilation). It comes naturally that we have to prepare site environment (copy static resources along with jar bundle into some directory layout), and this task should be done by the build tool.
Is there a plugin to copy files around the filesystem (or something which could substitute it, like running Ant), or I must write one myself? Right now I'm using shell scripts, but it is very inconvenient since I had to run several commands instead of one, and also it is unportable.
did you checkout lein-resource?
in any case. here is a long list of available plugins for lein, maybe you will fine some of them helpful

How do you distribute a Clojure program to non-programmers?

I'm new to Clojure but I'm learning it. I'd like to know the best way to package and distribute a Clojure program to end users who aren't necessarily programmers. I know in Ruby you can just tell users to download the program with gem install [program name] and then run the command that runs the program. What's the equivalent for Clojure programs?
I you use Leiningen it has an uberjar command to make self contained executable jar files, which your users can just double click. See: http://zef.me/2470/building-clojure-projects-with-leiningen
Clojars is great if you're distributing a library, but I'm not sure if that's the best option for end users.
If you're already using Maven, I believe the best option is to create a uberjar containing all required classes. If you want to make it even more end user friendly, you can then create an installer from this jar using something like IzPack. Just remember that Clojure programs are Java programs, so all distribution options for Java are valid for Clojure as well.
lein uberjar works great for small mostly-Clojure apps, but it doesn't scale when using many Java libraries, including necessary licenses, and other such things. If you use the Maven Clojure plugin, you could take advantage of the vast and terrifying Maven assembly plugin to build and final structure you might conceivably need.
Or you could write a Leiningen plugin to do something similar. I'm not sure if such a thing exists.
Clojars (http://clojars.org/) is the bigger repository of Clojure libraries you can find.
It works perfectly with Leiningen projects or any other Maven based project management tool.

Does Clojure require a JDK?

I want to distribute a Clojure program. Do I need a JDK or can a JRE handle everything in Clojure?
You only need the user to have a JRE (v1.5 or above)
Clojure programs can be compiled into a jar file. You don't have to use something like
leiningen, but it's a lot easier.
Check out this page on the Clojure.org site for how to compile and run a program.
You can compile to a jar file from the REPL:
(compile 'clojure.examples.hello)
Here's how you would run a compile jar:
java -cp ./classes:clojure.jar clojure.examples.instance asdf
You just need a JRE.
https://github.com/technomancy/leiningen/blob/master/TUTORIAL.md explains in more detail, but I believe you just want an "Uberjar" which will contain all the dependencies that you need to distribute your application.
JRE is required! You can easily download it from Internet.