1. Use the cross-compilation toolchain to compile the aarch64 program
1. The disadvantage is that you cannot use the NixOS binary cache, and you need to compile everything yourself (cross-compilation also has cache, but there is basically nothing in it)
2. The advantages are that you don't need to emulate the instruction set, and the performance is high
2. Use QEMU to emulate the aarch64 architecture, and then compile the program in the emulator
1. The disadvantage is that the instruction set is emulated and the performance is low
2. The advantage is that you can use the NixOS binary cache, and you don't need to compile everything yourself
by using method one, you don't need to enable binfmt_misc, but you need to execute the compilation through the cross-compilation toolchain.
If you use method two, you need to enable the binfmt_misc of the aarch64 architecture in the NixOS configuration of the building machine.
### Cross Compilation
nixpkgs comes with a set of predefined host platforms for cross compilation called pkgsCross, let's explore them in `nix repl`:
```shell
› nix repl '<nixpkgs>'
warning: future versions of Nix will require using `--file` to load a file
The `nixpkgs.crossSystem` option is used to set `pkgs` to a cross-compilation toolchain, so that all the contents built will be `riscv64-linux` architecture.
## Compile through emulated system
The second method is to cross-compile through the emulated system. This method does not require a cross-compilation toolchain.
To use this method, first your building machine needs to enable the binfmt_misc module in the configuration. If your building machine is NixOS, add the following configuration to your NixOS Module to enable the simulated build system of `aarch64-linux` and `riscv64-linux` architectures:
You do not need to add any additional modules, just specify `system` as `riscv64-linux`.
Nix will automatically detect whether the current system is `riscv64-linux` during the build. If not, it will automatically build through the emulated system(QEMU). For users, these underlying operations are completely transparent.
### Custom build toolchain
Sometimes we may need to use a custom toolchain for building, such as using our own gcc, or using our own musl libc, etc. This modification can be achieved through overlays.
For example, let's try to use a different version of gcc, and test it through `nix repl`:
```shell
```shell
› nix repl -f '<nixpkgs>'
Welcome to Nix 2.13.3. Type :? for help.
Loading installable ''...
Added 17755 variables.
# replace gcc through overlays, this will create a new instance of nixpkgs
`nixpkgs.overlays` is used to modify the `pkgs` instance globally, and the modified `pkgs` instance will take effect to the whole flake. It will likely cause a large number of cache missing, and thus require building a large number of Nix packages locally.
To avoid this problem, a better way is to create a new `pkgs` instance, and only use this instance when building the packages we want to modify. The example `flake.nix` is as follows: