Fork me on GitHub
#boot
<
2016-09-25
>
adamkowalski01:09:15

how long does it normally take from the time you launch boot to the time you have a cljs repl in the browser?

adamkowalski01:09:25

mine took like 45seconds so idk if that is normal

martinklepsch08:09:30

@adamkowalski: for initial launch that seems reasonable. Also depends on hardware etc

xla10:09:01

Hey everyone - I'm relatively new to boot but really liking it so far. So I thought I'd start to write my own task (it's going to be open source in case someone else finds it useful) but I'm hitting a problem that I can't explain at all at the moment: None of the changes I made today is picked up by boot; instead it looks like an older version of my task gets executed. I tried to reduce the problem as much as possible and ended up with just a build.boot file in an otherwise empty folder. As you can see below the only thing I do is requiring the original task namespace but I'm not adding any dependencies:

(require '[schranz.boot-resource-filter :refer [filter-resources]])
I would expect an error that it can't find the namespace but instead this lets me execute the task; but not the current version Where is it finding that namespace? Is Boot doing some caching of tasks that I'm not aware of? (I haven't been able to reproduce it with any other task so far) Things I've tried so far: • I deleted the target folder and ~/.boot/cache folder just in case • removed the task artifact from my local maven repository (which I don't think mattered since I didn't specify any dependencies) • updated to the latest boot 2.7.0-rc1 (but I'm back on 2.6.0 now) • getting slightly desperate I even deleted the original project folder at some point • I also renamed the namespace at some point (just added a character at the end) which allowed me to see my latest changes. • boot show -c is not showing anything that is related to my task except for a few folders in ~/.boot/cache/tmp but all of them are empty I'm probably missing something really silly and obvious but I can't see it just yet - if anyone has an idea what's going on that would be greatly appreciated 🙂

martinklepsch10:09:36

@xla: is that require statement the only thing in your build.boot?

xla10:09:57

Yes it is

martinklepsch10:09:05

I don't have any explanation unfortunately, have you tried reproducing in a new directory?

martinklepsch10:09:53

It doesn't sound like the kind of issue I could reproduce on my machine but I'm happy to try if you put it on GitHub or something

xla10:09:17

I'm completely baffled by it - and yes I tried it in a new directory. Unfortunately I don't have my company laptop here or I would have tried on that machine (I'm sure it'll fail) I've already pushed my work in progress to my github repository: https://github.com/danielschranz/boot-resource-filter (btw I also updated the doc string yesterday via a force push to see if boot is downloading it somehow from there, but that's not the case either) Thanks for having a look at it!

martinklepsch10:09:57

@xla: now there are more files etc in there, what are you observing and how does it differ from what you expect?

xla10:09:35

When I make changes to the filter-resources task in the boot-resource-filter namespace (a simple example would be changing the doc string) and running boot in the terminal again I expect to see the new docstring - but it doesn't change.

martinklepsch10:09:42

Cool, I'll check it out in 20min or so

xla10:09:05

Thanks, no rush 🙂

martinklepsch11:09:16

@xla after commenting out the (*usage*) line (so that the task returns a fileset) it seems to work fine for me

martinklepsch11:09:46

@xla also you might want to try Clojure 1.8 instead of 1.7

martinklepsch11:09:55

I changed the task docstring and ran boot filter-resources -h and the printed docstring is updated

xla11:09:23

Weird, I commented out that line but it still behaves the same for me. - Actually this is the expected behaviour so it must be something that I did on my laptop. Btw I took that pattern to return *usage* from an example online - it does return a fileset if the parameter checks pass - which I confirmed by adding a string to the processed files (but I'll check whether that is a correct pattern) Seems like I have to do more digging here - but thanks @martinklepsch for taking the time to confirm it's not something boot does...

urbanslug11:09:46

An alternative to installing boot on ox that is not via brew because brew’s version of boot is old.

martinklepsch11:09:16

@urbanslug boot's version on homebrew is up to date

martinklepsch11:09:30

The binary is upwards compatible

urbanslug11:09:34

It’s 2.5.2

martinklepsch11:09:33

@urbanslug when you specify a higher version via BOOT_VERSION it will use the given version

martinklepsch11:09:01

the version of the binary is not coupled to the version of Boot itself: https://github.com/boot-clj/boot-bin/releases

urbanslug11:09:26

Then the error I’m getting has nothing to do with boot version. Thanks @martinklepsch

martinklepsch11:09:52

@urbanslug make sure you always pin the Boot version via boot.properties

xla12:09:44

Ha @martinklepsch - I think I found it! bananadance Following your suggestion I updated the Clojure version in boot.properties to 1.8.0 and got the new docstring - went back to 1.7.0 I saw the older doc string again... tested version 1.6 and also got the new docstring. So I deleted Clojure from my local maven repo and now I get the correct doc string with version 1.7.0 as well. I think I also know how it happened: when I first experimented with installing the task locally I didn't get the config right and I remember it saying it installed the Clojure artifact into the repo (I didn't encounter any problems so I didn't think much about it, but apparently it installed my task there)

xla12:09:06

Thanks again for your help, hope I can return the favour at some point 🙂

pesterhazy17:09:35

Has anyone attempted a simplified terminal based boot-cljs-repl? What I'm imagining is a sort of browser based planck. Without any other configuration, you can do boot -d com.andrewmcveigh/cljs-time browser-repl and it greets you with a working command-line repl.

pesterhazy18:09:40

In the background it could automaticaly open a page in chrome or whatever, and it'd serve a default index.html containing only script tag

pesterhazy18:09:31

I think that'd be very useful for trying out clojurescript without diving into a boot setup etc.

kurt-yagram18:09:39

I have a project in which the dependencies depend on the task executed (production needs another dependency). So, for example, for testing, I can add my own deftask in which I set the env, in which I only execute the boot-check test task:

(deftask test-project "" []
  (set-env! :dependencies #(conj % ...))
  (test))
However, in this case, if there are task options, I also must implement all these options to pass them to (test). I know there's a task-options I possibly can know, but can it be used to set the environment? Doing:
(task-options!
 test {:source-paths #{"src/clj" "test/clj"}
       :dependencies #(conj % ...) }
results in:
test: unknown option(s): :source-paths, :dependencies
How can I set dependencies in an task defined in another dependency (`boot-check`)?

micha18:09:19

@xla can you try adding the --no-profile option to boot?

micha18:09:46

you might have code in your boot.profile file?

keithsparkjoy18:09:36

Pretty new to Clojure and just learning boot... I'm trying to get a repl going on a hello world project. At the root of the project I have build.boot with (set-env! :source-paths #{"src"}). When I run a boot repl and print the classpath, I see file:/usr/local/Cellar/boot-clj/2.5.2/bin/boot and file:/Users/keith/.boot/cache/bin/2.6.0/boot.jar only.

keithsparkjoy18:09:00

I must be doing something really dumb because I expected my source path to be in there as well 🙂

micha18:09:37

@keithsparkjoy how are you printing the classpath?

keithsparkjoy18:09:47

(println (clojure.string/join "\n" (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader)))))

micha18:09:26

boot doesn't mess with the system classloader

micha18:09:42

because that would defeat any later attempts at classloader isolation

micha18:09:30

the TCCL is the one you want, probably

keithsparkjoy18:09:07

I think I need to learn the basics about how boot deals with classloaders and paths and such - is there a good resource you can suggest?

micha18:09:10

there are functions in the boot.pod namespace that expose various classloader functionality in a handy way

micha18:09:38

are you already comfortable with classloaders on the JVM?

keithsparkjoy18:09:14

I think I understand the basics yea

micha18:09:56

ok cool, so one of the main affordances of boot is the "pod" framework

micha18:09:07

pods are isolated clojure runtimes

micha18:09:32

you can add dependencies (jars), directories, etc to a pod

micha18:09:00

and those remain isolated in that pod, they are not on the classpath in the context that created the pod

micha18:09:16

then you can evaluate expressions in the pod to do work

micha18:09:20

sort of like a proxy

micha18:09:48

it's customary for classlaoder to resolve classes from the parent down

micha18:09:25

meaning if classloade A is the parent of classloader B, B will delegate to A

micha18:09:33

if A can't load the class then B tries to

micha18:09:55

the system classloader is at the very top, it doesn't have a parent

micha18:09:36

in boot, to make it possible to achieve isolation, we ensure that the clojure runtime is not loaded into an classloader that could ever be the parent of another pod

micha18:09:53

beacuse once that happens you can no longer isolate

micha18:09:14

so the entry point in boot is a java program

keithsparkjoy18:09:27

I see - so I was printing the classpath of that.

micha18:09:31

the java program creates classloaders for clojure pods

keithsparkjoy18:09:19

Makes sense. Ultimately what I’m trying to figure out here is why boot repl is not finding my source files, even though I’ve set up the path to them in my build.boot file.

kurt-yagram18:09:21

... is it possible to set an environment (`set-env`) of a task defined by a dependency? (For example, can I set the environment of the test task of tolitius/boot-check)?

micha18:09:56

@keithsparkjoy you can try (boot.pod/get-classpath)

keithsparkjoy18:09:33

yep, @micha that gives me a nice long list

micha18:09:45

you can also try ( "foo/bar.clj"), assuming you have a src/foo/bar.clj file in your project

micha18:09:59

if that returns a non-nil URL then it's on the classpath

keithsparkjoy18:09:23

I don’t see my project directory anywhere on the classpath

keithsparkjoy18:09:31

that I printed via (boot.pod/get-classpath)

micha18:09:37

you won't, boot doesn't touch your project files

micha18:09:05

the reason for this is to allow boot tasks to modify anything

micha18:09:19

without needing to know or care if it's a file you're editing in your editor

micha18:09:40

so when you set :source-paths that tells boot where your source files are

micha18:09:44

for your project

micha18:09:57

and boot copies them into a temporary directory it owns

micha18:09:59

and manages

keithsparkjoy18:09:10

(lights coming on)

micha18:09:24

this way it doesn't need to have all kinds of special cases for what to do if it needs to delete a file from your project

micha18:09:34

because it doesn't ever touch your real project files

micha18:09:39

only copies that it owns

micha18:09:09

also this make the whole immutable fileset stuff straightforward to implement and understand

keithsparkjoy18:09:16

ahh okay so I’m seeing some stuff I recognize now that I’m looking at the boot/cache file paths in that classpath

keithsparkjoy18:09:24

some paths that are clearly from my project

micha18:09:39

yeah those are kept in sync via native FSEvent watch services

micha18:09:03

there are a few temp dirs you'll see there

micha18:09:24

one is for files on the classpath that have been copied from your project dirs

micha18:09:38

one is for new files that are created and added to the classpath by tasks

micha18:09:54

it's useful to separate those for various performance optimizations

micha18:09:33

you shouldn't molest files in those direcotries though

micha18:09:43

boot assumes that only it will mess around in there

micha18:09:50

again for performance optimizations

micha18:09:09

the files you see in there are in fact mostly hard links

micha18:09:44

an interesting consequence of this is that you can remove directories from the classpath

micha18:09:58

not really, but from the user's perspective that's the effect

micha18:09:13

because boot has the same set of directories added to the classloader

micha18:09:16

the temp dirs

micha18:09:36

it just copies files into there from different places depending on your source-paths and resource-paths settings

micha18:09:46

so if you remove a path from :source-paths, for instance

micha18:09:55

those files will be removed from the temp dir

micha18:09:01

but the temp dir is still on the classpath

micha18:09:08

if that makes any sense 😄

keithsparkjoy18:09:21

So I guess what I really need at this point

keithsparkjoy18:09:57

Is to know how to get an interactive development workflow going for a simple project with boot

micha18:09:11

what kind of project is it?

keithsparkjoy18:09:44

An app in this case (hello world).

keithsparkjoy18:09:51

I’ve had success with a hoplon app

micha18:09:56

a clojure program, where you make an uberjar?

micha18:09:06

sure that's a good one

micha18:09:33

so you have a directory for your project already, with a main namespace?

micha18:09:46

you can get rid of the build.boot file if you want

micha18:09:52

and we can just do it in the repl

keithsparkjoy19:09:32

Project is called “wf” for workflow - just trying to figure this out.

keithsparkjoy19:09:38

I have a subdir src

keithsparkjoy19:09:44

with a couple clojure source files

keithsparkjoy19:09:50

user.clj and core.clj

keithsparkjoy19:09:01

with a simple def in each one.

keithsparkjoy19:09:34

I was having trouble loading these namespaces (use ‘wf.core) for example

keithsparkjoy19:09:38

getting file not found errors

keithsparkjoy19:09:47

I see my problem. I need a wf dir under the src dir.

keithsparkjoy19:09:03

(dopeslap self)

micha19:09:50

easy to fix

micha19:09:25

so after you create the wf dir and moev the sources in there, you can do (require 'wf.core)

keithsparkjoy19:09:25

working better already 🙂

micha19:09:46

ok so at this point you can make an uberjar to test it out

micha19:09:10

boot.user=> (boot (aot :namespace '#{wf.core}) (uber) (jar :main 'wf.core) (target))

micha19:09:35

you should have a file target/project.jar

micha19:09:51

and java -jar target/project.jar should run the program

micha19:09:44

also when you're at the repl you can see info about tasks with clojure.repl/doc

micha19:09:56

boot.user=> (doc aot)

micha19:09:39

actually there is a bug

micha19:09:01

(set-env! :dependencies '[[org.clojure/clojure "1.8.0"]])

micha19:09:22

you need to include clojure.jar in the uberjar fo course

keithsparkjoy19:09:39

Okay going to take this new knowledge and hack a bit. Thanks for the help, @micha!

micha19:09:52

good luck 🙂

manenko19:09:58

Hello everyone. Let's say I want a boot task that downloads a file from a url. This task accepts url and taget-file. Should this task add downloaded file to a fileset or it has to be done by a callee (the code that invokes this task)? What if I save a file under random name? How do I provide a path to this file to a callee?

micha19:09:04

@manenko you want to add it to the fileset

micha19:09:17

what do you mean by "callee" though?

manenko19:09:45

@micha A code that invokes this task

manenko19:09:10

oh thanks, I will take a look

micha19:09:11

the code that invokes this task would be the call_er_ no?

micha19:09:29

but usually you would have the caller specify where it wants the file to end up

manenko19:09:53

yes, it would be the caller 🙂 > but usually you would have the caller specify where it wants the file to end up Thanks