TLDR;
lein repl starts in the namespace defined by :main in project.clj, instead of user, as desired.
Details
I have a Leiningen project which is deployed as a command-line application in an uberjar, so I can run it like so:
java -jar my-app-1.0-standalone.jar --some --args
I also have a dev/user.clj to give me a nice REPL environment, as described here.
My project.clj looks like this:
(defproject my-app "1.0"
:main my-app.cli
:aot [my-app.cli]
:profiles {:dev {:source-paths ["src" "dev"]}})
When I start my REPL, either with lein repl from the command line or M-x cider-jack-in from Emacs, I am in the my-app.cli namespace, rather than user.
If I remove :main my-app.cli from project.clj, my REPL starts in the user namespace as I'd expect, but clearly this breaks my uberjar.
Any ideas?
When lein repl task runs, it will look up the ns to switch to in this order of preference:
ns specified in the :init-ns of the :repl-options
ns specified :main
user ns
In your case, try adding:
:repl-options {:init-ns user}
to your project.clj
Related
I have followed the readme from the lein new re-frame <project-name>template exactly, but I get the error:
No :main namespace specified in project.clj.
I know this is a well documented error, but when I add the line :main my-first-reframe-app.core to my project.clj and a -main function to core.cljs namespace, the compiler throws a huge error when I use lein dev.
Why won't this template run out of the box for me and how should I fix the problem? Thanks.
/edit Nowadadays, as can be seen in the README of the downloaded template
Use:
lein watch
and navigate to http://localhost:8280/ to see the started shadow-cljs app in development mode.
.lein/profiles.clj has dependencies as,
{:user {}
:repl {:dependencies [[org.clojure/clojure "1.4.0"]
[ring/ring "1.1.6"]]
}}
in repl
(require 'ring.adapter.jetty)
throws,
java.io.FileNotFoundException: Could not locate ring/adapter/jetty__init.class or ring/adapter/jetty.clj on classpath: (NO_SOURCE_FILE:0)
This means, ring dependency is not loaded in repl shell. Any mistakes?
Firstly, I would recommend reading https://github.com/technomancy/leiningen/blob/stable/doc/PROFILES.md as I'm not sure you are using profiles correctly. In particular, at the end it shows a way of debugging your profiles, which will show you what is going on.
Secondly, I'm not sure about "there is no project - I am running it from bash shell". If your loading jetty and using ring, you will also need code which sets handlers, routes and probably middleware. this means code files, which means a project tree. Create a basic project with lein new and run from the root of that project.
However, if you really do need to do it as you say, I would suggest you just do
{:user {:dependencies [[....]]}} as your profiles.clj as I suspect that what is happening is that lein is not loading your :repl profile. You could also try running lein with the explicit profile i.e. lein with-profile +repl repl
I am trying to use environ to access environment variables specified in my project.clj :dev profile. This looks like a nice way to set up different configuration options, but I can't seem to get it to work. My project.clj entry looks like this:
:profiles
{:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
[ring-mock "0.1.5"]]
:env {:foo "FOO" :bar "BAR"}}}
If I run lein repl and require then enter (with in-ns) a namespace from my project, environ.core/env just returns nil:
(environ.core/env :foo)
nil
Adding an :env entry to the :user profile in .lein/profiles.clj also doesn't work. What am I doing wrong?
OK, it was a case of reading the docs more thoroughly. :) To access environment variables specified in the project map you need the lein-environ plugin. Add it like this:
:plugins [[lein-environ "0.4.0"]]
That worked. It's easy to miss that in the docs though.
I want to create a number of uberjars with different main entrypoints from a single codebase. I see you can specify the main namespace as an argument to lein uberjar but I don't see a way to specify the resulting filename or path, so they'll just overwrite one another. Is there a way to override the output filename or path from the command line?
Or is there a better way of doing this? Have separate project files that all reference a central "library" project? If so, what would the physical structure of this look like and how to get it to build?
You can use multiple Leiningen profiles to accomplish what you are talking about.
(defproject project1 "0.1.0-SNAPSHOT"
:description "Something Amazing!"
:dependencies [[org.clojure/clojure "1.5.1"]]
:profiles {:v1 {:main project1.core1
:uberjar-name "uberjar1.jar"}
:v2 {:main project1.core2
:uberjar-name "uberjar2.jar"}
:v3 {:main project1.core3
:uberjar-name "uberjar3.jar"}})
And, you can build them with:
$ lein with-profile v1:v2:v3 uberjar
Here is an annotated reference source where you can find an option for specifying a name of your output jar or uberjar file and any other options that may be set in a project.clj file.
;;; Jar Output
;; Name of the jar file produced. Will be placed inside :target-path.
;; Including %s will splice the project version into the filename.
:jar-name "sample.jar"
;; As above, but for uberjar.
:uberjar-name "sample-standalone.jar"
I'm a beginner with clojure, only starting it yesterday.
I have gathered that a simple way to create a standalone app is with leiningen lein new foo.
I tried to create a hello world test project with leiningen. I added :main and :aot directives to project.clj, added :gen-class to the core.clj file and tried lein run, but I get errors about class definition not found.
Exception in thread "main" java.lang.NoClassDefFoundError:
Caused by: java.lang.ClassNotFoundException:
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
The core.clj file
(ns test.core
(:gen-class))
(defn -main [& args] (println "Hello main"))
And the project.clj file
(defproject test "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:main test.core
:aot [test.core]
:dependencies [[org.clojure/clojure "1.2.1"]])
Edit: After further testing, it seems like copying the project to my desktop works as is, which I think points to that the environment on my laptop is somehow borked, but I don't know how.
The environment on desktop is clojure from repositories and leiningen from AUR. On laptop the clojure is from clojure.org and leining is from github.
[UPDATE April 2013]
Leiningen 2, which has been officially released for some time, includes the concept of project templates. By default, Leiningen provides an app template that provides what you need out of the box. Try:
lein new app my-project
You will see that Leiningen creates the familiar project template, but also includes:
The default namespace of my-project.core as the :main entry in your project.clj file
The :gen-class form in the namespace declaration of my-project.core
A default -main function in the my-project.core namespace
For those who cannot yet use Leiningen 2, the lein-newnew plugin provides an equivalent experience under Leiningen 1.
[/UPDATE]
To build a project that, when run, prints "Hello World!", you'd do as follows (revision of your process above):
Setup
lein new my-project
cd my-project
lein deps
You should now have a basic structure in place and the Clojure jar in your lib folder.
Write a Function
Now edit src/my_project/core.clj with your editor of choice, adding the following below the (ns ...) form:
(defn -main []
(println "Hello World!"))
This function is inside your my-project.core namespace. To ensure this gets run as your main, let's add a gen-class parameter to your namespace definition at the top, so that it now looks like this at the top of core.clj:
(ns my-project.core
(:gen-class :main true))
So all together, your core.clj file looks like this:
(ns my-project.core
(:gen-class :main true))
(defn -main []
(println "Hello World!"))
Configure it as the Main Function
Once you've got src/my_project/core.clj edited as above, you need to tell Leiningen (the build tool) where the "main" function for your project lives. Here's an example defproject form that does this:
(defproject my-project "1.0.0-SNAPSHOT"
:description "My Project"
:dependencies [[org.clojure/clojure "1.2.1"]]
:main my-project.core)
Now the -main function inside my-project.core becomes the entry-point for your program.
Run It
You can now have two options for running this project:
Use lein run at the command-line while at the root of your my-project project
Create a standalone jar file by running lein uberjar. You can then run the resultant jar file by running java -jar my-project-1.0.0-SNAPSHOT-standalone.jar
Figured it out. I had the latest leiningen from git, which was borked somehow. I checked out the 1.6.1 tag and ran self-install, and now it works.
I missed it, You named your project test, you can't do that change the name to something else it will work.
You say above
lein new foo
what you mean is
lein new test