Open devth opened 8 years ago
Would something like this work in your case?
(defproject my-project "0.1.0-SNAPSHOT"
:description "FIXME: write this!"
:url "http://example.com/FIXME"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.8.51"]]
:source-paths ["src"]
:clean-targets ["out"]
:target-path "target"
:plugins [[lein-cljsbuild "1.1.3"]]
:cljsbuild {:builds {:my-project {:source-paths ["src"]
:compiler {:my-project my-project.core
:output-to "out/my_project.js"
:output-dir "out"
:source-map "out/map.js.map"
:pretty-print true}}}}
:profiles {:dev {:cljsbuild {:builds {:my-project {:compiler {:verbose true}}}}}
:release {:cljsbuild {:builds {:my-project {:compiler {:optimizations :advanced}}}}}})
If not, do you have a certain config structure in mind that would be helpful in your case? It would be great if you could give a minimal example of a current config of yours and how you would like it to be instead.
Your example is essentially what I'm doing now, but results in a fair amount of duplication when dealing with multiple builds. For example, I have several foreign libs that need to be duplicated across every build.
e.g. with two separate builds:
:cljsbuild {:builds {:build1 {:source-paths ["src/build1"]
:compiler {:my-project build1.core
:output-to "build1/out.js"
:output-dir "build1/out"
:source-map "build1/out/map.js.map"
:pretty-print true}}
:build2 {:source-paths ["src/build2"]
:compiler {:my-project build2.core
:output-to "build2/out.js"
:output-dir "build2/out"
:source-map "build2/out/map.js.map"
:pretty-print true}}}}
Now if I want to add the same set of foreign libs to all my builds I need to set them individually, either inline or using a profile – in either case there will still be a separate :foreign-libs
for each build.
What I'd like to do is set cljsbuild configuration globally for all builds using a profile, then mix-in that profile for dev
and release
(in this example), e.g.:
:profiles {:cljs-shared
;; common configuration shared across all builds
{:cljsbuild {:compiler {:foreign-libs [{:file "file1.js" :provides ["Lib1"] :language-in :ecmascript5}
{:file "file2.js" :provides ["Lib2"] :language-in :ecmascript5}
{:file "file3.js" :provides ["Lib3"] :language-in :ecmascript5}]}}}
;; dev only configuration for all builds
:dev [:cljs-shared
{:cljsbuild {:compiler {:verbose true}}}]
;; release only config for all builds
:release [:cljs-shared
{:cljsbuild {:compiler {:optimizations :advanced}}}]})
So I think what would need to happen is: if a :cljsbuild
map doesn't specify {:build {:somebuild {...}}
, then it should apply the configuration across all build configurations.
Other ideas for removing duplication of common configuration across build1
and build2
?
Your example should work if you specify the same build id across the different profiles, e.g.:
:profiles {:cljs-shared
;; common configuration shared across all builds
{:cljsbuild {:builds {:app {:compiler {:foreign-libs [{:file "file1.js" :provides ["Lib1"] :language-in :ecmascript5}
{:file "file2.js" :provides ["Lib2"] :language-in :ecmascript5}
{:file "file3.js" :provides ["Lib3"] :language-in :ecmascript5}]}}}}}
;; dev only configuration for all builds
:dev [:cljs-shared
{:cljsbuild {:builds {:app {:compiler {:verbose true}}}}}]
;; release only config for all builds
:release [:cljs-shared
{:cljsbuild {:builds {:app {:compiler {:optimizations :advanced}}}}}]}
When using profiles the merging of the different configurations is done by leiningen as described here. You can take a look at the final project configuration that is handed to cljsbuild by using the pprint
plugin, e.g. lein with-profile dev pprint
.
Yep, that's essentially where I am now. The problem is the amount of duplication required across build config. So my idea / feature request was for cljsbuild
to apply config across all configs if the build id was unspecified. There are other ways to achieve this too, e.g. if the build-id key is a vector, apply it to multiple configs, which has the benefit of more precision than my previous suggestion:
:profiles {:cljs-shared
;; common configuration shared across all builds
{:cljsbuild {:builds {[:build1 :build2]
{:compiler {:foreign-libs [{:file "file1.js" :provides ["Lib1"] :language-in :ecmascript5}
{:file "file2.js" :provides ["Lib2"] :language-in :ecmascript5}
{:file "file3.js" :provides ["Lib3"] :language-in :ecmascript5}]}}}}}
;; dev only configuration for all builds
:dev [:cljs-shared
{:cljsbuild {:builds {[:build1 :build2] {:compiler {:verbose true}}}}}]
;; release only config for all builds
:release [:cljs-shared
{:cljsbuild {:builds {[:build1 :build2]{:compiler {:optimizations :advanced}}}}}]}
:cljsbuild {:builds {:build1 {:source-paths ["src/build1"]
:compiler {:my-project build1.core
:output-to "build1/out.js"
:output-dir "build1/out"
:source-map "build1/out/map.js.map"
:pretty-print true}}
:build2 {:source-paths ["src/build2"]
:compiler {:my-project build2.core
:output-to "build2/out.js"
:output-dir "build2/out"
:source-map "build2/out/map.js.map"
:pretty-print true}}}}
(Thanks for the pprint
plugin tip!)
I would need to think a bit about this, but using an approach that is similar to composing leiningen profiles might be more intuitive, e.g. using a vector instead of a map as the value for a specific build. For example:
:cljsbuild {:builds {:app {:source-paths ["src"]
:compiler {:main app.core
:output-to "out/app.js"
:output-dir "out"
:source-map "out/map.js.map"
:pretty-print true}}
:dev [:app {:compiler {:verbose true}}]
:release [:app {:compiler {:optimization :advanced}}]}}
So for this example, if you would run lein cljsbuild once dev
cljsbuild could merge the config for the :app
build and {:compiler {:verbose true}}
into one build config.
Sounds useful!
I want to make sure it still works with lein profiles, as that's the standard for specifying differences between envs:
build1
and build2
in my example)In other words, to build a release it should look more like:
lein with-profile release compile
And for dev:
lein compile
Not sure the cljsbuild merging would support multiple builds, e.g.:
:profiles {:cljs-common
{:cljsbuild {:builds {:shared-cljs
{:compiler
{:foreign-libs [{:file "file1.js" :provides ["Lib1"] :language-in :ecmascript5}
{:file "file2.js" :provides ["Lib2"] :language-in :ecmascript5}
{:file "file3.js" :provides ["Lib3"] :language-in :ecmascript5}]}}
:build1 [:shared-cljs {:source-paths ["src/build1"]}]
:build2 [:shared-cljs {:source-paths ["src/build2"]}]}}}
:dev
[:cljs-common
;; not sure this makes sense,
;; merging multiple builds into
;; one?
{:cljsbuild {:builds {:dev-build [:build1 :build2 {:compiler {:verbose true}}]}}}]
:release
[:cljs-common
;; same here
{:cljsbuild {:builds {:release-build [:build1 :build2 {:compiler {:optimizations :advanced}}]}}}]}
I guess we can use ... Clojure :)
(def optimizing-compiler
{:compiler {:optimizations :advanced
:elide-asserts true
:pretty-print false}})
(defproject com.capital-match.lending/ui "0"
:description "Capital Match Web application"
:url "https://www.capital-match.com"
:min-lein-version "2.8.1"
:dependencies [
[bidi "2.1.3"]
[cljsjs/create-react-class "15.6.3-0"]
[cljsjs/csv "1.1.1-0"]
[cljsjs/react "16.0.0-0"]
[cljsjs/react-dom "16.0.0-0"]
[com.andrewmcveigh/cljs-time "0.5.2"]
[org.clojure/clojure "1.9.0"]
[org.clojure/clojurescript "1.10.339"]
[org.clojure/core.async "0.4.474"]
[org.omcljs/om "1.0.0-beta4"]
[prismatic/dommy "1.1.0"]
]
:plugins [
[lein-aggravate "0.1.2-SNAPSHOT"]
[lein-cljsbuild "1.1.7"]
]
:profiles {:release
{:cljsbuild
{:builds
{:user ~optimizing-compiler
:admin ~optimizing-compiler
}}}}
;;............
In other words, set this from a profile.
Compilation Profiles describes setting compiler options with profiles, but if your
:cljsbuild
contains more than one build, these are not correctly merged in. Instead, it tricks cljsbuild into thinking config is in the wrong format, and outputs a bogus "fixed" format:Using compilation profiles is only possible if you fully specify every build in every profile, like this project.clj which is super verbose, and unDRY.
Instead, I want to specify settings like:
:optimizations :advanced
in every production build":pretty-print true
in every dev build":foreign-libs [...]
for all builds everywhere"