Closed chancerussell closed 2 years ago
@chancerussell does the following watcher work on Big Sur?
Actually forget that.
It would be nice if we could fall back on a simple java based watcher when things like this happen.
Yeah, according to their issues they’re bit by the same exact problem.
I found a temporary workaround by falling back to polling, so Figwheel can at least run in a (slightly) degraded fashion. As far as I can tell, the major cost is degraded battery / higher power consumption.
The hawk lib checks to see if it's working on macOS, and uses a multimethod to set up a Barbary watcher. Thus, I can just swap in that multimethod before I start up figwheel. In my user.clj
I've added:
(ns user
(:require [figwheel.main.api :as fig]))
;; Patch hawk for macOS Big Sur
;; hawk can't find the carbon lib any more, so the underlying barbary watcher
;; doesn't work for getting OS-level file change events. We have to fall back to
;; polling by monkey-patching the barbary-vending multimethod for now.
(import [hawk SensitivityWatchEventModifier])
(require '[hawk.watcher])
(defmethod hawk.watcher/new-watcher :barbary [_]
(prn "WARN - falling back to filesystem polling on macOS")
(let [sensitivity SensitivityWatchEventModifier/HIGH]
(hawk.PollingWatchService. sensitivity)))
(fig/start {:mode :serve} "dev")
It doesn't have to be in user.clj
, but it does have to run before Figwheel gets going. I start the Figwheel process manually, so I haven't tried it with clj -m figwheel.main
, but I would hope this would load and patch OK in that circumstance too.
Of course, now that I've taken enough time to look through the code in preparing a PR, I see that we can explicitly opt-out of using the OS's FS events with https://figwheel.org/config-options.html#hawk-options . I don't think I understood why that would be useful before. This is a lot simpler than my shenanigans above.
In summary, this problem is a temporary problem that is being worked on and will hopefully be fixed by the time Big Sur is released this fall.
Folks that are using the Big Sur preview need to fall back to a :polling
watcher in the :hawk-options
Figwheel option.
I.E.
:hawk-options {:watcher :polling}
Big thanks to @rgm for taking the time to track this down.
I'm not sure where this leaves the "real" fix ... is it something like having figwheel rely directly on the patched jna dependency in deps.edn
once one's available? Or do we work through getting the upstream deps updated through barbary -> hawk -> figwheel?
We'll make sure that hawk has this fix.
FYI, JNA 5.6.0 has been released.
@bhauman I got to thinking, dealing with this issue: would the ability to manually trigger builds be a useful add? I used to run into polling battery-drains in Meteor.js because of how they originally implemented their own file watcher and so I've tried to rely as much as possible on more dedicated tools like http://eradman.com/entrproject/ instead of a hodgepodge of a SASS watcher here and a gulp thing there, with another for the test watcher, etc. etc.
In Gary Bernhardt's old Destroy All Software videos he would set up a manual unit test trigger in his editor (eg. for vim it would be something like :map ,t :wa\|!ruby -Ilib %<CR>
so that every time you hit ,t
in normal mode, the focused unit test on the current file would run). Over time, I've come to personally prefer this approach. I know it's not a beginner thing so I don't think dumping all file watching code is very realistic.
But it did get me thinking: could the default Figwheel server on 9500 listen for a POST, instead of watching the filesystem? This would be reasonably straightforward to hook up per the above, eg. :map ,t :wa\|!curl -X POST http://localhost:9500/_build
for us vimmers, or if using the Entr util, in another shell window:
> find src -name ".clj*" | entr curl -X POST http://localhost:9500/_build`.
I just got to thinking I'd been here before with Javascript file watchers rotting, and maybe this could add some extra advanced abilities, eg. being able to observe static EDN or JSON data under /resources
, or rebuild when .clj
sources change instead of just .cljs
or .cljc
files change.
I guess the challenge would be to communicate to Figwheel which namespaces to hot-reload ... maybe by hashing the contents of known files on the classpath?
I'm happy to try taking a crack at this if you think it's a reasonable idea.
(Apologies if some or all of this already exists. Often I don't appreciate the words in the manual until I re-read them after musing like this for a while).
@rgm In order to capture the full behavior of figwheel a triggered build would have to run through all the files for changes, because figwheel watches javascript and plain Clojure files as well. After the build figwheel can do its own detection of what has changed and do its magic. So really this would be a manual file poll.
This is what gets called when the watcher finds changes: https://github.com/bhauman/figwheel-main/blob/master/src/figwheel/main.cljc#L266
This of course would also affect CSS watching etc.
Creating an end point for this makes sense. But of course there is also the REPL connection so you could add a build
function to the figwheel.main.api
which is intended to be used from the cljs repl. There is currently a figwheel.main/build-once
in the repl but it's not very efficient and it doesn't handle the js
and clj
files.
This deserves more thought.
Creating an end point for this makes sense. But of course there is also the REPL connection so you could add a
build
function to thefigwheel.main.api
which is intended to be used from the cljs repl. There is currently afigwheel.main/build-once
in the repl but it's not very efficient and it doesn't handle thejs
andclj
files.
Hm, I hadn't really followed but I had some time to read through tonight. Perhaps it's enough to bind that (bound-fn ,,,)
to something we can get a hold of from an editor repl connection, presuming that calling it is enough to kick off the whole rebuild -> hot-reload process. (Which I presume it does if it's all hawk knows about; I had some trouble following things all the way through). If it were bound in the build registry, it'd be pretty straightforward to map a shortcut to it, and just leave the file watching off entirely.
After upgrading to macOS 11.5.1
with M1
chip I started to get similar error when starting figwheel-main
:
...
[Figwheel:SEVERE] /private/var/folders/m8/xtnsq6gn2k9d3l4n362z9p080000gn/T/jna4678795419772323478.tmp: dlopen(/private/var/folders/m8/xtnsq6gn2k9d3l4n362z9p080000gn/T/jna4678795419772323478.tmp, 1): no suitable image found. Did find:
/private/var/folders/m8/xtnsq6gn2k9d3l4n362z9p080000gn/T/jna4678795419772323478.tmp: no matching architecture in universal wrapper
/private/var/folders/m8/xtnsq6gn2k9d3l4n362z9p080000gn/T/jna4678795419772323478.tmp: no matching architecture in universal wrapper
[Figwheel] Validating figwheel-main.edn
...
Syntax error (NoClassDefFoundError) compiling at (/private/var/folders/m8/xtnsq6gn2k9d3l4n362z9p080000gn/T/form-init5239701982387845518.clj:1:125).
Could not initialize class com.barbarysoftware.jna.CarbonAPI
$ java -version
openjdk version "1.8.0_302"
OpenJDK Runtime Environment (Zulu 8.56.0.23-CA-macos-aarch64) (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (Zulu 8.56.0.23-CA-macos-aarch64) (build 25.302-b08, mixed mode)
This setting helps:
:hawk-options {:watcher :polling}
but feels not great.
I've tried to run master
branch version and it works fine. Looks like https://github.com/bhauman/figwheel-main/pull/299 helps not only with the speed 🙂
Could you, please publish it if possible?
I'm experiencing the same thing on the Apple M1. Any update on a new release?
EDIT: Ack, my bad! My issue is purely wkf/hawk related, not figwheel. Sorry!
@bhauman this issue can be closed (see comment by @il-tmfv) a release has seen been made, so AFAIK this is resolved.
When starting up file watching via wkf/hawk, an exception is thrown. After a little digging, this looks to be caused by changes to how MacOS loads dylibs in 11.0+.
It looks like the JNA folks are already working on a fix, so once that lands, we can update (or fork) BarbaryWatchService, then update wkf/hawk to use it.
Stack trace: