This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-02-23
Channels
- # announcements (1)
- # babashka (68)
- # babashka-sci-dev (12)
- # beginners (36)
- # biff (22)
- # calva (20)
- # clerk (1)
- # clj-on-windows (7)
- # clojure (27)
- # clojure-conj (8)
- # clojure-denmark (2)
- # clojure-europe (141)
- # clojure-france (1)
- # clojure-italy (4)
- # clojure-nl (1)
- # clojure-uk (2)
- # clojurescript (7)
- # conjure (8)
- # core-async (111)
- # cursive (3)
- # datahike (4)
- # datalevin (18)
- # events (9)
- # gratitude (4)
- # guix (2)
- # helix (3)
- # hyperfiddle (62)
- # introduce-yourself (2)
- # kaocha (4)
- # london-clojurians (3)
- # lsp (7)
- # malli (34)
- # membrane (1)
- # nbb (9)
- # polylith (4)
- # portal (6)
- # reagent (4)
- # releases (2)
- # remote-jobs (4)
- # shadow-cljs (30)
- # sql (2)
- # tools-deps (58)
- # xtdb (9)
Possibly I'm not seeing something obvious here, but I have a namespace with no require
(ns cljs.globals)
(goog-define ENV-NAME "NONE")
and my entry point as defined by :modules {:app {:entries [cljs.core]}}
requires it
(ns cljs.core
(:require
[cljs.globals :refer [ENV-NAME]]
....
yet I'm somehow getting this when I try running shadow
Circular dependency detected: cljs.core -> cljs.globals -> cljs.core
even though globals is not requiring anything..
any ideas?Is it because the name cljs.core is special? Try renaming to mycljs.core
Ah yes! I don't know why I didn't think of that... I have js and cljs files in the project so named the root folder cljs, but that was probably a bad move. Renaming fixes it
just dug to the bottom of a problem, having a lot of cljc files but not using java other than compilation and macros, then adding a :require-macros on a file which imports a lot of other files seems to force the clojure part to activate and the compiler "notices" that my cljc files aren't valid, having js/blah and other clojurescript-only things. It's like there's this kind of bomb in my code waiting for me to make a high level file macro-self-referential
because the errors only come up intermittently between big changes, it means that the "space" I have to search for the problem and fix is big, and also these sort of cljc compilation errors often don't give the file/line that explodes, which overall makes it something that causes pain every now and again
this last one took me doubly long because it seems that requiring a defrecord or defitem by name is valid clojurescript but not valid clojure:
(defrecord MyRecord [a b c])
(:require [my-ns :refer [MyRecord]])
afaict works in cljs but not clj, so this part of the carnage took me ages to find by binary searchhigh level file in the sense of importing lots of other files, because failing under clj is transitive to files-importing so I basically have to search the space of all imported files for the problem
one technique which might be superstition is to put (:require-macros [this-ns :refer [dummy-macro]]) #?(:clj (defmacro dummy-macro [] nil)) into files that I consider suspect to force the underneath-clojure-tree to be checked or at least that file itself
sorry I don't have a specific suggestion and this also might be obvious or stupidity on my part but maybe my pain and ignorance is useful somehow
I strongly recommend split clj/cljs files instead of cljc. https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html
It also kind of seemed like good practice, to keep code minimally seperated from clj in case part of the code was later exposed that way, but a combination of the way that it's lazy in checking the clj half works, rough non-file-specific error messages and some pitfalls I didn't know like the record import incongruity mean that this is maybe the third time it's cost me quite a while effectively doing a slow, semi-blind search through the code for cross-compilation problems
if I'm right that self-requiring any macro forces a check that all recursively required files work under clojure then I can do that at the app entry point in future to catch problems (earlier === in a reduced search-space) but I just thought I'd mention it here since it's maybe the most painful thing I've found in cljs development recently
it doesn't force a check. it loads all the referenced files AS Clojure, which I guess implies a check but it is just regular clojure.
Is there a reason cljs.test
wouldn't be available from the repl connected to a shadow-cljs watch
process for a :react-native
build target? I'm used to being able to run tests for cljs at the repl, but I'm getting TypeError: undefined is not an object (evaluating 'cljs.test.report')
Ah I added cljs.test
to {:devtools {:preloads [cljs.test]}}
and that seems to have fixed it!
I’m seeking help debugging discrepancies between the shadow watch
behaviors I’ve observed on two different OSes (I’m on a Mac M1, and my colleage is on WSL2). Our current hypothesis is that watch
treats symlinks differently on Mac and WSL.
Observations: When I run shadow watch
on my Mac, Shadow runs the build and only re-compiles the CLJS files when I change a file in the src-paths directory. In contrast, when my colleague runs the shadow watch
command on his WSL machine, his build loops indefinitely - it will finish compilation and then recompile (in a never-ending loop).
The endless cycling behavior in WSL is associated with creating soft symlinks during our build process. Normally, the build emits compiled Javascript into a folder called .compiled-stories
and then it symlinks the .compiled-stories
folder to another location inside the src-paths directory. When we stop the build from creating the soft symlink of the .compiled-stories
directory, the WSL machine does not loop indefinitely.
Right now we hypothesize that the shadow watch
(or the code it relies on, or WSL itself) somehow treats the WSL and Mac symlinked folders differently. Specifically, it looks like the https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/util/FileWatcher.java#L34-L46 creates different watchers on Mac vs Linux, so we’re hypothesizing that that could be a factor.
Before we start to explore the differences between FileWatchers, we were looking for a sanity check: is there way we can determine why shadow triggered a recompile and trace the causal chain of events leading to a recompile?
It seems like the MacOs Filewatcher library https://github.com/gmethvin/directory-watcher/issues/30.
And the shadow FileWatcher class seems to use https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/util/FileWatcher.java#L77 in the call to registerAll
- https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitOption.html`FOLLOW_LINKS`https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileVisitOption.html.
Is that line of code telling the file watcher to watch all symbolic links if possible?
I have a Linux machine and home and I just tested this hypothesis on a mac and a Linux machine with a minimal example. I saw that, when running shadow watch, the Mac ignored it when I created new files in the symlinked directory, and the Linux machine did not ignore and tried to rebuild
I’ll write up a minimal reproducible example and file an issue in Shadow
it should generally be avoided to put output files somewhere shadow-cljs "watches", as that just creates a lot of useless noise. output files should never be inputs.
if you create symlinks in any of your :source-paths
that can indeed confuse things a lot
Re: symlinking:
Who: Our custom-rolled build process is creating symlinks
When: The links are created before we run shadow watch. But the links place the folder with the compiled Javascript into the :source-path
.
Here’s an illustrative example of what our directory hierarchy looks like
->myproject
->output-js (where output goes)
->src (being watched)
->foo.cljs
->output-js (soft symlink)
I think the surprising this was that doing this was OK in MacOS; it seems like it only caused strange behaviors in Linux. I believe that is due to discrepancies in how the file watchers for Mac and Linux treat symlinks.
I know that our build system is doing something a bit crazy by symlinking the output directory back into the watch path. But aside from that issue, I suspect that the MacOS file watchers would ignore any directory that is symlinked into the watch path. And i suspect that we would follow symlinks on a Linux machine.