leiningen

N.B. The maintainers are on #leiningen on Libera chat IRC. Go there for direct support/bug reports.
anthony-galea 2019-02-20T15:34:28.000400Z

Just came across an issue with the latest lein release v2.9.0:

─$ git clone <https://github.com/quil/quil.git>

# with lein 2.9.0
─$ lein do clean, compile
Compiling quil.applet
java.lang.ClassNotFoundException: quil.helpers.AppletListener, compiling:(quil/applet.clj:256:22)
Exception in thread "main" java.lang.ClassNotFoundException: quil.helpers.AppletListener, compiling:(quil/applet.clj:256:22)
...
Caused by: java.lang.ClassNotFoundException: quil.helpers.AppletListener

# after downgrading to lein 2.8.3:
─$ lein do clean, compile
Compiling quil.helpers.applet-listener
Compiling quil.applet

─$ java -version
java version "1.8.0_202"
Has anyone seen anything similar?

NoahTheDuke 2019-02-20T15:57:03.000700Z

Is there a race condition in the compilation?

alexmiller 2019-02-20T16:11:23.000900Z

are you using :aot :all ?

alexmiller 2019-02-20T16:12:25.001400Z

looks like, no (there was a possible change in compilation order with that in lein 2.9.0)

anthony-galea 2019-02-20T16:13:26.002200Z

?

alexmiller 2019-02-20T16:13:36.002400Z

oh wait, you are seeing a difference in order there

alexmiller 2019-02-20T16:13:57.002900Z

project.clj has :aot [quil.helpers.applet-listener quil.applet] - but you are seeing quil.applet compiled first

alexmiller 2019-02-20T16:14:42.003600Z

that sort was supposed to only occur for :aot :all based on what I was told. if not, then I'd say that's a regression and you should file a bug

anthony-galea 2019-02-20T16:17:10.004Z

ok will do, thanks @alexmiller

2019-02-20T16:17:55.004300Z

Yeah, looks like it sorts all forms of :aot

2019-02-20T16:18:02.004500Z

from that commit above.

2019-02-20T16:19:15.005400Z

However, isn’t it not really a good impl in quil.applet to not require the namespace that the class is defined in?

2019-02-20T16:19:41.006Z

Not saying lein should resort your list, just thinking, that’d break with :aot :all if you chose to go that route instead later

2019-02-20T16:20:39.006800Z

I mean, quil.applet refers to the class quil.helpers.AppletListener, without adding a :require for quil.helpers.applet-listener I tend to consider that a faulty ns

alexmiller 2019-02-20T16:22:49.007Z

it's loading a gen-class though?

alexmiller 2019-02-20T16:23:56.007500Z

if I'm reading it right, AppletListener is a genclass. aot is being used to compile it. applet is just using it purely as a java class.

alexmiller 2019-02-20T16:24:25.007900Z

that all seems sane to me

2019-02-20T16:28:32.008200Z

@alexmiller It’s loading a gen-class’ed class

2019-02-20T16:28:48.008600Z

but if you did AOT :all and is “started” with the ns quil.applet, it’d fail I think

2019-02-20T16:29:05.009100Z

due to the missing :require so it wouldn’t know to first compile that ns

2019-02-20T16:43:36.009800Z

Well, I did learn now that lein :aot :all calls repeated compile on each ns. Not a big fan of that due to duplicated loading concerns. Yikes

2019-02-20T16:43:50.010400Z

I wish it would just take a “single entry point” ns that transitively requires all else - so only one compile goes

alexmiller 2019-02-20T16:43:52.010500Z

well, yes. that's why you sometimes need to order your aot calls

2019-02-20T16:44:19.011Z

but seems like you wouldn’t have the ordering problem if you have a single top-level ns that causes the transitive (one time load) of everything it depends on

2019-02-20T16:44:38.011600Z

but thanks for the reddit pointer. all stuff I was unaware of and good to know about now.

2019-02-20T16:45:16.012300Z

I still think if I use a gen-class class from another ns, I always make taht explicit with a (:require [quil.helpers.applet-listener]) <- the ns that defines the gen-class

alexmiller 2019-02-20T16:46:15.012700Z

I don't think there is any reason to in this case

anthony-galea 2019-02-20T16:58:38.014700Z

@mikerod fyi just tried :aot :all with lein 2.8.3. Without the require I get a ClassNotFoundException for AppletListener and with the require I don’t as you expected. Order of compilation:

...
Compiling quil.applet
...
Compiling quil.helpers.applet-listener
...

2019-02-20T17:04:30.017800Z

@anthony-galea @alexmiller Yeah, the general rule I’m getting at is that if a ns requires another ns to be pre-loaded - for any reason, including side effects like gen-class - then it should explicitly ensure that other ns is loaded - typically via adding it to :require (or something that loads appropriately). So this quil ns, assumes the gen-class class exists, but never ensures the ns that creates it is loaded. That violates my “general rule” here. I think it’s a brittle pattern when you don’t make your direct dependencies explicitly called out. ie. I’d expect to be able to do (compile 'quil.applet) and have success with no prior compile calls to ns’s it depends on. All that aside though, I didn’t realize that (1) :aot :all in lein calls compile multiple times for possibly inter-related ns’s and (2) now there is this sorting happening both for all and what looks like the explicit ns vector way.

alexmiller 2019-02-20T17:10:06.018200Z

That’s how aot works in all tools

😱 1
alexmiller 2019-02-20T17:10:15.018400Z

1 that is