**Custom Cross Compiler with Nix**

**Introduction** ===============

As a developer, you may have encountered situations where you need to write code for an unusual system or platform. Even if you have a cross compiler at your disposal, getting it working with Nix can be a daunting task. In this article, we'll explore the journey of creating a custom cross compiler with Nix and provide a detailed solution that saves you time.

**The Journey Begins** =====================

I have a deep love for Risc Os, an old operating system made by Acorn Computers Ltd. for their Archimedes range of computers. Although it's still possible to run it on Raspberry Pi, programming it is not easy due to its outdated conventions and lack of good text editors. However, there's a cross compiler available, but it requires a seriously old version of Ubuntu on X86_64 Linux (patched GCC 4.7.4). Since I'm currently using an Arm Mac, I couldn't build the compiler with such an old version.

**Enter Nix** =============

At this point, we can use Nix to our advantage. We can create a flake that builds the cross toolchain and use it to cross-build software using the Rosetta builder from Mac OS.

**Building Old Versions of GCC** -------------------------------

As you might expect, building old versions of GCC is a task I wouldn't wish upon my worst enemies! However, this is where Nix shines. We can create a flake that builds our custom cross toolchain and use it to build packages for Risc Os.

**Custom Cross-Stdenv** =====================

After having our cross toolchain built in Nix, we want something more convenient than manually invoking the correct compiler or passing the correct `--target` option. We need a custom cross-stdenv that does all this work for us!

**How C Compilers Work in Nix** ------------------------------

When building compilers, Nix uses a specific mechanism to wrap them with the necessary tools and libraries. However, if we build binutils and GCC separately, the cross-GCC will try to use `ar` and `as` instead of their cross-compiled counterparts.

**pkgs.wrapCCWith: The Magic Begins!** -------------------------------------

To solve this issue, we can use Nix's `wrapCCWith` function. This function takes a C compiler as an argument and wraps it with the necessary tools and libraries. However, if we simply call `pkgs.wrapCCWith` with our cross-GCC, it won't work.

**Telling Nix We Want to Cross-Compile** ---------------------------------------

The reason behind this is that Nix needs to know when we're cross-compiling versus building a normal package. When cross-compiling, the host platform differs from the build platform.

**The Hidden Package Set** -------------------------

But where do cross compilers live? They can't live in `pkgs` because their target differs from the package set's target. Nor can they live in `pkgsCross` because their host (our system) differs from the package set's.

**Solving the Puzzle** =====================

The solution lies in creating a new package set that defines our cross platform and overrides the configuration to get the correct compiler prefix.

**Final Solution** ==================

Here's the final flake that we'll use to build our custom cross toolchain:

```html

import pkgs;

let riscosTools = pkgsCross { system = "riscos"; }

riscosToolchain = riscosTools.buildToolchain { crossSystem = "arm-unknown-riscos"; }

crossConfig = { config, ... } @ { config = config._module.args.config; }

crossBuildSystem = pkgsCross.wrapBintoolsWith { config = crossConfig; }

crossCCWrap = pkgsCross.wrapCCWith { config = crossConfig; }

packageSet = pkgs.pkgsCross.cross.riscos;

in { inherit riscosToolchain; packageSet; }

```

This solution creates a new package set that defines our cross platform and overrides the configuration to get the correct compiler prefix.

**Conclusion** =============

In this article, we've explored the journey of creating a custom cross compiler with Nix. We've seen how building old versions of GCC is a task not for the faint of heart and how Nix can be used to create a custom cross-stdenv that simplifies our workflow. With the final solution in place, you should now have a working custom cross toolchain for Risc Os.

Note: This article uses HTML formatting with `

` tags for better readability.