haskell.nix icon indicating copy to clipboard operation
haskell.nix copied to clipboard

Make "Lazy Cross-Compiling" Easy Somehow

Open TravisWhitaker opened this issue 2 years ago • 4 comments

The NixOS wiki documents this neat trick for cross-compiling an individual package without having to worry about whether or not its dependencies may be cross-compiled. The trick is to use an overlay on your cross-targeted package set to grab the package of interest's dependencies from the native package set for your target arch (so this wouldn't work at all for Windows, but would work great for Linux aarch64).

It would be nice to have some function in haskell-nix like crossDevFor "aarch64-multiplatform" x that gives me the the cross toolchain targeting aarch64-linux, but all of x's dependencies from the native aarch64-linux package set.

TravisWhitaker avatar Jan 26 '22 21:01 TravisWhitaker

Sorry for being late to this. Can you help me understand the motivation for this?

angerman avatar Mar 12 '22 12:03 angerman

Suppose I'm responsible for developing package A, which depends on package B. I have an x86 machine but I'm deploying A to aarch64. I want to be able to cross-build A so I can easily deploy it from my x86 machine to an aarch64 machine, but I don't particularly care if B can be cross-built, since I'm not responsible for package B, I just depend on it.

Currently, if I want to be able to cross-build A, I must cross-build B too (since all of the target platform's packages from pkgsCross.* are cross-built by construction). The trick documented in the wiki allows me (at the expense of loads of boilerplate and manual dependency chasing) to cross-build A, but link it against a natively-built B. The practical effect is that I can cross-build A even if B would fail to cross-build for one reason or another. In the current state of the world without this trick, I must patch B myself to make it cross-build if I want to cross-build A.

This trick would save a lot of work because, for better or for worse, most Haskell package developers (and indeed most Linux userspace software developers in general) don't seem to care whether or not their software supports cross compilation. The effect is that developers who depend on cross compilation end up spending a lot of time patching things from the closure of their dependencies to fix cross compilation problems (at the very least I've found myself spending a lot of time doing such work). In practice I really only care if the software I'm actively developing may be cross compiled, and I'd be happy to use the natively-built code for all of my dependencies. Making it easy to arrange things in such a way would save the work of patching the whole universe to fix cross compilation bugs.

TravisWhitaker avatar May 19 '22 18:05 TravisWhitaker

I guess this would be similar to what happens if we are compiling with GHCJS and a package relies on a C library that we don't have an alternative for (although in most cases now we can compile with emscripten). In some cases it is enough to point at the buildPackages version of the package. So we wind up adding something like:

somehaskellpackage.cabal

...
library
  extra-libraries: somecpackage

We can add a modules arg like this:

modules = [{pkgs, ...}: {
  packages.somehaskellpackage.components.library.libs = lib.mkForce [ pkgs.buildPackages.somecpackage ];
}];

This causes the build to use pkgs.buildPackages.somecpackage instead of pkgs.somecpackage. It should work for pkgconfig-depends as well like this:

modules = [{pkgs, ...}: {
  packages.somehaskellpackage.components.pkgconfig = lib.mkForce [ pkgs.buildPackages.somecpackage ];
}];

Is that the sort of thing you need?

hamishmack avatar May 24 '22 03:05 hamishmack

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Sep 28 '22 14:09 stale[bot]