Having found myself using a Chromebook with Arch Linux, I acutely felt the lack of official [Crystal](https://crystal-lang.org) builds for ARM. After spending an hour or so looking online for a comprehensive guide to getting a working compiler on ARM, I think I now know the general idea. I will lay it out here, for myself, as well as for others who may be in the same situation.
### To compile Crystal, you need Crystal
To compile Crystal without bootstrapping it from older versions, you need a different machine which is capable of cross-compilation. Fortunately for me, my friends and I have previously set up a server hosting several x86_64 virtual machines, one of which we dedicated to cross-compiling various programs.
To get started, I had to download the compiler on that machine:
```
sudo pacman -S crystal
```
Note that this isn't the ARM Chromebook. Running this command on the Chromebook would not work.
### Building on the x86_64 Machine
After getting the compiler, I also needed to download the compiler source. This was done using git:
I also installed `llvm6`, which is required on both the machine that's building the compiler and the machine for which the compiler is being built:
```
sudo pacman -S llvm6
```
From here on in, I ran commands from inside the directory that was downloaded via `git clone`:
```
cd crystal
```
Finally, I didn't want to compile the "master" version of the compiler. It wasn't a release! To check out the latest release (0.27.2 at the time of writing), I used git:
```
git checkout 0.27.2
```
Now, I had the compiler and the source. I was ready to compile the source to get myself a nice ARM Crystal compiler. But how? The official guide specified two options for cross compilation:
*`--cross-compile` - This option is basically a flag. You just add it to the command to enable cross compilation.
*`--target=<llvm target triple>` - This specifies the target architecture you're building for.
In order to get the second option right, I had to know the LLVM target triple for my target machine. To find it, I ran the following command on that machine:
```
gcc -dumpmachine
```
This produced the output `armv7l-unknown-linux-gnueabihf`. This was exactly what I needed to know!
Finally, looking through the Makefile in the repository, I found three more flags that are used by default in the process:
There is only one more trick to cross-compiling Crystal: although the official guide specifies the options `--cross-compile` and `--target=...`, and although you can just attempt to use the `crystal` command on the source file, __this won't work__. You need to use the wrapper script that Crystal provides. I had to replace `crystal` with `./bin/crystal`:
With this, I finally obtained a `crystal.o` file. After downloading this onto my target machine, __and making sure to copy the command the compiler printed out__, I was ready to proceed.
### Compiling on the Target ARM Machine
Just like with the x86_64 machine, I needed llvm6:
```
sudo pacman -S llvm6
```
I also needed the Crystal source, again!
```
git clone https://github.com/crystal-lang/crystal.git && cd crystal
git checkout 0.27.2
```
Finally, I needed a few more libraries. These are `gc` (the Garbage Collector Crystal uses) and `libevent`:
```
sudo pacman -S gc libevent
```
With these dependencies installed, I could compile the last two files needed to build a working compiler:
```
make deps
```
After this, the command I noted down from earlier (on the x86_64 machine) was all that was left (note that I placed `crystal.o` in the clone of the Crystal repository):
I was not done. The executable couldn't compile a basic "Hello, world"! This is because I once again needed the wrapper script. This script searches the `.build` directory for the Crystal executable, and so I placed it there:
```
mkdir .build
mv crystal .build
```
Finally, I made sure to add the `./bin` directory to my PATH.
### Shards
Crystal is not complete without its package manager, shards. This program doesn't need to be cross compiled, but it does come separately from the compiler. First, I cloned the repository: