Use leiningen aliases to specify JVM flags - clojure

How can I specify JVM flags so that they apply only to one alias in a project.clj file?
Specifically I want to try the built in server capability in Clojure 1.8.0.
I can do this with an uberjar and the command:
java -Dclojure.server.interactive="{:port 8411 :accept srv.action/process}" -jar target\uberjar\srv-0.1.0-SNAPSHOT-standalone.jar
But I was hoping I could set that -D... from within a lein alias.
I tried this
:aliases {
"serve" [:jvm-opts ["-Dclojure.server.interactive={:port 8411 :accept srv.action/process}"] "run"]
}
But I get
java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String
Is it possible to do this?
I am using "Leiningen 2.6.1 on Java 1.8.0_92 Java HotSpot(TM) 64-Bit Server VM"

Leiningen profiles are definitely the way to do this. You can define a profile with any of the usual options, in your case :jvm-opts. In your profile.clj include something similar to the following:
:profiles {:clj-server {:jvm-opts ["-Dclojure.server.interactive={:port 8411 :accept srv.action/process}"]}}
Then you can tell leiningen you wish to use this profile via with-profile.
lein with-profile clj-server run
However, this will only use the options specified in the new profile. If you wish to activate the new profile in addition to the default profiles (dev, test, etc) you need to prepend the profile with a +.
lein with-profile +clj-server run
If you're lazy, like me, you can define an alias to run different tasks utilizing this newly defined profile:
:aliases {"clj-server-run" ["with-profile" "+clj-server" "run"]}
Then it's as easy as calling lein clj-server-run.
Hopefully this helps. I truly recommend reading through the leiningen documentation provided as well as its extremely useful.

I found an answer using profiles:
:profiles {:uberjar {:aot :all}
:server {:jvm-opts ["-Dclojure.server.interactive={:port 8411 :accept srv.action/process}"]}}
:aliases {
"serve" [ "with-profile" "server" "run"]})
I added a 'server' profile, which is allowed to specify its own :jvm-opts and then an alias to run that profile. It can be run with lein serve.
Any comments welcome.

Related

What is equivalent of leiningen :repl-options {:init-ns 'user} for tools.deps in Clojure?

I'm using Cursive and I set aliases to dev, when I run the REPL it does not load the namespace that defined in deps configuration file:
:aliases {:dev {:main-opts ["--init" "src/my/server/core.clj"
"--eval" "(my.server.core/-main)"]}}
I tried this at the command-line and it worked as expected, loading my.server.core and then running its -main function, so I suspect that Cursive is using -R on aliases rather than -A so it is only pulling in :extra-deps and not :main-opts (that's just a guess, I don't use Cursive). My best suggestion is to ask in the #cursive channel on the Clojurians Slack as that is the primary channel for Cursive support (as far as I know).
I'll also highlight Krisztian's comment that you could use "-m" "my.server.core" as your entire :main-opts since -m will load the namespace and run the -main within it.
However, those options are not the same as Leiningen's :init-ns -- what I think you need is:
{:aliases {:dev {:main-opts ["-e" "(require,'my.server.core)"
"-e" "(in-ns,'my.server.core)"]}}}
When you specify :main-opts, that will suppress starting a REPL:
$ clj -A:dev
#object[clojure.lang.Namespace 0x3dddbe65 "my.server.core"]
$
So you need to add -r to tell the Clojure CLI that you also want a REPL started:
clj -A:dev -r
#object[clojure.lang.Namespace 0x433ffad1 "my.server.core"]
my.server.core=> (doc -main)
-------------------------
my.server.core/-main
([& args])
I don't do a whole lot ... yet.
nil
my.server.core=>

How to change Lein's Clojure default version outside of a project directory?

This is asking for help regarding the same question as How to change Clojure or Lein's Clojure default version?
but is not an answer to that question. Should I have nevertheless have written it as an answer under that thread?
Specifying a Clojure version to be used when the "(lein repl)" command is issued outside of a project directory seems to be a natural thing to want. Of course there may be good design reasons for not allowing it, but do you think an error message like the following,
to be displayed when Leiningen detects that the ~/.lein/profiles.clj (or other relevant profile files) specify a different Clojure version from the one hard coded into Leiningen,
would be a good idea?
"specifying the Clojure version to be used with certain software, such as tools.nrepl and clojure-complete, is only allowed when this command is issued within a project directory"
A lot of people apparently have spent a lot of time on Stack Overflow trying to find out how to do this.
References:
"Updating ~/.lein/profiles.clj to {:repl {:dependencies [^:displace [org.clojure/clojure "1.9.0"]]}} does not seem to work. – Petrus Theron Jan 10 2018 at 9:05" How do you change Clojure version in Leiningen and LightTable?
"I asked technomancy on IRC just now. He said: "REPL's outside projects are hard coded to lein's version of clojure". – David J. Feb 24 '14 at 19:52" How to change Clojure or Lein's Clojure default version?
"this ^:displace trick will not work with tools.nrepl or clojure-complete." https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md
How to upgrade nrepl version of leiningen?
I think you may try to declare different profiles in your project.clj where each of them has its own Clojure version. For example:
:profiles
{;; :default [:base :system :user :provided :dev]
:server-jvm {:jvm-opts ^:replace ["-server"]}
:1.5 {:dependencies [[org.clojure/clojure "1.5.1"]]}
:1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]}
:1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]}
:1.8 {:dependencies [[org.clojure/clojure "1.8.0"]]}
:1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}}
Now that, when running any Lein command, specify a profile as follows:
lein with-profile 1.7 repl
The REPL session of Clojure 1.7 should start.
I grabbed that fragment from carmine sources. The official Lein profiles manual also has the same example.

Cider version does not match cider-nrepl version in new luminus project

I'm experimenting with luminus, and all new luminus projects are giving me the cider version/ cider-nrepl version mismatch error when I connect to the repl started by lein run using emacs M-x cider-connect:
WARNING: CIDER's version (0.14.0) does not match cider-nrepl's version (nil). Things will break!
If I ignore the automatically started nrepl and use M-x cider-jack-in to start a new repl I don't see the error. This is what I would normally use for a clojure project but there appear to be certain things that don't work as well using luminus (starting and stopping an h2 database if I recall correctly, but that is another issue).
I have removed my ~/.lein/profiles.clj file and replaced it with one containing just the cider-nrepl plugin, ie:
{:user
{:plugins
[[cider/cider-nrepl "0.14.0"]]}}
I have also tried adding the plugin via the project.clj file but I still get the error.
lein deps :tree gives me a few possible conflicts and suggests exclusions, but none of them involve nrepl or cider.
What am I missing here?
I seems you are not using ciders nrepl but luminus-nrepl - therefor you get
not match cider-nrepl's version (nil)
if you create a luminus project like so
lein new luminus <project-name> +cider
the warning should disappear.
addendum, lein deps :tree (which was a good approach to analyse the problem)
without +cider
[luminus-nrepl "0.1.4"]
[org.clojure/tools.nrepl "0.2.12" :exclusions [[org.clojure/clojure]]]
with +cider
[cider/cider-nrepl "0.15.0-20170626.002218-19"]
[luminus-nrepl "0.1.4"]
[org.clojure/tools.nrepl "0.2.12" :exclusions [[org.clojure/clojure]]]

Using a mirror of Clojars from Leiningen

The following Wiki page describes a straightforward way of setting up Leiningen to use a mirror of Clojars.org: https://github.com/clojars/clojars-web/wiki/Mirrors
Based on this, I have put the following as my ~/.lein/profiles.clj:
{:user {:mirrors
{#"clojars" {:name "clojars mirror"
:url "https://clojars-mirror.tcrawley.org/repo/"}}}}
However, even with this profiles.clj, I can still see in e.g. Wireshark that lein is trying to connect to clojars.org instead of clojars-mirror.tcrawley.org. What setting am I missing?
My Leiningen version is
Leiningen 2.5.3 on Java 1.7.0_91 OpenJDK 64-Bit Server VM
I couldn't get a mirror working by modifying profile.clj either.
However I was able to get it working for a specific project.clj by adding this within defproject
:mirrors {#"clojars" {:name "Clojar Mirror"
:url "https://clojars-mirror.tcrawley.org/repo/"
:repo-manager true}}
Notes:
This came from the official Leiningen sample project.clj:
https://github.com/technomancy/leiningen/blob/master/sample.project.clj
I tried following the below for global setting in profile.clj (the syntax is somewhat different from yours) but had no luck:
https://github.com/technomancy/leiningen/issues/271#issuecomment-21108691
https://stackoverflow.com/a/17697119/617320

Lein console (like sbt)

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.