This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-08-03
Channels
- # admin-announcements (2)
- # arachne (1)
- # architecture (6)
- # boot (316)
- # cider (7)
- # cljsrn (7)
- # clojure (169)
- # clojure-argentina (3)
- # clojure-belgium (1)
- # clojure-canada (4)
- # clojure-india (1)
- # clojure-russia (39)
- # clojure-spec (27)
- # clojure-uk (55)
- # clojurescript (213)
- # css (1)
- # cursive (20)
- # datavis (2)
- # datomic (52)
- # devcards (3)
- # dirac (78)
- # emacs (20)
- # events (1)
- # funcool (3)
- # hoplon (15)
- # jobs-rus (2)
- # om (57)
- # onyx (82)
- # overtone (1)
- # re-frame (10)
- # reagent (1)
- # ring-swagger (46)
- # spacemacs (7)
- # specter (31)
- # spirituality-ethics (1)
- # sql (43)
- # test-check (1)
- # testing (4)
- # untangled (30)
is I can get this done in leiningen with zero problems, but I really want to use boot as it appears similar to gulpjs
might just have to defer boot to clojurescript alone if I can't figure this out soon
and when you're more familiar with clojure and all that you can probably easily debug your cider configuration
without a good grasp of the underlying clojure stuff, it will be hard to maintain a complex tower of tooling
leiningen project.clj is a static map, so you just need to learn the names of different keys etc
I don't have a strong motivation to use boot besides the point of "it will be a better tool once I use both clojure/clojurescript"
@micha: it does cause a problem; windows doesn't recognize "/C:/file.txt" as being a valid path, it'd need to be "C:\file.txt", altho most of the win32 API will also accept "C:/file.txt"
(map #(.getPath (URL. %))) returns the path component of a URL, I believe this would be more robust: (map #(.getPath (.toFile (Paths/get (.toURI (URL. %))))))
if I'm not mistaken, this would convert the URL to a filesystem path in a platform-independent way
a couple keys under (core/get-env) also contains values where there's a leading forward slash before paths
obviously doesn't cause issues internally, but as soon as a value is made available to the other windows programs, issues arise
because some tasks want to make correlation between paths on the filesystem and URLs for like HTTP for example
on the other hand, everything that trickles down to a value being made available through a System property should be in the format of the current system, no?
in fact the next line (partial string/join (System/getProperty "path.separator")) joins it based on the system's path separator
so in set-fake-class-path!
, I believe both boot.class.path
and fake.class.path
would benefit from converting the the URL to a path using Paths.get
I'm currently trying to convert one of our lein/figwheel project to boot/boot-reload, I got it to work until this issue caused vim-fireplace to not be able to display the result of a REPL eval
went through vim-fireplace for a couple hours until I realized boot was generating the wrong path format for windows in fake.class.path
is anyone using :preloads
with boot-cljs
? any pointers on where should I use that option? in the task or in the .edn?
Just installed boot (with brew install) on machine without it, running into this problem:
any ideas?
@richhickey: 2 things: does the error still happen if you run boot -B
?
2nd: what’s the output of boot -b
?
does not happen with boot -B
so the problem is somewhere in your build.boot
or its dependencies
(or maybe profile.boot
)
it’s right there
[depsfile (io/file "deps.edn")]
but no require for
ah, I’m in a project dir with boot stuff
that was it, thanks @anmonteiro !
yeah, it’s why boot -B
works, it doesn’t load the boot script
np, happy to help
-b good to know
boot -h
lists all this stuff
boot -h wasn’t working either
oh, of course it wasn’t, silly me
@richhickey: do you still want to be able to use a development version of Clojure via BOOT_CLOJURE_VERSION
, or do pods accomplish everything you need there?
Does anyone know how to use a standalone .jar file as a dependency in build.boot?
@marc-schwartz: I have not, but just an idea; maybe :resource-paths #{"src" "lib/my.jar"}
?
@timothypratley: thanks! I will try that and if not, perhaps a local mvn repo
Often recommended is installing the jar in your m2, or hosting a repo for a company
something like mvn install:install-file -Dfile=<path-to-file>
@marc-schwartz: local mvn is good, there's also boot.pod/add-classpath
@marc-schwartz: example of alan's suggestion: (boot.pod/add-classpath "lib/my.jar")
Thanks, everyone! Going with local mvn repo option...
Is it possible to have task options be recursively merged? For example, I set up some default compiler options using like this:
(task-options! cljs {:compiler-options {:language-in :ecmascript5}})
I then have a task which then adds new :compiler-options
:
(deftask do-stuff
[]
(comp
;; do stuff before
(cljs :compiler-options {:closure-defines {'myns.core "foo"}})
;; do stuff after
))
:compiler-options
is replaced with the map I defined in the task. Instead, I would like to recursively merge :compiler-options
. Is this possible?Oh I see. Rather than setting the cljs
task options inline I should use task-options!
inside my task.
using task-options! like that isn't a good solution becuase you're mutating global state
so what you want to do is consume the existing .cljs.edn file, add options to it, then write your new version of it and add it to the fileset
using task-options! in the way you're describing will be complicated because it's not scoped to the pipeline
So then is this the preferred way to set up dev and prod build tasks: Have your .cljs.edn file(s) contain the default options for both dev and prod build tasks. If you need to set specific options for either the dev or prod task you need to read the .cljs.edn file and merge it with the options you want to set.
Okay that makes sense for that specific case. What about in the general case where you may want to inline merge task options?
if your task mutates global state in the pipline, then consider something like the watch task
one of the things that makes tasks composable is the guarantee that every time the task is called it's called with a clean environment
and that isn't reversible, so the tasks that precede it in the pipeline would see the modifications it made to the cljs task
with the .cljs.edn method though, none of the tasks need to know anything about each other
So the key here is the rewinding -- task options are not passed around like the fileset is. If they were then you would get the rewind functionality. Correct?
they're to pass information to the tasks about things that normally can't change over time
so basically for stuff that changes during the pipeline you can use the fileset to transmit info
Just to get some clarification.. What are you thinking I mean when I say inline merge task options?
Were you thinking this?
(deftask do-stuff
[]
(task-options! cljs {})
(comp
;; do stuff before
(cljs :compiler-options {:closure-defines {'myns.core "foo"}})
;; do stuff after
))
or more precisely in the handler function the task returns that becomes part of the pipline
if you do your global mutation where you have the task-options! in your example tat's better
so if you're doing (boot (do-stuff))
in the repl you will have artifacts from the first time you do it that persist to the second time
Right. What I had originally had wanted was to do something like this:
(deftask do-stuff
[]
(comp
;; do stuff before
(cljs :compiler-options #(merge % {:closure-defines {'myns.core "foo"}}))
;; do stuff after
))
Actually my specific use case is I want the {{:compiler-options {:language-in :ecmascript5}}
set for all cljs
tasks and I want to merge that with my :compiler-options
in my task.
ok so what you want at the end of the day is to compile all your stuff as :ecmascript5?
To do something like this:
(task-options! cljs {:compiler-options {:language-in :ecmascript5}})
(deftask do-stuff
[]
(comp
;; do stuff before
(cljs :compiler-options #(merge % {:verbose true}))
;; do stuff after
))
In that example I want {:compiler-options {:language-in :ecmascript5}}
set as default for all cljs
tasks. Then in the do-stuff
task I want {:compiler-options {:verbose true}}
merged with the defaults for cljs
.
the .cljs.edn way you control the order in which you compose your tasks in the pipeline
and it's not mutating anything global, so you don't need to worry about how the merge will affect things when they're applied over themselves
you can use the :id method of selecting which .cljs.edn file to operate on, like the reload and cljs-repl tasks do
(deftask doit
[]
(comp
(task1)
(cljs-compiler-options :update #(update-in % [:closure-defines] into ['foo.bar "asdf"]))
(taskN)
(cljs)))
Just to make sure I understand.. In the general case you are suggesting that the way you update task settings is by creating a custom file (e.g. .cljs.edn
) that is understood by your task, do-stuff
. If task1
or taskN
wants to modify the settings for do-stuff
before the do-stuff
task is ran they would need to update the task specific file.
And this method is preferred because then you do not need to worry about the ordering of how certain tasks update/merge task settings
But then isn't allowing tasks to specify options inline (e.g. (task1 :some-option true)
) going against that method? Because then you need to think about how your task-specific file is going to get merged with the options specified inline on the task.
it's not like that in the cljs task because the whole .cljs.edn thing is different from what people expect
like the install task looks for a pom.xml in the jar file it's installing into local maven
but if you specify options to the task then those override the pom and it doesn't look for it
you only run into the kinds of problems you're seeing when there is no real model for what we're doing
the compiler options are tricky because they're coupled to each other in ways that are not easy to understand
Agreed. I believe we are on the same page now -- I just happened to pick an edge case for my leading example which caused a tangent, but very insightful, discussion. The conclusion I have drawn is that tasks will generally not have a complex map for specifying options. If the task does need a map to specify options it should be set in a task-specific file that can be overridden by task-options. If the task-specific file is overridden by task options, it should be completely overridden so you don't introduce any additional complexity of merging.
so like in your case maybe just do your :compiler-options configs in .cljs.edn files and not in the task options
It seems like there could be a general task created to do this sort of thing. You specify your file and operation and the task would do the rest
but like the way clojure.core/update-in
unrolls the sexps into a sort of concatenative expression
i was thinking maybe specter has some unique possibilities for making nested data updates concatenative like that
Yeah totally. If someone want's to use it they could just require
it in their build.boot and use it as they please. Not worth introducing a new dependency
although it wouldn't necessarily introduce a dependency, because it would be loaded in the worker pod
I think if you get to a case where you want specter to modify your task-specific options file then you probably need to rethink your task
Clojure's default navigators should be more than sufficient. And, as you said, it is definitely the exception when a task needs complex config options.
Anyway, I'll be writing a task like the one discussed earlier which can certainly be used as a template/starting-place for a future built-in task.
BTW, I was going to ask earlier but didn't want to distract from the conversation, you said you use a macro to set :closure-defines
. What is the use-case for that? Right now I am just setting them using :compiler-options
on the cljs
task in my prod build task (obviously that isn't preferred after our discussion).
the main thing i use it for is to bring configuration settings that i make at compile time into my cljs application
i have a logging macro that does a bunch of stuff but doesn't emit anything unless the log level is set in the environment or system properties when you compile
imo it's superior to the compiler options, because now it's in a place where you're actually computing