Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

launching a clojure program, refs #140 #141

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion content/guides/faq.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,3 @@ Example:
Because of its focus on immutable data, there is generally not a high value placed on data encapsulation. Because data is immutable, there is no need to worry about someone else modifying a value. Likewise, because Clojure data is designed to be manipulated directly, there is significant value in providing direct access to data, rather than wrapping it in APIs.

All Clojure vars are globally available so again there is not much in the way of encapsulation of functions within namespaces. However, the ability to mark vars private (either using `defn-` for functions or `def` with `^:private` for values) is a convenience for a developer to indicate which parts of an API should be considered public for use vs part of the implementation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove this errant change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged master into this branch, and I don't think this is an issue anymore

34 changes: 34 additions & 0 deletions content/guides/running_a_clojure_program.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
= Running a Clojure Program
Kevin Downey
2016-09-21
:type: guides
:toc: macro
:icons: font

ifdef::env-github,env-browser[:outfilesuffix: .adoc]

toc::[]


== How to Start

// [[launch]]
// **<<faq#launch,How do you launch a Clojure program?>>**

There are two important pieces of information that need to be conveyed to the JVM when launching a Clojure program:

1. Where to find the code.
2. Where is the main entry point in the code.

#1 usually comes down to setting what is called the "classpath". The classpath is the default way that the JVM finds code. You can setup the classpath using the `-jar` or `-cp` flags on the `java` command. The `-cp` flag takes a list of jars (or directories) separated by ':' on Unix or ';' on Windows. The `-jar` flag takes a single jarfile, and makes some assumptions about where the entry point for the code is. The `-cp` and the `-jar` flags are mutually exclusive. Which flag you use is often driven by the type of artifacts your build system produces. A common type of artifact to build is an uberjar. An uberjar is a jar that contains all of your code and its dependencies. Because an uberjar is a single jar file, they are often used with the `-jar` flag.

As for #2, telling the JVM where the main entry point for your code is, that can be tricky becuase the JVM is expecting a main entry point in some classfile, but we are working in terms of Clojure code. You need a classfile to bootstrap from JVM land in to Clojure. Clojure has its own class it uses for bootstrapping, which you can use too. The name of this class is 'clojure.main'. If you run `java -jar clojure.jar clojure.main` a Clojure repl will be launched, and clojure.main is the class that does that. `java -jar clojure.jar clojure.main --help` will list all the command line flags that clojure.main takes.
The most useful for launching a Clojure program is `-m`. The `-m` flag takes a namespace like `foo.bar`, and causes clojure.main to load that namespace and apply the function named `-main` to the rest of the command line arguments.

But, when using the `-jar` flag, you don't always need to specify which class is your main class. Jar files can contain a manifest and that manifest can specify what the main class is. How this is setup is dependant largely on your build tooling. The jar file containing clojure specifies clojure.main as its main class so `java -jar clojure.jar` will run clojure.main which starts a repl, without you having to specify clojure.main should be run at the command line. Some build tools (like Leiningen) will default to making clojure.main the main class if you don't specify one.

If you have clojure.main specified as your main class in your uberjar, you can launch your Clojure program like `java -jar my-project.jar -m my.project`.

You can also create your own main class, either by writing a stub in Java or AOT compiling some or all of your Clojure program, and use that as the main class for your Clojure program.

If you don't have an uberjar `java -cp $CP clojure.main -m foo.bar`, where $CP is a ';' or ':' seperated list of jars will launch your program. If you don't have a jar at all, and your clojure source code lives in a directory named `src` then `java -cp clojure.jar:src clojure.main -m foo.bar` will run your program.