-
-
Notifications
You must be signed in to change notification settings - Fork 171
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
CLJS output is undeterministic #958
Comments
I can add that the output of compile with whitespace only optimization level also generates undeterministic code... |
Actually, scratch that, it seems that it is the cljs JS generation that is not stable. Running
generates diffs like -return cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped(state__9471__auto__);
+return cljs.core.async.impl.ioc_helpers.run_state_machine_wrapped(state__9316__auto__); |
Deterministic output is not supported. Neither ClojureScript or the Closure Compiler really support it and it would require substantial changes in both to get it. Not something shadow-cljs can address in any way on its own. |
To further clarify: The compiler uses The Closure Compiler does have mechanism to store previously shortened names so they get determistic names back on further compiles. By not using the cache you are also not using that feature. But even with that results are pretty much entirely random. Long story short: Deterministic output is not supported. The only thing that should decide when to use a cache is the inputs (ie. use your |
Thanks for the explanation! Unfortunately I do not decide how Nix does caching, it essentially requires output to be the same if input is the same. However it is good to know that this is expected behavior, then we can work around it :) |
It also creates problems with systems like Terraform, that uses a hash of the output to know if it is supposed to replace an uploaded archive or not. |
Maybe I misunderstand something but how does Nix use any cache if it has to compile to know if it can use a cache? That kinda sounds like the opposite of any other caching mechanism I ever heard of or used? I mean isn't the point of a cache to skip the expensive part (ie. the compilation)? |
Actually, deterministic output is not a strict requirement for getting caching (unless using the new CAS derivations). CAS derivations enables deduplication, early cutoff in build systems, and unprivileged closure copying so it is more a nice-to-have. We will work around the Terraform issue in some other way. |
Sorry, I don't know what any of that means. All caching shadow-cljs does is based on fairly strict checking of the inputs. If they are all equal no compilation is done assuming the shadow-cljs also offers a couple options for "fingerprinting" outputs but now clue how this plays into Terraform since I have not used that either. You can sort of create a shortcut and skip a CLJS build if none of your "inputs" changes (eg. build config, package-lock.json, shadow-cljs.edn, *.cljs). Unless of course you are using side-effecting macros then all bets are off since they can do anything and there is no way for shadow-cljs to keep track of it. |
Thanks a lot for all the information! This is not a huge issue and there is a lot of ways we can work around it but it is a good point about the fingerprinting options! Thanks again! |
Hi,
When building with any optimization from the closure compiler (simple or advanced) and turning off cache, the output is constantly different.
results in diffs like this
where we can see that the local variables
l
andm
are switched at the end of the line.This is a problem for us since we use Nix to build this output and want the same input to produce identical output to make it properly cacheable.
When turning off optimizations, the output is deterministic.
Saw this as well. Does shadow-cljs need to send a seed somewhere to the closure compiler?
The text was updated successfully, but these errors were encountered: