This question already has answers here:
How do I start the REPL in a user defined namespace?
(7 answers)
Closed 7 years ago.
Specifically with a leiningen uberjar.
java -cp myapp.jar clojure.main -r
gets me a repl but defaults to the user namespace
What do I need to do to get it to myapp's namespace?
java -cp myapp.jar clojure.main -e (in-ns myapp.core)
gives me clojure.lang.LispReader$ReaderException
* Update *
The ultimate goal is to simply run
java -jar myapp.jar
and have a Clojure REPL in my app's namespace.
Every solution I've seen involves writing code on the command line that I want to put into my main method but can't seem to get running
(defn -main [&args]
(clojure.main/main "-e" "(in-ns myapp.core)"))
completes/terminates immediately
java -cp myapp.jar clojure.main -m myapp.core
Related
I currently run a simple cli I wrote by calling: lein run my-cli-command arg --option
How can I call my command without needing to include lein run? This is what i'm after: my-cli-command arg --option
Do I need to convert it to an binary or executable and if so how?
As far as I know, there's no way to run just my-cli-command arg --option.
You can take lein out of the equation though by creating a Java archive:
lein uberjar
Then run the jar as you would any other:
java -jar target/my-cli-command-standalone.jar arg --option
uberjar will name the jar based on what you've called your project in project.clj, and will create a jar that relies on external dependencies, and one that doesn't (standalone).
Then, as #gary pointed out, you can stick the java - jar ... command in a .bat file, name it whatever you want, then run the bat directly. My bat-Fu is pretty weak, but there's likely a way to pass arguments to the bat and have them passed to the jar so you don't need to hard code the arguments.
As of Clojure 1.9 there are new CLI tools! See this guide for installation. You can create an executable script like this:
#!/usr/local/bin/clojure
(println "Hello World! from" *ns*)
(require '[clojure.walk :as walk])
(walk/postwalk-demo {:woo ::yeah})
Then make the script executable and execute it:
$ chmod +x my_script
$ ./my_script
Hello World! from #object[clojure.lang.Namespace 0x1ebea008 user]
Walked: :woo
Walked: :user/yeah
Walked: [:woo :user/yeah]
Walked: {:woo :user/yeah}
Start-up time seems improved as well. It takes a little over a second to run a trivial script (just print a string) on a recent MBP:
time ./hello
Hello World!
./hello 1.51s user 0.12s system 184% cpu 0.887 total
I've not used it, but I know inlein exists and it looks like what you need.
Inlein is the easiest and fastest way to run Clojure scripts. You only have to inline your dependencies, add in a shebang line, and make the script file executable.
And a minimal example:
#!/usr/bin/env inlein
'{:dependencies [[org.clojure/clojure "1.8.0"]]}
(println "hello world!")
You can use "binary payload" in shell script as described in https://coderwall.com/p/ssuaxa/how-to-make-a-jar-file-linux-executable
Basically you can concatenate a shell script and your uberjar in a single shell script file and execute java in the script specifying that script as the jar file on the classpath - the example comes from the linked post:
Save your runner script in stub.sh:
#!/bin/sh
MYSELF=`which "$0" 2>/dev/null`
[ $? -gt 0 -a -f "$0" ] && MYSELF="./$0"
java=java
if test -n "$JAVA_HOME"; then
java="$JAVA_HOME/bin/java"
fi
exec "$java" $java_args -jar $MYSELF "$#"
exit 1
Then concatenate it with your uberjar:
cat stub.sh my-cli-command-uberjar.jar > my-cli-command && chmod +x my-cli-command
Now you can run it directly:
./my-cli-command args...
There is also a lein plugin automating this process: lein-binplus
I tried following the ClojureScript quick start guide http://clojurescript.org/guides/quick-start and hit an NPE trying to manually invoke the clojurescript compiler on OS X.
I have java 1.8.0_92
% javac -version
javac 1.8.0_92
I made a new directory (for the sake of completeness ~/tmp/clojure/cljstest/). All paths are relative to this directory. I think I am using version 1.9.293 of clojurescript.
% cat $(which cljsc)
#!/bin/bash
exec java -jar /usr/local/Cellar/clojurescript/1.9.293/libexec/cljs.jar "$#"
The cljsc jar by itself, however, works fine.
% cljsc
Clojure 1.8.0
user=>
I also downloaded the standalone cljs.jar mentioned in the tutorial and checked the md5sum to make sure that they're the same.
% wget https://github.com/clojure/clojurescript/releases/download/r1.9.293/cljs.jar
% md5 cljs.jar
MD5 (cljs.jar) = 658d7b722cebe46e36604baf9eecfcb5
% md5 /usr/local/Cellar/clojurescript/1.9.293/libexec/cljs.jar
MD5 (/usr/local/Cellar/clojurescript/1.9.293/libexec/cljs.jar) = 658d7b722cebe46e36604baf9eecfcb5
I ran
% mkdir -p src/hello_world
and then
% touch ./src/hello_world/core.cljs
The contents of ./src/hello_world/core.cljs are:
(ns hello-world.core)
(enable-console-print!)
(println "Hello World!")
The contents of ./build.clj are:
(require 'cljs.build.api)
(cljs.build.api/build "src" {:output-to "out/main.js"})
I downloaded clojure through homebrew
% where cljsc
/usr/local/bin/cljsc
This is a shell script that I used to locate the .jar
% cat $(which cljsc)
#!/bin/bash
exec java -jar /usr/local/Cellar/clojurescript/1.9.293/libexec/cljs.jar "$#"
I tried running the compiler with the explicit classpath given in the tutorial
% java -cp /usr/local/Cellar/clojurescript/1.9.293/libexec/cljs.jar:src clojure.main build.clj
That produced the following stack trace:
% java -cp /usr/local/Cellar/clojurescript/1.9.293/libexec/cljs.jar:src clojure.main build.clj
Exception in thread "main" java.lang.NullPointerException, compiling:(/Users/gregnisbet/tmp/clojure/cljstest/build.clj:3:1)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$script_opt.invokeStatic(main.clj:335)
at clojure.main$script_opt.invoke(main.clj:330)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:379)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.NullPointerException
at cljs.closure$build.invokeStatic(closure.clj:1920)
at cljs.build.api$build.invokeStatic(api.clj:198)
at cljs.build.api$build.invoke(api.clj:187)
at cljs.build.api$build.invokeStatic(api.clj:190)
at cljs.build.api$build.invoke(api.clj:187)
at user$eval24.invokeStatic(build.clj:3)
at user$eval24.invoke(build.clj:3)
at clojure.lang.Compiler.eval(Compiler.java:6927)
at clojure.lang.Compiler.load(Compiler.java:7379)
... 11 more
I expected the clojurescript compiler to either produce main.js or give me a clojurescript-related error message. Why is the ClojureScript compiler throwing a NullPointerException? Is it a compiler bug?
Is there some built-in functionality or plugin to lein to get a lein console, so for example one could test without waiting every time for JVM to start up.
$ lein console
>>> test
...
>>> test
...
>>> jar
Note: I'd like to trigger test runs myself, not e.g. by watching source files. That's why I'd like to have a lein console.
Clarification: I'm not looking for lein repl. I'd like to have a console where I could run lein task commands.
Older versions of leiningen used to include lein interactive, which behaved much like the feature you are asking for: it opened a shell into which you could type test and have it run lein test from the already-running lein jvm, and so on. This feature was removed in the transition to lein 2.0, I think, and although I don't know why I suspect there was a good reason. Maybe try asking in #leiningen on freenode?
You might want to have a look at grenchman. While it's not a Leiningen console it at least enables reusing of an existing REPL session. From what I gather, usage is as follows:
Move somewhere that is not inside a project and call:
$ lein repl :headless
Within your project directory, use:
$ grench lein <task> <options>
Tasks will be run inside the already spun up Leiningen JVM and the startup overhead should disappear.
Building grenchman seems to be tedious, though, and it is recommended to use one of the precompiled binaries (BUT they are currently not available).
And finally, that page also states:
Grenchman is still very new and may not be fully reliable.
So, good luck, I guess?
One option is to run a repl from leiningen's own jar file.
$ java -cp ~/.lein/self-installs/leiningen-2.5.0-standalone.jar clojure.main
Clojure 1.6.0
user=> (require '[leiningen.core.project :as project] '[leiningen.test :as test])
nil
user=> (def prj (project/read))
#'user/prj
user=> (test/test prj)
lein test org.noisesmith.orsos.load-test
Ran 3 tests containing 3 assertions.
0 failures, 0 errors.
nil
user=> (require '[leiningen.jar :as jar])
nil
user=> (jar/jar prj 'org.noisesmith.orsos)
Compiling org.noisesmith.orsos
Created /media/justin/806084F16084EEEA/clojure/orsos/target/orsos-0.1.0-SNAPSHOT.jar
{[:extension "jar"] "/media/justin/806084F16084EEEA/clojure/orsos/target/orsos-0.1.0-SNAPSHOT.jar"}
user=>
As a baseline, this can run lein tasks without having to restart lein every time. If you also use rlwrap or use nrepl it becomes a bit more usable. As far as I know there is no user friendly tooling around this (though there easily could be).
If you wish to use tasks from lein plugins those can be added to the -cp arg.
In clojure I can run:
lein run -m my.namespace # run the -main function of a namespace
and this will run my code from the command line.
Is there an equivalent for Clojurescipt to run the generated code in node.js? (In leiningen)
(I have read the doco for starting the Clojurescript REPL, for the running on node.js and the reply integrated into my application. I was just looking for a one-line command line solution.)
Depending on what your goal is, you might find it useful to use 'cljsbuild test'. You can specify a test context on your project.clj that uses node.js/v8/phantomjs.
Example:
:cljsbuild {
:test-commands {
"v8" ["v8"
"target/generated-sources/private/js/client.js"
"tests/v8-test-runner.js"]}}
v8-test-runner.js:
path.to.your.entrypoint.start()
You can also leave 'lein cljsbuild auto' running and start the javascript application directly:
v8 target/generated-sources/private/js/client.js tests/v8-test-wrapper.js
That's probably the best option if you are building a node.js application using clojurescript. You don't need to worry about classpaths in javascript (which is the major thing that lein run provides), you can just run your application directly from the assembled javascript file.
I downloaded Clojure 1.2 https://github.com/downloads/clojure/clojure/clojure-1.2.0.zip , extracted it under /Library directory, created CLOJURE_HOME, added $CLOJURE_HOME/script to my $PATH.
When I'm trying to run clj or repl scripts that are located under script directory, I'm getting this error:
Exception in thread "main" java.lang.NoClassDefFoundError: jline/
ConsoleRunner
Caused by: java.lang.ClassNotFoundException: jline.ConsoleRunner
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Ok, jline.jar isn't in the CLASSPATH so I checked clj and repl scripts:
CLASSPATH=src/clj:test:test-classes:classes/:script/jline-0.9.94.jar:../clojure-contrib/target/clojure-contrib-1.2.0-SNAPSHOT.jar
if [ -z "$1" ]; then
exec java -server jline.ConsoleRunner clojure.main
else
SCRIPT=$(dirname $1)
export CLASSPATH=$SCRIPT/*:$SCRIPT:$CLASSPATH
exec java -Xmx3G -server clojure.main "$1" "$#"
fi
I downloaded jline.jar under $CLOJURE_HOME/script but I'm still getting the same error.
This lead me to the question:
What is the role of https://github.com/downloads/clojure/clojure/clojure-1.2.0.zip anyway?
Is it supposed to be used to install Clojure? or just to to build and get clojure.jar?
I noticed no one is talking about installing Clojure this way.
Am I missing something?
Clojure, being a JVM language, has to deal with the JVM classpath. This makes 'installing' it a bit unwieldy and confusing. Rather than install it yourself like this, try out some tools like cljr and cake. I wrote a blog post about this that might be helpful: http://blog.raynes.me/?p=48
In summary: Check out cljr, cake, and leiningen.
The majority of people in the Clojure community don't have Clojure 'installed'. Most people use a build tool and/or cljr. It doesn't make a lot of sense to install Clojure to a central place when, inevitably, you're going to need dependency management, and jars will be copied around everywhere anyway. In any case, it's much easier to let a tool handle the classpath for you.
the clojure.zip file exists so people who write tools will have a place for their tools to get the parts they need ;)
For people not writing tools they are either working on/with the latest branch from github and so they get Clojure with a git pull or they are using the above mentioned liningen, cake, cljr , counterclockwise(eclipse), la clojure (intellij), or netbeans.