Compiling ClojureScript from cljc files with lein - clojure

Does cljc / lein / clojurescript work yet?
I was previously using cljx, and was able to compile the same project with the cljx plugin for lein firing off a cljsbuild task.
Now I'm switching to cljc, I want to compile my cljc files into both compiled Java and into javascript for use in the browser.
Here's my current project.clj file
(defproject com.mysite/myproj "0.3.2-SNAPSHOT"
:description ""
:url ""
:license {:name "Gnu Lesser Public License"
:url "https://www.gnu.org/licenses/lgpl.html"}
:dependencies [[org.clojure/clojure "1.7.0"]]
:plugins [[lein-cljsbuild "1.0.3"]
[lein-localrepo "0.4.0"] ]
:source-paths ["cljc" "src" ]
:cljsbuild {:builds [{
:source-paths ["cljc" ]
:compiler {
:output-to "browser-based/js/main.js"
:optimizations :whitespace
:pretty-print true }
} ]}
:hooks [leiningen.cljsbuild]
:aot [myproj.core]
:main myproj.core)
I don't remember exactly where I copied some of this from, but I assume that the leiningen.cljsbuild hook was what automatically fired off the cljs build process. However after removing the cljx plugin, and moving to cljc, this is successfully compiling the Java version of my program but doesn't seem to be producing any javascript.

Yes, it works.
Try with:
(defproject com.mysite/myproj "0.3.2-SNAPSHOT"
:description ""
:url ""
:license {:name "Gnu Lesser Public License"
:url "https://www.gnu.org/licenses/lgpl.html"}
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.28"]
:plugins [[lein-cljsbuild "1.0.6"]
[lein-localrepo "0.4.0"]]
:source-paths ["cljc" "src"]
:cljsbuild {:builds [{
:source-paths ["cljc" "src"]
:compiler {:output-to "browser-based/js/main.js"
:optimizations :whitespace
:pretty-print true}}]}
:hooks [leiningen.cljsbuild])
Then run: lein compile or lein cljsbuild once
Please note that I changed the :source-paths under :cljsbuild to include "src": :source-paths ["cljc" "src"]. Apart from that I added an explicit dependency on clojurescript and bumped cljsbuild version to 1.0.6
By the way, why do you have a separate cljc directory? You can have your cljc, clj & cljs files sharing the same directory structure.

Related

FileNotFoundException with Leiningen and Ring

I'm currently using Leiningen and Ring through the command line on a project I'm making called reagent_test, and I ran into a problem:
C:/...reagent_test>lein ring server
... huge chunk of errors
Caused by: java.io.FileNotFoundException: Could not locate reagent_test/core__init.class or reagent_test/core.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
... more errors
If anyone wants a gist for the issue, I'll make one if needed.
The problem is, the files are all in the right place. Here's my project.clj:
(defproject reagent-test "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:plugins [[lein-cljsbuild "1.1.5"]
[lein-ring "0.10.0"]]
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.456"]
[ring "1.4.0"]
[leiningen "2.7.1"]
[reagent "0.6.0"]
[garden "1.3.2"]]
:cljsbuild {:builds {:app {:source-paths ["src/cljs"]}
:compiler {:output-to "resources/public/main.js"
:pretty-print true}}}
:ring {:handler reagent-test.core/-main})
And my project structure is like this (at least, for the relevant files):
src:
clj:
reagent_test:
core.clj
cljs:
reagent_test:
core.cljs
project.clj
In both core.clj and core.cljs I have this as my namespace:
(ns reagent-test.core)
NOTE: Folders have a colon and files don't.
In the namespace declaration at the top of the file you should use a dash:
(ns reagent-test.core)
Whereas the file (and all the directories above the file) should use underscores. So the filename should be whatever/reagent_test/core.clj or whatever/reagent_test/core.cljs.
As Chris Murphy has pointed out in the comments of his answer. Since you have changed your project directory structure a little, you will need to modify your project.clj file:
(defproject reagent-test "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:plugins [[lein-cljsbuild "1.1.5"]
[lein-ring "0.10.0"]]
:source-paths ["src/clj"]
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.456"]
[ring "1.4.0"]
[leiningen "2.7.1"]
[reagent "0.6.0"]
[garden "1.3.2"]]
:cljsbuild {:builds {:app {:source-paths ["src/cljs"]}
:compiler {:output-to "resources/public/main.js"
:pretty-print true}}}
:ring {:handler reagent-test.core/-main})
The addition is the :source-paths key which should specify the directory for the Clojure code. By default lein uses the src directory as the root for the Clojure source files.

