---
title: "Sword Windows Cross Build 20241018"
date: 2024-10-18T11:05:36-05:00
draft: false
---
*[TL;DR](#tldr)* Just let me download it

I have been trying to come up with a good, reliable way to build executables for
Windows from Linux for a long time. One of the longer running problems I have had
is that the ground keeps shifting out from under me. Sometimes, you've got exactly
the set of requirements that you need, and that's all you want! But, when I have
previously used things like the [MinGW](https://sourceforge.net/projects/mingw-w64/)
toolchain from [Fedora](https://fedoraproject.org/) - I would have had to
freeze the exact machine I was building on in order to be able to reproduce the
same results as before. But, of course, this is not a feasible thing to do, especially
for an open source project that is leveraging CI.

Of course, [Nix](https://nixos.org) came along and has largely solved the problem of
pinning an entire system of libraries, executables, and compilers. But I had never
dived into how to use its pinning power to create a cross compile result. Well, it
turns out that it was simpler than I had thought. So I went about compiling my
favorite cross-build library for Windows from my Linux host. That library it
[The SWORD Project](https://www.crosswire.org/sword), available in NixPkgs as just
the package name "sword".

To build Sword for Linux hosts, all you need to do is go to a Linux machine with
Nix already installed (I use NixOS, but it can be installed on basically any distribution
of Linux) and invoke the command: `nix build "nixpkgs#sword`. Provided you have
nixpkgs setup as a flake and you have the nix command and flakes enabled (these are
pretty common options on systems), you will end up with a symlink in your current
directory named `result`. You can then run any of the tools from SWORD by invoking
them like anything else you would call. `./result/bin/diatheke`, for instance, gives
you the diatheke command from SWORD.

But how do you cross compile it? Well, that is already thought out for you! You just
need to invoke `nix build "nixpkgs#pkgsCross.mingwW64.sword`. pkgsCross has quite
a few targets available to you. `mingwW64` is the one that corresponds to Windows for
x86\_64 architectures. It also has an older target for 32-bit Windows machines, as
well as other targets for building. If you are interested, trying using nix repl to
eplore:

```
nix repl
>>> :lf nixpkgs
>>> legacyPackages.x86_64-linux.pkgsCross
```

### BUT....

Was it relaly that simple to build SWORD binaries for Windows from my NixOS machine
the first time? Of course not. The SWORD package is tagged as only supporting Unix-based
or adjacent systems. So I could have compiled for BSDs, Linux on ARM, PPC, RISC-V,
and more. But I got an error message the first time I tried to build for Windows, that
looked something like this:

```
error:
       … in the condition of the assert statement

         at /nix/store/lryfc8mhk1czqsa421di2y5nzz5c3b8m-source/lib/customisation.nix:365:17:

          364|     in commonAttrs // {
          365|       drvPath = assert condition; drv.drvPath;
             |                 ^
          366|       outPath = assert condition; drv.outPath;

       … while evaluating the attribute 'handled'

         at /nix/store/lryfc8mhk1czqsa421di2y5nzz5c3b8m-source/pkgs/stdenv/generic/check-meta.nix:507:7:

          506|       # or, alternatively, just output a warning message.
          507|       handled =
             |       ^
          508|         (

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: Package ‘sword-1.9.0’ in /nix/store/lryfc8mhk1czqsa421di2y5nzz5c3b8m-source/pkgs/by-name/sw/sword/package.nix:49 is not available on the requested hostPlatform:
         hostPlatform.config = "x86_64-w64-mingw32"
         package.meta.platforms = [
           "i686-cygwin"
           "x86_64-cygwin"
           "x86_64-darwin"
           "i686-darwin"
           "aarch64-darwin"
           "armv7a-darwin"
           "i686-freebsd"
           "x86_64-freebsd"
           "x86_64-solaris"
           "aarch64-linux"
           "armv5tel-linux"
           "armv6l-linux"
           "armv7a-linux"
           "armv7l-linux"
           "i686-linux"
           "loongarch64-linux"
           "m68k-linux"
           "microblaze-linux"
           "microblazeel-linux"
           "mips-linux"
           "mips64-linux"
           "mips64el-linux"
           "mipsel-linux"
           "powerpc64-linux"
           "powerpc64le-linux"
           "riscv32-linux"
           "riscv64-linux"
           "s390-linux"
           "s390x-linux"
           "x86_64-linux"
           "aarch64-netbsd"
           "armv6l-netbsd"
           "armv7a-netbsd"
           "armv7l-netbsd"
           "i686-netbsd"
           "m68k-netbsd"
           "mipsel-netbsd"
           "powerpc-netbsd"
           "riscv32-netbsd"
           "riscv64-netbsd"
           "x86_64-netbsd"
           "i686-openbsd"
           "x86_64-openbsd"
           "x86_64-redox"
         ]
         package.meta.badPlatforms = [ ]
       , refusing to evaluate.

       a) To temporarily allow packages that are unsupported for this system, you can use an environment variable
          for a single invocation of the nix tools.

            $ export NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1

          Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake,
                then pass `--impure` in order to allow use of environment variables.

       b) For `nixos-rebuild` you can set
         { nixpkgs.config.allowUnsupportedSystem = true; }
       in configuration.nix to override this.

       c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
         { allowUnsupportedSystem = true; }
       to ~/.config/nixpkgs/config.nix.
```

That's a WHOLE lot of text to tell me it can't build for Windows! But, I have opened some pull requests
for NixPkgs so that SWORD will be listed as supported. Because, indeed, there isn't anything inherent
in SWORD that requires it to be built for only Unix systems. It supports all manner of embedded, Windows,
and other environments in addition to standard Linux/Unix platforms. It only required a few tweaks to
the build formula to tell it where to find the options that it wanted.

### TLDR

Show me the goods!

OK, if you're just looking for the compiled binaries. Try [this link](../sword-nixbuild-win64-20241018.tar.xz)
to get the resulting product. Drop me an email if you have any feedback on it. I haven't had much of a
chance to test things, so it's very possible some parts of it don't work. Give me a shout if that's the case.
