-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrong compilation order (uberjar, check) (WAS: with linux x86-64) #2508
Comments
Can you provide a repro case outside docker? |
Only by setting the order manually to the same as compiled inside docker. lein with-profile uberjar/fail uberjar |
I see; I misread this as the order of the tasks was different, not the order of the namespaces. This is probably due to implementation details of the underlying filesystem leaking thru, so we ought to explicitly sort them before compilation. Happy to take a patch for this. |
So if I'm understanding this issue correctly, the compilation order for namespaces is not identical across platforms? Looking at the compile.clj source, it doesn't look like there is any strict ordering enforced by stale-namespaces. If that is the case, how does this error not occur more often by random chance? Adding a simple (sort ...) to the compilable-namespaces function still fails. Do we need to build a directed dependency graph of namespaces to correctly order compilation here? |
@LoganGirard, I believe you're correct. There are a couple of things going on here:
Thus if you first compile a namespace that uses Well, maybe Clojure could be changed so that As for why this does not happen more often: probably not that many projects do the point 4? I don't know if the uberjar would actually work if the compilation would succeed. |
Thanks for the detailed explanation. Would CLJ-1814 help here? Still, don't think that issue is going to be resolved & deployed any time soon... |
This failure does happen a lot! People come by IRC with broken protocols due to this problem pretty frequently, or at least they used to when IRC was more active. It's a big part of why I don't use protocols; they cause really weird, difficult-to-debug errors where two things look identical but behave differently depending on load order. Just a huge pain in the neck.
There is one fix that will work for the uberjar case (though you'll still run into random bugs in the repl) is to avoid using |
So it sounds like this issue is ideally better supported by waiting on Clojure to support it? Any action for us at the moment, barring contributing to the clojure source? |
Depends on which problem you're talking about.
The problem of "order of namespaces depends on which filesystem you're
using" can be fixed in Leiningen easily by adding a sort, and I'd be
happy to take a patch for that.
The problem of recompiling causing protocols to fail to dispatch can't
be solved in Leiningen and probably can't be solved in Clojure either
without sacrificing the fast-dispatch features that protocols were
designed to facilitate.
|
Sounds like this could explain some seemingly indeterministic behavior we've seen when using aot and protocols... now that this change has been merged do you anticipate another release soon? I'm eager to try it out. |
Given that there has been basically only one other small change on master since the last release and that this is very easy to work around, I don't foresee having another release soon.
|
I would like to reopen this. The compilation-order is now consistent in 2.9.1, which means it fails on all environments. The compilation should be ordered by the dependencies. |
It only recently occurred to me that the I'm glad you pointed out this "only provide a main entry point solution" and I strongly feel that that should be the way nearly anyone does If you don't have a main entry point that works, that may be questionable as to why since it is a typically an "application" you AOT, not a library. Also, doing Actually, in a typical ClojureScript build, you do typically just provide a "main entry point" and compilation happens in one pass from there. I see no reason why that wouldn't be the norm for Clojure.
Doing a |
Thing is that many people use With the current setting, building an uberjar succeeds by default, but will fail if the user adds a namespace using some protocols and which happens to be named so that it is referenced before the namespaces defining those protocols. "Don't use protocols of type X in a namespace that starts with alphabet < M" kinda problem. |
Sorry, but I don't think this is going to happen within Leiningen. It's easy to order the compilation by dependencies by specifying the entry points; then Clojure will just do the right thing for you. Using |
Locally everything works fine, but when
lein uberjar
is run with default Clojure Docker container, the compilation order is different and the compilation fails as the Protocolssatisfy?
doesn't match to values.I believe the compilation order should be the same (working one) on all platforms?
lein uberjar
Here's a sample project: https://github.com/ikitommi/uberjar-problem, with guides on how to reproduce this.
Original problem: metosin/muuntaja#90
lein check
Saw the same with
lein check
: works locally ok, but not on travis:The text was updated successfully, but these errors were encountered: