Fork me on GitHub
#boot
<
2016-01-25
>
myles05:01:26

Anyone around to answer a newb question?

seancorfield05:01:56

I can try šŸ˜ø

seancorfield05:01:41

Unless you've already gone @myles ?

myles05:01:55

Hi @seancorfield, thanks, if youā€™re still around, this is my question:

myles05:01:24

Given a dir with src/hello.clj in it, and that file has (ns hello) (defn -main [& args] (println "hello worldā€))

myles06:01:23

is there a boot invocation I can make from the repl that will build namespace in such a way it can be invoked from the command line and print ā€œhello worldā€?

seancorfield06:01:30

Do you have (set-env! :source-paths #{"src"}) to add src to the classpath?

myles06:01:37

honestly, Iā€™m very new to this stuff, but, if I do:

myles06:01:50

how do I run one of those files?

myles06:01:59

(this might be a basic jvm question)

seancorfield06:01:10

I'm just setting up a test environment to make sure I can match yours

seancorfield06:01:43

You don't need to AOT the Clojure code to just run it.

seancorfield06:01:01

You only need to AOT it if you're planning to make a JAR to run separately.

myles06:01:16

how do I run it directly?

seancorfield06:01:28

Well, you asked about the REPL... so ... do you want to run this from the REPL or from the shell?

myles06:01:07

repl ideally

myles06:01:29

but the project Iā€™m planning on working on, will use itā€™s own readline based repl itself

seancorfield06:01:15

Well, you can just say boot -s src repl and you've got a REPL with that src folder on your source paths...

seancorfield06:01:23

then you can (require 'hello)

seancorfield06:01:29

and then (hello/-main)

myles06:01:42

So I guess Iā€™m trying to come up with a workflow where I provide a file that has a main fn, and it gets compiled then evaluated

myles06:01:21

is there a way I can do something like boot -s src run hello ?

myles06:01:39

and let that command take control of stdin/stdout?

seancorfield06:01:48

Well, a more common workflow with Clojure is to work in an editor, connected to a REPL, where you write code and evaluate it in the connected REPL as you go.

seancorfield06:01:18

So you work with a form at a time, instead of a whole program.

myles06:01:45

Iā€™m ok with that, but what if the program itself implements a repl?

seancorfield06:01:48

But you can (require 'hello :reload-all) to fully reload your code from disk and recompile it in the REPL

seancorfield06:01:07

You could always create a build.boot file containing a run task to call your main function... or you could build a full "uber JAR" (containing Clojure and all your dependencies and your program) and just run that via java -jar from the command line.

seancorfield06:01:15

So there are lots of options.

seancorfield06:01:57

If your program implements its own REPL, then when you run it in the Clojure REPL, it'll still work as expected, running and reading/evaluating input until it "ends" and then you'll be back in the Clojure REPL.

seancorfield06:01:53

But that's really why it's easier to develop it from the bottom up via the (Clojure) REPL one function at a time, until you're ready to write and test the top-level loop.

seancorfield06:01:14

Does that help?

seancorfield06:01:24

If you want to see some examples of how to run a -main function or just evaluate some code via the command line, take a look at the discussion in this ticket https://github.com/boot-clj/boot/issues/374

seancorfield06:01:33

What editor are you using?

myles06:01:32

Iā€™m using sublime, with no repl integration

myles06:01:06

for now I just want to get a build-and-run pipeline that I understand simple_smile

myles06:01:14

then Iā€™ll try and optimize it

seancorfield06:01:09

I'd definitely recommend keeping a boot -s src repl open and testing code in that as you write it.

seancorfield06:01:16

So edit code, save. Switch to REPL, require/reload code, invoke the function you're working on. Rinse, repeat.

seancorfield06:01:32

With REPL integration you'll optimize that to edit code, evaluate it, edit code, evaluate it (and saving it occasionally).

seancorfield07:01:30

BTW, @myles in case this helps, if your -main namespace has :gen-class like this

(ns hello
  (:gen-class))
(defn -main [& args]
  (println "hello world"))
then the following command would build you a simple JAR you can run standalone:

seancorfield07:01:53

boot -d org.clojure/clojure -r src pom -p hello -v 0.1.0 aot -n hello uber jar -m hello target

seancorfield07:01:25

Like this:

> java -jar target\project.jar
hello world

ska08:01:29

@myles boot also supports shebang scripts, i.e. scripts that can be invoked just like any other program (at least on Linux). Maybe that is what you're looking for? https://github.com/boot-clj/boot/wiki/Scripts

dave14:01:48

@myles: you could also write a boot task that just runs the main method, something like:

(deftask run-main
  []
  (require 'hello)
  ((resolve 'hello/-main)))

dave14:01:01

passing it arguments is a little trickier, but technically possible

dave14:01:20

you could run it from the command line with boot run-main

myles17:01:09

thanks @dave, Iā€™ve ended up with something like that

richiardiandrea23:01:24

Hello guys, I am working on a boot issue and would like to ask where is *opts* defined...I can't find it

micha23:01:40

@richiardiandrea: the clifn macro isn't hygienic, that binding is created there

richiardiandrea23:01:15

oh, gotcha, so it is not actually a rebindable global?

micha23:01:25

no it's a lexical binding