Trouble testing Leiningen plugin against latest Clojure

I am trying to update lein-resource to use clojure.spec which requires the alpha version of Clojure [org.clojure/clojure "1.9.0-alpha13"]. When I add the dependency it compiles ok but the REPL and testing use the lein version of Clojure 1.8.0.
If I set :eval-in-leiningen to false, it respects the Clojure dependency.
How can I test a lein plugin with a different version of Clojure without disabling the ability for it to run as a plugin?
I'm guessing that your project.clj is getting overridden by your file ~/.lein/profiles.clj. Mine looks like this:
> cat ~/.lein/profiles.clj
{ :user {
:plugins [
[com.jakemccrary/lein-test-refresh "0.16.0"]
[jonase/eastwood "0.2.3"]
[lein-ancient "0.6.0"]
[lein-codox "0.9.3"]
[lein-exec "0.3.6"]
]
:dependencies [
[org.clojure/clojure "1.9.0-alpha13"]
]
:test-refresh { :quiet true
:changes-only true }
; :jvm-opts ["-Xms1g" "-Xmx4g" ] ; "-server"
}
}
I'm assuming your project.clj should look something like this:
(defproject clj "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [
[org.clojure/clojure "1.9.0-alpha13"]
[tupelo "0.9.9"]
]
:java-source-paths ["/home/alan/xpr/src"]
:main ^:skip-aot clj.core
:target-path "target/%s"
:profiles {:dev {:dependencies [[org.clojure/test.check "0.9.0"]] }
:uberjar {:aot :all}}
)
Fix up your ~/.lein/profiles.clj and you should have no problem.
Turns out the problem is :eval-in-leiningen true in the project.clj. It is a bit of a catch-22. If it is there, it forces the test to run with the version of Clojure defined with the installed with lein. If it is removed, the lein dependecies in the code are not resolved.

How to create an uberjar correctly with "lein uberjar"?

if I use lein run the project is no problem.
But when I use jave -jar blog.jar after lein uberjar It happen exceptions.
16-Jul-20 11:28:05 DESKTOP-C3SC9AR INFO [slf4j-timbre.adapter] - >> starting.. *db*
Exception in thread "main" java.lang.RuntimeException: could not start [*db*] due to
.....
Caused by: java.lang.Exception: :jdbc-url, :datasource, or :datasource-
AND my project.clj file
(defproject blog "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies ....
:min-lein-version "2.0.0"
:uberjar-name "blog.jar"
:jvm-opts ["-server"]
:main blog.core
:migratus {:store :database}
:plugins [[lein-environ "1.0.1"]
[migratus-lein "0.2.0"]]
:profiles
{:uberjar {:omit-source true
:env {:production true}
:aot :all
:source-paths ["env/prod/clj"]}
:dev [:project/dev :profiles/dev]
:test [:project/test :profiles/test]
:project/dev ...
:project/test ...
:profiles/dev {:env {:database-url "jdbc:postgresql://localhost/blog?user=postgres&password=root"}}
:profiles/test {}})
Maybe it can't find the key of "database-url"?
Data provided via environment settings in project.clj are not provided when you use java directly. It's your responsibility to make sure the environment settings visible to the app provide any credentials or connection info needed.
It could look something like:
DATABASE_URL="jdbc...." java -jar my-project-standalone.jar

Resource not found : Exception Directory does not exist: resources ring.middleware.file/ensure-dir (file.clj:12)

I am deploying a Clojure project built on luminus on Ubuntu server. When I try to start my server I get the following exception:
Exception Directory does not exist: resources ring.middleware.file/ensure-dir (file.clj:12)
This is my project.clj file
(defproject big5 "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]
[lib-noir "0.5.0"]
[compojure "1.1.5" :exclusions [ring/ring-core]]
[com.cemerick/friend "0.1.5"]
[ring-server "0.2.7"]
[clabango "0.5"]
[korma "0.3.0-RC6"]
[mysql/mysql-connector-java "5.1.6"]
[com.taoensso/timbre "2.7.1"]
[com.taoensso/tower "2.0.1"]
[com.postspectacular/rotor "0.1.0"]
[markdown-clj "0.9.19"]
[clj-json "0.5.3"]
[clj-time "0.6.0"]
[log4j "1.2.17"
:exclusions
[javax.mail/mail
javax.jms/jms
com.sun.jdmk/jmxtools
com.sun.jmx/jmxri]]
[org.slf4j/slf4j-log4j12 "1.7.5"]]
:plugins [[lein2-eclipse "2.0.0"]
[lein-ring "0.8.7"]
[lein-midje "3.0.0"]]
:ring {:handler big5.handler/war-handler
:init big5.handler/init
:destroy big5.handler/destroy}
:profiles
{:production {:ring {:open-browser? false
:stacktraces? false
:auto-reload? false}}
:dev {:dependencies [[ring-mock "0.1.3"]
[ring/ring-devel "1.1.8"]
[midje "1.5.1"]]}}
:min-lein-version "2.0.0")
I believe Leiningen uses the resources directory as the classpath root. Typically resources/public is where you store your static web assets like images, javascript, and stylesheets. If you create those directories you should be good.
Here are some references for you:
Resources in Clojure applications
Serving static files with ring/compojure - from a war
Finally, from the luminus documentation itself:
http://www.luminusweb.net/docs#anatomy_of_a_luminus_application

Auto building Clojurescript files for Compojure app

I have a web application where i'm using Compojure on the server and Clojurescript on the client. I'm using the leing-cljsbuild plugin to automatically compile cljs files to js.
I'm able to generate the required client side files and load them in the browser when I set the optimizations to :whitespace or :simple, but when I set optimizations to none, the js files reference their dependencies using the local file-system path, which leads to the files not loading at all in the browser.
So, my question is how do I make the generated files use server urls instead of local file paths when they are generated by the clojurescript compiler.
Here's my project.clj file
(defproject my-proj-clj "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies [[org.clojure/clojure "1.5.1"]
[compojure "1.1.6"]
[org.clojure/tools.nrepl "0.2.3"]
[hiccup "1.0.3"]
[com.novemberain/monger "1.5.0"]
[org.clojure/clojurescript "0.0-2127"]
[jayq "2.5.0"]
]
:plugins [[lein-ring "0.8.8"]
[lein-cljsbuild "1.0.1"]
]
:ring {:handler my-proj-clj.handler/app
}
:cljsbuild { :builds
[{
:source-paths ["src/my-proj-clj"]
:compiler {
:output-dir "./resources/public/js"
:output-to "./resources/public/js/cljs-file.js"
:pretty-print true
:source-map "./resources/public/js/cljs-file.js.map"
:optimizations :none
}}]}
:profiles {:dev {:dependencies [[javax.servlet/servlet-api "2.5"]]}}
I believe the only valid optimization values are :whitespace, :simple, or :advanced. See line 96 at https://github.com/emezeske/lein-cljsbuild/blob/1.0.1/sample.project.clj.
Thus I would use :whitespace as the optimization level (at least to get something working).
Per your post, an optimization level of :whitespace works? Thus, perhaps you can elaborate.
What results are you expecting from an optimization level of ":none". How does your expected result differ from what an optimization level of :whitespace produces?
An optimization level of :none means cljsbuild is not generating js from your cljs source (it will generate a few goog.include statements but nothing else). Try using an interactive repl to help you prototype. Try running the following : lein trampoline cljsbuild repl-rhino
Hope that helps.
I have roughly same setup, optimizations set to :none, generated files use local paths. However, browser does load the scripts.
What I have is this in index.html:
<script src="js/development/goog/base.js" type="text/javascript"></script>
<script src="js/development/main.js" type="text/javascript" ></script>
<script type="text/javascript">goog.require("ixtlan.core");</script>
this in project.clj:
:cljsbuild {
:builds [{:id "dev"
:source-paths ["src/cljs"]
:compiler {
:output-to "resources/public/js/development/main.js"
:output-dir "resources/public/js/development"
:optimizations :none
:source-map true}}
...
and routes contain:
(defroutes routes
(GET "/" [] (index))
(route/files "/" {:root "resources/public"}))
Hope, this helps.