The basic homebrew command cannot install Crystal properly on Apple Silicon M1. And the “install” page did not mention anything about it.
llvm@9: The x86_64 architecture is required for this software.
Error: An unsatisfied requirement failed this build.
I have seen that we can try to install it under Rosetta 2, but I did not find any proper instruction related to this. I have tried a few ways to install brew and software under Rosetta 2 (found on google), but all of them are not working for Crystal.
So if there is any solution, or it is not supported yet, I suggest mentioning it out on the “install” page of the crystal-lang website.
One of the challenges of a self-hosted compiler (the Crystal compiler is written in Crystal) is that support for other architectures must be released before it can be used to compile itself for that architecture.
The tooling inside the compiler to allow it to compile itself for the M1 processor was just released with 1.0 so M1 builds on Homebrew won’t be available until at least the next release.
The pkg file from the releases page is built for the x86_64 architecture, so it’ll run on the M1 via Rosetta 2 but it isn’t yet optimized for the native ARM architecture of the M1 processor.
The good news is that there are instructions for building Crystal on the M1. On my M1 MBP I compiled the compiler from source with those instructions. I did add --release to compile the compiler in the last step to optimize compilation times for my apps, though. With that in place, I’m seeing compile times on my apps up to 30% faster than on my iMac — which is the Intel Mac with the fastest single-core benchmarks on Geekbench.
Thanks for this link also Jamie. I took a look at the build instructions for the M1 but I kept getting errors about linker & architecture issues. I just skimmed the thread (and followed the post you linked directly so it’s possible I overlooked something).
I think I’ll just need to wait until the next release when we have some
For those looking at the omni, I just ran into some issues with linker issues due to SSL architecture issues so even the omni may not solve every issue. Even docker images won’t run correctly locally so I may just wait until this sorts itself out.
I gave this multiple run thrus from scratch last night & again today. Upgraded big sur, xcode, etc. Something seems to have changed. I made it all the way to the last step last night (with small tweaks here and there)
Pulled down latest changes from main branch today and now it dies early (sigfault file is missing for one)
Upside though: Docker works now so i think there was an update.
Thanks, that’s helpful to know. I’m still going to wait a bit until this gets homebrew support or has some additional instructions. I wasn’t interested as much in crystal development as I was just writing code in it.
Some of the steps I’m noticing failing for M1 support (like libcrystal.a not compiling, and missing for example) are a bit too much for me to step into right now.
Has anyone had any luck getting Lucky working on an M1 by chance? For brevity’s sake, here’s the link to the Github of what I’ve tried to do to get Crystal and Lucky running. I managed to get it mostly working but I run into an issue when running script/setup at database creation. OpenSSL doesn’t seem to play nice with Crystal and I’m guessing it might be because OpenSSL is native and Crystal is running as x86? I installed Crystal 0.36.1 from the .pkg file since Lucky isn’t compatible with 1.0 yet.
I’m seeing the same issue you seem to see; when using the omni installer pkg file, openssl doesn’t seem to link/work correctly. The instructions that Jamie linked above, here, might fix that issue. I haven’t been able to build it myself off of those instructions yet.
libcrystal.a is no longer needed, so you can skip any mention of it (don’t need to build or link it).
You also need to be using LLVM 11 on an M1 for it work (both on the x86_64 and arm64 sides of Homebrew).
Other than that, the instructions should still work, but I haven’t built from scratch on an M1 in a little bit. I’m hoping to find some time this week to sit down and write up a blog post on doing it, so that I can keep that up-to-date as things change.
Once full support for LLVM 11 lands in Crystal land, and the x86_64 macOS build of crystal is built with LLVM 11 it should be possible to build an arm64 build via Homebrew from the x86_64 build.
Max thanks for this. I took at a look at your post, it’s mostly similar to the original one linked but the compilation near the end is different. I think the only piece I’m missing is what to do with the reference to libcrystal.a in the snippet from:
Even removing the reference to libcrystal.a returns this error:
Undefined symbols for architecture arm64:
"___aarch64_cas8_relax", referenced from:
_GC_mark_local in libgc.a(mark.o)
"___aarch64_ldadd8_relax", referenced from:
_GC_generic_malloc_many in libgc.a(mallocx.o)
"___aarch64_ldset8_relax", referenced from:
_GC_dirty_inner in libgc.a(os_dep.o)
ld: symbol(s) not found for architecture arm64
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
I feel like I’m missing something obvious. I wrapped these inside of a gist here: Build crystal · GitHub
You can remove any reference to libcrystal.a. It doesn’t exist any more. There’s nothing to replace it with, just remove it anywhere it shows up
As for the other messages related to libgc.a, it’s possible it compiled libgc for x86_64 instead. The good news is, we don’t actually need to install it from source anymore, as Homebrew now include the proper patches in their version. You can try by using bdw-gc installed via Brew (brew install bdw-gc, assuming you’ve installed Homebrew for ARM). If using the Brew version, you can remove any references to libgc.a.
Working on the blog post right now, and hopefully will have something to show later that goes into the changes more.
I’m happy to take a look at the blog post when you’ve got it posted
I think I got it sorted with your suggestions. I had to brew unlink bdw-gc, then brew install libatomic_ops and then brew link bdw-gc --HEAD. Then copy the right libgc.a file into the crystal root. I updated the instructions in my linked gist. Still have to run specs, but it runs and reports a version
Tested it all this evening, and was able to get working shards, as well as another application compiled and running without making any changes to either of those.
I need to tweak the code blog styles on my blog a bit so that it’s not so ugly, but after that I’ll publish more broadly.
@maxfierke , thank you so much for the blog post and the effort you’ve put into this.
I’m hitting a snag, though, on trying to compile for x86_64. Make is returning the error “make: *** No targets specified and no makefile found. Stop.”. Could you help me understand which makefile needs to be processed? I’m just not familiar at all with LLVM (or crystal)! I’m also in zsh, which I’m not sure if that matters. I double-checked all the env variables, and they seem correct, too.