Skip to content

Instantly share code, notes, and snippets.

@zentrope
Forked from rauhs/Makefile
Last active September 6, 2015 17:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zentrope/60960df050c1b8d997c3 to your computer and use it in GitHub Desktop.
Save zentrope/60960df050c1b8d997c3 to your computer and use it in GitHub Desktop.
Compiling clojurescript + figwheel without boot nor leiningen. Using leiningen to manage dependencies.
CLJ_NREPL_PORT:=22340
CLJS_JAR_VERSION:=1.7.48
CLJS_JAR_URL:=https://github.com/clojure/clojurescript/releases/download/r$(CLJS_JAR_VERSION)/cljs.jar
.PHONY: def_target
def_target : null
# http://blog.jgc.org/2015/04/the-one-line-you-should-add-to-every.html
# Allows:
# make print-SOURCE_FILEE
print-%: ; @echo $*=$($*)
# We use `lein run` to run the cljs compiler scripts since we need the
# classpath properly set:
# We could also do a lower level and use the standalone jar of cljs to test
# different versions quickly:
cljs-c-jar-dev :
java -cp cljs-$(CLJS_JAR_VERSION).jar:scripts:$$(lein with-profile +dev-cljs classpath) \
clojure.main scripts/cljs-build.clj dev
cljs-c-dev :
lein with-profile +dev-cljs run -m clojure.main scripts/cljs-build.clj dev
cljs-c-simple :
lein with-profile +prod-cljs run -m clojure.main scripts/cljs-build.clj simple
cljs-c-production :
lein with-profile +prod-cljs run -m clojure.main scripts/cljs-build.clj production
figwheel :
@echo "Starting a figwheel server. Note: Do not use the printed fighweel URL" \
" but use the clojure server instead. Needs to be started :)";
lein with-profile +dev-cljs run -m clojure.main scripts/figwheel-cljs-repl.clj
dl-cljs :
curl -L $(CLJS_JAR_URL) > cljs-$(CLJS_JAR_VERSION).jar
#TODO: cljs autotest

Synopsis:

Compiling clojurescript + figwheel without boot nor leiningen. Using leiningen to manage dependencies.

Note:

The below filesnames have || in them. That's because gist doesn't allow subdirectories. But the script are all in a ./scripts/ subdir.

Usage

You can have contious (watching) builds by running make in multiple terminals:

make cljs-c-dev
make cljs-c-simple
etc..

You can run figwheel from the command line with:

make figwheel

You can run fighweel from Cursive by adding it as Use clojure.main in normal JVM process and call the figwheel repl in scripts.

I'm sure you can somehow also do the same in Emacs.

(defproject xyz "0.1.0-SNAPSHOT"
:description "TODO description"
:dependencies [;; CLJ or common
[org.clojure/clojurescript "1.7.122"]
;; Example dependency:
[org.omcljs/om "0.9.0"]
[precursor/om-i "0.1.7"] ;; perf inspect om stuff
[prismatic/om-tools "0.3.12"]
[secretary "1.2.3"] ;; Routing alternative to bidi
[sablono "0.3.6"] ;; [:html]
[hodgepodge "0.1.3"] ;; localstorage idiomatic interface
[cljs-ajax "0.3.14"]
[cljsjs/react "0.13.3-1"]
;;[reagent "0.5.0" :exclusions [cljsjs/react]]
[klang/klang "0.2.0-SNAPSHOT"] ;; cljs logging
;; TOOLING
[figwheel-sidecar "0.3.7" :scope "provided"]]
:plugins [[lein-environ "1.0.0"]
[lein-figwheel "0.3.7"]]
;; Some speedup
;; https://github.com/technomancy/leiningen/wiki/Faster
:jvm-opts ["-Xverify:none"]
;; We dont have "one" source path when doing CLJS+CLJ in one project, we always
;; specify these in the profiles
;;:source-paths ["src" "target/classes"]
;; TODO: Temporary workaround for Cursive can't start a REPL with profiles so
;; we need to specify everything here:
;; The ^:replace meta keys in the profiles will overwrite this and make it a non-issue.
;; Also see Cursive issue 1036
;; NOTE: This also gets picked up by Cursive/IntelliJ every time it starts:
;; So this is ONLY really set for Cursive ATM:
:source-paths ["src/clj" "src/cljs" "src/cljc"
"env/dev/cljs" "env/dev/clj"
"env/prod/cljs" "env/prod/clj"]
;; No magic aliases here, Makefiles are better, we get autocomplete on the command line for
;; instance
;;:aliases {"msg-client" ["run" "-m" "srs.remote-messaging-client"]}
:resource-paths ["resources"]
;; All generated files will be placed in :target-path. In order to avoid
;; cross-profile contamination (for instance, uberjar classes interfering
;; with development), it's recommended to include %s in in your custom
;; :target-path, which will splice in names of the currently active profiles.
:target-path "target/%s/"
;; Directory in which to place AOT-compiled files. Including %s will
;; splice the :target-path into this value.
:compile-path "%s/class-files"
:clean-targets ^{:protect false} ["resources/public/js/" "target"]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Not using cljsbuild anymore, it hangs up all the time for me and I can't debug it
;;:cljsbuild {:builds }
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
:profiles {
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dependencies for development
;; This profile gets merged into other profiles (see "leiningen composite profiles")
:dev-cljs-deps
{
:dependencies [
;; cljs builds that re-run when a macro file (.clj) is changed
;; TODO: Not yet used, mabye soon.
[clojurescript-build "0.1.9"]
]
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Env for clojurescript dev environ
:dev-cljs
[:dev-cljs-deps
{:source-paths ^:replace ["src/cljs" "src/cljc" "env/dev/cljs"]
:env {:is-dev true}}]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Env for clojurescript prod environ
:prod-cljs
[:dev-cljs-deps
{:source-paths ^:replace ["src/cljs" "src/cljc" "env/prod/cljs"]
:env {:is-dev false}}]
};; profiles
);; defproject
(require 'cljs.build.api)
(def build-id
(keyword (first *command-line-args*)))
(def errors
{:no-build-id "You have to pass in a build id"
:no-such-build "Could not find the build id"})
(defn err [ev]
(println (get errors ev))
(System/exit 1))
(when-not build-id
(err :no-build-id))
(def all-builds
(-> (slurp "scripts/cljs-builds.edn")
read-string))
(defn start-c [opts]
(cljs.build.api/watch
(apply cljs.build.api/inputs (:source-paths opts))
(:compiler opts)))
(if-let [build (get all-builds build-id)]
(start-c build)
(err :no-such-build))
{:dev
;;;;;;;;;;;;;;;;;;;;;;; Development build
{
:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
:figwheel {:websocket-host "localhost"
:on-jsload "srs-c.dev/on-js-reload"}
:compiler {:main "srs-c.dev"
;; :asset-path is a relative URL path not a file system path.
:asset-path "js/dev/compiled/out" ;; See :output-dir
:output-dir "resources/public/js/dev/compiled/out"
:output-to "resources/public/js/dev/compiled/srs-dev.js"
:pretty-print true
:optimizations :none
:source-map-timestamp true
}
}
;;;;;;;;;;;;;;;;;;; Development build with modules
;; NOTE: Simple + Modules doesn't do any code motion it seems, so the modules
;; are still relatively small and most of the code is in cljs-base
:simple
{
:source-paths ["src/cljs" "src/cljc" "env/prod/cljs"]
:compiler {;;:main srs-c.dev
:output-dir "resources/public/js/simple/compiled/out"
:optimizations :simple
;;:optimizations :advanced
:pretty-print true
:elide-asserts false
:closure-defines {"goog.DEBUG" true}
:source-map true ;; for all modules
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MODULES ;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Any namespaces not in an :entries set will be moved into the default
;; module :cljs-base
;; Google Closure can move functions and methods into the modules where
;; they are actually used. This process is somewhat conservative so if
;; you know that you want to keep some code together do this via :entries
:modules
{;;:cljs-base {} ;; created by cljs
:common
{:output-to "resources/public/js/simple/compiled/srs-common.js"
:entries #{"srs-c.modules.common"}}
:login
{:output-to "resources/public/js/simple/compiled/srs-login.js"
:entries #{"srs-c.modules.login"}}
;; dev module contains ALL the code.
:dev
{:output-to "resources/public/js/simple/compiled/srs-dev.js"
:entries #{"srs-c.modules.dev"}
:depends-on #{:common :login}}
};; modules
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Compile time type checking:
;;:closure-warnings
#_{:check-types :warn ;; This gives a NPE:
:undefined-names :off
:externs-validation :off
:missing-properties :off}}
}
;;;;;;;;;;;;;;;;;;; Advanced but readable
:pseudo-advanced
{
:source-paths ["src/cljs" "src/cljc" "env/prod/cljs"]
:compiler {;;:main srs-c.dev
:output-dir "resources/public/js/pseudo-advanced/compiled/out"
:optimizations :advanced
:pretty-print true
:pseudo-names true
:elide-asserts false
:closure-defines {"goog.DEBUG" false}
:source-map true ;; for all modules
:modules
{;;:cljs-base {} ;; created by cljs
:common
{:output-to "resources/public/js/pseudo-advanced/compiled/srs-common.js"
:entries #{"srs-c.modules.common"}}
:login
{:output-to "resources/public/js/pseudo-advanced/compiled/srs-login.js"
:entries #{"srs-c.modules.login"}}
;; dev module contains ALL the code.
:dev
{:output-to "resources/public/js/pseudo-advanced/compiled/srs-dev.js"
:entries #{"srs-c.modules.dev"}
:depends-on #{:common :login}}
};; modules
}
}
;;;;;;;;;;;;;;;;;;; Actual production builds
:production
{
:source-paths ["src/cljs" "src/cljc" "env/prod/cljs"]
:compiler {:output-dir "resources/public/js/advanced/compiled/out"
:optimizations :advanced
:pretty-print false
:pseudo-names false
:elide-asserts true
:closure-defines {"goog.DEBUG" false}
:source-map true
:modules
{;;:cljs-base {} ;; created by cljs
:common
{:output-to "resources/public/js/advanced/compiled/srs-common.js"
:entries #{"srs-c.modules.common"}}
:login
{:output-to "resources/public/js/advanced/compiled/srs-login.js"
:entries #{"srs-c.modules.login"}}
;; dev module contains ALL the code.
:dev
{:output-to "resources/public/js/advanced/compiled/srs-dev.js"
:entries #{"srs-c.modules.dev"}
:depends-on #{:common :login}}
};; modules
}
}
}
(use 'figwheel-sidecar.repl-api)
(def builds
(read-string (slurp "scripts/cljs-builds.edn")))
(start-figwheel!
{:all-builds builds
:figwheel-options
{:css-dirs ["resources/public/css"]
:websocket-host "localhost"
;; The port of the fighweel server, the browser connects to this:
:server-port 22341
;; The bind IP of the figwheel server
:server-ip "127.0.0.1"
}})
;; The cljs repl is NOT an nrepl. So you have to interact with the prompt
(cljs-repl)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment