159 lines
6.6 KiB
Markdown
159 lines
6.6 KiB
Markdown
---
|
||
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.
|