Closed psobolewskiPhD closed 2 years ago
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/fiji-clij-etc-native-on-apple-silicon-arm64-m1/53627/16
4. my universal imagej-macosx (x86/arm64), with current official JRE (x86): Wrong architecture error, system Java fallback, launches Fiji, No issues. (<4 s launch)
Thinking about it more, this is a regression, since being able to run Fiji in Rosetta can certainly be desired—especially in the early going, ie. now.
I’m puzzled that Get Info does not offer Open using Rosetta, as is available for other universal (x86/arm64) apps. However, the launcher can be forced into x86 mode and Fiji launches in Rosetta from the terminal:
arch -x86_64 ./ImageJ-macosx
Probably best that the "stable" Fiji be x86 launcher, x86 JRE, but perhaps use the universal for a No JRE version or for a arm64 JRE version.
@psobolewskiPhD I want to thank you for all your efforts in this direction, and apologize for my silence till now. Another user asked on in the fiji Gitter chat room about running Fiji on M1, so I linked them to this very helpful issue. :smile:
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/fiji-clij-etc-native-on-apple-silicon-arm64-m1/53627/24
Hey Peter, thanks for your work on this, it'll only become more important as more M1 Macs are adopted in the bioimaging community.
My issue is that, while I can manage to compile the launcher into an ARM executable that runs, imagej-launcher itself seems to be incompatible with modern versions of the JDK, both the official ARM-native Oracle JDK17 (https://www.oracle.com/java/technologies/downloads/#jdk17-mac), and OpenJDK from a package manager like Homebrew.
The error is Required service is missing: net.imagej.legacy.LegacyService, preventing Fiji/ImageJ from launching. The issue seems to have come up before in discussions related to Java 9 and 10 in this repository.
We could just stick to this Azul JDK, but I'm curious to know:
Do you get the same errors when using the current ARM-native OpenJDK?
Did you manage to find an ARM-native version of OpenJDK 8 or any earlier version of the JDK known to work well with imagej-launcher?
Do you have any insight into why the launcher fails with more recent JDKs? (Probably this would be better to escalate as a separate issue if it's not just something specific to my setup.)
I've only used (and still using) Azul Java 11. There is a java 8 from Azul: https://www.azul.com/downloads/?os=macos&architecture=arm-64-bit&package=jdk I've not tried it though. Never seen that message, sorry!
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/could-not-install-fiji-on-mac-os-monterey-can-any-one-help-thanks/63880/13
@psobolewskiPhD This is fantastic.
The missing case is universal launcher on x86 Mac, which I might be able to try this weekend.
Did you get a chance to try this out? (with the "official" x86 azul java 8 JRE) If that works then I am in favor of merging this and building new bundles.
Sorry an x86 mac isn't conveniently available at the moment. I'll poke around maybe can figure something out...
@psobolewskiPhD just had someone locally test the launcher on an x86
mac and it seems to work (thanks @etadobson!)
@psobolewskiPhD This is fantastic.
The missing case is universal launcher on x86 Mac, which I might be able to try this weekend.
Did you get a chance to try this out? (with the "official" x86 azul java 8 JRE) If that works then I am in favor of merging this and building new bundles.
The only catch is I think it won't work on M1 wanting to run x86 in Rosetta. Edit: See my comment here https://github.com/imagej/imagej-launcher/issues/82#issuecomment-858549849 If they have system Java it will fall back to that. If not, I think it will just give the no JVM found due to the arch error.
╰─ ./ImageJ-macosx (base) ─╯
Could not load Java library '/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/java/macosx/adoptopenjdk-8.jdk/jre//Contents/Home/jre/lib/jli/libjli.dylib': dlopen(/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/java/macosx/adoptopenjdk-8.jdk/jre//Contents/Home/jre/lib/jli/libjli.dylib, 0x0001): tried: '/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/lib/macosx/libjli.dylib' (no such file), '/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/mm/macosx/libjli.dylib' (no such file), '/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/java/macosx/adoptopenjdk-8.jdk/jre//Contents/Home/jre/lib/jli/libjli.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), '/usr/local/lib/libjli.dylib' (no such file), '/usr/lib/libjli.dylib' (no such file), '/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/lib/macosx/libjli.dylib' (no such file), '/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/mm/macosx/libjli.dylib' (no such file), '/Users/piotrsobolewski/Dev/Fiji MacOS Java/Fiji.app/java/macosx/adoptopenjdk-8.jdk/jre/Contents/Home/jre/lib/jli/libjli.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), '/usr/local/lib/libjli.dylib' (no such file), '/usr/lib/libjli.dylib' (no such file)
Warning: falling back to System JVM
Seems like the FAT binary defaults to native if possible which then clashes with the Java.
So maybe the x86 Java bundle should have x86 launcher. But the no-JRE bundle could have the FAT launcher? And a putative arm64 Java bundle could have FAT too.
@psobolewskiPhD would you mind testing one more bundle? This should have your arm64
launcher + the arm64
zulu Java 8 JRE.
The only catch is I think it won't work on M1 wanting to run x86 in Rosetta.
I don't have a sense of how big an issue this might be - why would they want to do this? They would still have the option to just use the arm64
bundle, right? My primary concern is that users on both x86
and arm64
macs have a download that works for them.
Your new bundle is wierd? I don't get it. I get system Java when double click and the main menu is ImageJ (not Fiji) and About ImageJ gives just java
. But I get Java 8 when using the terminal launcher and the main menu is Fiji and the About Fiji launches the fancy multi channel image.
🤷
I will download a fresh no-JRE and try transplanting the zulu +/- a fresh zulu zip.
Edit: Yeah I can't figure it out. Same behavior. Why would double click be different than ./Imagej-launcher?
Edit2: it has to be something with the Contents/Info.plist I tried:
<key>LSArchitecturePriority</key>
<array>
<string>arm64</string>
<string>x86_64</string>
<string>i386</string>
<string>ppc64</string>
<string>ppc</string>
</array>
See: https://developer.apple.com/documentation/bundleresources/information_property_list/lsarchitecturepriority But the behavior hasn't changed.
I don't have a sense of how big an issue this might be - why would they want to do this? They would still have the option to just use the
arm64
bundle, right? My primary concern is that users on bothx86
andarm64
macs have a download that works for them.
I think it comes down to plugins. Basically, anything with a compiled dependency that hasn't setup an arm64 version will not run in an arm64 Fiji. It's all or nothing: all emulated by Rosetta2 (which btw, excludes AVX instructions) or all native arm64. I've been using all native arm64 from the start basically & chronicled some of my experiences here: https://forum.image.sc/t/fiji-clij-etc-native-on-apple-silicon-arm64-m1/ Frequently recompiling the depends is easy (see CLIJ or this launcher) but the devs of the plugin may have no idea or no interest.
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/could-not-install-fiji-on-mac-os-monterey-can-any-one-help-thanks/63880/14
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/fiji-bundles-updated-with-newest-zulu-8-jdk-fx/65809/7
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/fiji-bundles-updated-with-newest-zulu-8-jdk-fx/65809/11
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/how-to-get-fiji-to-run-natively-on-macos-m1-arm64-apple-silicon/68384/2
Now that we have f5942cb1484c011d016b1064b137a654c0f44a57, can this issue be closed? Of course, still need to solve #86 and cut a new release of the Launcher and update Fiji to use this new version.
Sure.
For anyone else reading, you can now build the Universal launcher yourself, by cloning the repo and building from source (assuming you have build tools).
Just cd
into the root of the repo and use cmake .
That should do some configuration and generate build files.
Then type make
and you should get a binary.
You can check it using:
lipo -info ImageJ-macosx
Note: you do need to make sure your $JAVA_HOME env variable is set (ie. that you have a system java installed).
@psobolewskiPhD Thanks. You don't even need to run CMake directly; just run mvn
and it should build everything (calling CMake under the hood).
I'm starting to wonder if having a universal launcher is a good idea. Does that mean we will need to make dual-arch fat binaries for everything?
I think we should figure out how to have distinct launchers for the Intel and the Apple M processors as soon as possible.
What's the advantage of distinct launchers vs a universal binary? It's all determined by the Java install anyways. Edit: to make it clear: the only way to run Fiji native at the moment is by installing a native system Java and using no-JRE Fiji. These are pretty deliberate choices...
I think a plan for moving to support M1 in general is a good idea. It will make it easier to find bugs, report stuff, etc. Cross compiling in most cases isn't hard, so just getting eye balls on stuff that needs some attention seems like a win to me, but I'm obviously biased since I have an M1.
The launcher is only the beginning. There are more native components that need M1 support. Are we going to be put into a situation where we need to make other native components universal as well? I think the answer to this is yes, although I'm not sure if it necessarily applies to everything.
If the answer is yes, then are upstream suppliers of binaries doing the same or will we need to repackage them? Looking at the homebrew discussion, it's pretty clear that they are not going to support universal binaries: https://github.com/Homebrew/brew/issues/10307
Based on the last time Apple switched processor architectures, there will come a time when we will want to drop or otherwise deprioritize Intel macOS support. Apple also dropped support for universal binaries at some point before reestablishing it for the current architecture change. How will distributing a universal binary affect our ability to split the binaries and prioritize one over the other in the future?
The question I'm asking is what kind of technical debt are we taking on by choosing to distribute a universal binary as opposed to treating aarch64-macOS as a distinct platform now rather than later?
Does that mean we will need to make dual-arch fat binaries for everything?
I don't think it does. We can have a fat launcher, but keep the other native libs in lib/<arch>
and jars/<arch>
separate. I agree @mkitti that in general we should do that. But for the launcher specifically, I don't really see the harm in having a universal one. Unless you think Apple might decide to make fat binaries stop working on future versions of macOS...?
I don't think they ever disabled running the old Universal binaries (PPC/x86)--there are plenty in the Fiji bundle. I think more likely Apple will stop supporting Rosetta2 at some point.
Eitherway, I can see the argument for keeping the x86 bundle x86 only and making a arm64 bundle that is arm64 only, because there is no FAT JRE (that I know of), so that will always be the decider.
But for the no-JRE bundle, which is currently the only arm64 option for M1, I think the FAT launcher is a real boon, because you can have multiple Java installed and just change using java_home
.
While universal mach-o binaries with PowerPC support still technically work, they became impractical at some point since new software needed to adapt for recent versions of Mac OS X which did not run on PowerPC.
Let's say a user downloads a FIJI bundle with a universal launcher. Suppose then Apple completely stops releasing new versions of macOS for Intel in three years. Perhaps a year or two after that, we find that we cannot support both recent macOS and legacy macOS with the same code as happened after the PowerPC transition. Do subsequent versions of the universal launcher contain a build with new code for the M9 processor and an a build for Intel processors using older code? At that point, how can we update the universal launcher?
The problem I am anticipating is that the use of a FIJI install will exceed Apple's transition period. At the end of that transition period, we may have an issue updating users from a universal binary to a platform specific one when the technical need arises.
Perhaps the solution is to give the universal launcher a unique name that clearly identifies what it is. Maybe one of the following.
Imagej-macosx-universal
Imagej-macosx-x86_64_aarch64
This would be in anticipation of possibly needing a ImageJ-macosx-aarch64
in the future.
The immediate practical question for me is what do I with libblosc
and other binaries that depend on it such as the HDF5 Blosc plugin I'm working on now.
I'll weigh in as a more of a user and less a developer-- even though I know I should defer to the people doing the real work here!
The model for supporting Mac as a platform with more than one architecture really seems to be universal binaries. I don't see the downside: it has never been true that universal binaries that include executable code for outdated architectures no longer run--the system just chooses the code for the compatible platform. There's no "post-transition" period where you have to go back to supplying platform-specific executables.
If, eventually, a developer no longer feels it's necessary to support Intel, just remove it as a build target (the same way that we no longer include "power_pc" as a build target). But even if the Intel target is included for much longer than necessary, there's no harm to leaving it in.
The binaries are "fat," but in the grand scheme of things, what are we really talking about here, 100 MB? Isn't the bulk of an IJ installation the JARs?
There's no "post-transition" period where you have to go back to supplying platform-specific executables.
There is a point where Apple stops supporting Intel Macs, just as they stopped supporting PowerPC Macs. After that, Apple offers no guarantee that this will continue to work. We already have enough issues with code signing as is.
If, eventually, a developer no longer feels it's necessary to support Intel, just remove it as a build target (the same way that we no longer include "power_pc" as a build target).
What makes FIJI unique is that we support the software over a very long period of time. A new install now could still be in use in five years or even ten. The problem is that we could not just stop shipping Intel support for a binary called "ImageJ-macosx". If we auto-updated that binary without Intel support, we would break FIJI for people who are still using Intel Macs.
Currently, we still have a ImageJ-macosx-tiger in the bundles. Why is that?
Basically, I'm asking the question now about the future support plans to make sure we have an easy path forward in several years.
What makes FIJI unique is that we support the software over a very long period of time. A new install now could still be in use in five years or even ten.
Not on macOS, unfortunately. Apple virtually guarantees that with their strategy of decisions to intentionally obsolete old hardware and software. Any scientist who buys and uses a Mac needs to be aware of this. Major example: the Java 6 version of Fiji can no longer run on macOS, because Apple Java 6 no longer works, because they don't maintain it, and it makes use of old deprecated+broken native APIs.
To clarify though, I'm not disagreeing with you @mkitti. I share your desire to make Fiji work for as long as possible on macOS. But only within the compatibility restrictions imposed by Apple. The good thing is that we also try to make old scripts and plugins continue to work in new downloads of Fiji. So even if a macOS user's Fiji stops working when they update their hardware and/or software, a project goal is for it to be straightforward for them to install a new Fiji that does work on that hardware+software, including all their old scripts, customizations, etc.
If we auto-updated that binary without Intel support, we would break FIJI for people who are still using Intel Macs.
Until now, Fiji has been a so-called portable application, meaning you can have a single Fiji.app
on a thumb drive with multiple java
subfolders, one for each platform you want to use it on. And then you can plug that thumb drive into whatever computer, and double-click the appropriate launcher, and Fiji will start up with the correct JDK for that platform. Same Fiji, multiple machines with different OSes/platforms.
The switch to M1/ARM has endangered this, because we cannot have Info.plist
point to two different native launchers, can we? But we can point to a universal launcher, which dynamically links to the correct Java for the architecture, supporting both x86 and ARM for the foreseeable future.
If the time comes when we can no longer build a universal launcher for all architectures running macOS, then we are already sunk, because we will need to ship a different Info.plist
per platform at that point, meaning we cannot have a single portable Fiji.app
folder anymore. When that day comes, we can decide whether to A) discontinue support for macOS x86 or whatever old problematic architectures; or B) abandon the "portable app" design of Fiji in favor of a customized Fiji.app
for each architecture of macOS. There are other reasons to embrace (B) anyway, such as less confusion on Windows and Linux (where the folder name Fiji.app
makes no sense), and potentially easier distribution via platform-specific application delivery systems: Chocolatey, Homebrew, Flatpak, etc.
Currently, we still have a ImageJ-macosx-tiger in the bundles. Why is that?
Because I am afraid to remove it, in case it still benefits anyone in the wild.
But we can point to a universal launcher, which dynamically links to the correct Java for the architecture, supporting both x86 and ARM for the foreseeable future.
Is this implemented? Because in my tests Java version is chosen alphabetically...
@psobolewskiPhD It is implemented in the sense that Linux x86-64 looks in subfolders of linux-amd64
, Linux x86-32 looks in subfolders of linux
, Windows x86-64 looks in subfolders of win64
, Windows x86-32 looks in subfolders of win32
. But for macOS, it looks in subfolders of macosx
without checking the architecture. Should be a simple fix to make the launcher check for arm64 and look in macos-arm64
instead, no? And likely also pretty easy to make it look there first but then fall back to macosx
if nothing found, so that Rosetta2 can do its thing in that situation.
This issue has been mentioned on Image.sc Forum. There might be relevant details there:
https://forum.image.sc/t/fiji-for-apple-silicon-macs/80794/2
I've been using Fiji on an Apple Silicon M1 (arm64) MacBook Pro (Big Sur 11.4) I've started a image.sc thread regarding getting things to work smoothly native rather than in Rosetta emulation. https://forum.image.sc/t/fiji-clij-etc-native-on-apple-silicon-arm64-m1/53627/16 Everything works when architectures are matched, so everything emulated or everything native. Mixing architectures is a no go.
So for Fiji/imagej the key is native JRE. I have Azul 11, but native OpenJDK is also available via homebrew, and use of the "No JRE" Fiji. (The normal Mac OS install also works fine in Rosetta, but is markedly slower.)
The existing launcher actually works—despite being x86.
It does report an architecture mismatch error and does a fallback to system Java, which results in a 2nd Fiji icon in the dock—minor inconvenience.
As noted in the thread, Apple docs show you can build for a different architecture than you run (can't test obviously) and can build universal binaries. This is also supported by cmake, which I was pleased to see is used by the imagej-launcher.
I made a fork (https://github.com/psobolewskiPhD/imagej-launcher) and tweaked CMakeLists.txt to provide the two arch for cmake (to make a universal binary). I also had some Java path issues, which may be a Big Sur thing.
The project compiled with no issue and the binary is universal: ~/dev/imagej-launcher > lipo -info ImageJ-macosx Architectures in the fat file: ImageJ-macosx are: x86_64 arm64`
I've tested this binary on my Apple Silicon M1 Mac. It works fine with the following behavior when launched from the command line to monitor errors (there's some warnings too regarding patcher/injector, but they seem of no issue):
(Also, if anyone is curious, if you put both an x86 and arm64 JRE in Fiji.app/java it's alphabetical. So adoptopen vs zulu results in wrong architecture error and system java. While adoptopen vs 1_zulu uses the included zulu.)
So from where I sit, a universal imagej-macosx for Fiji with native JRE inside is the best for Apple Silicon Macs, but all cases work fine, as long as a system Java exists. The missing case is universal launcher on x86 Mac, which I might be able to try this weekend. Here's a link to the binary if anyone wants to test it themselves, it belongs in: Fiji.app/Contents/macos https://www.dropbox.com/s/1ftxheyx85siko3/ImageJ-macosx.zip?dl=0