~ruther/guix-cross-shells

70a2087d — Rutherther 2 days ago
docs: Add initial readme
4caa6773 — Rutherther 2 days ago
feat: Use inputs from bags in inputs-from
ab27b347 — Rutherther 2 days ago
chore: add example with u-boot cross profile

refs

master
browse  log 

clone

read-only
https://git.ditigal.xyz/~ruther/guix-cross-shells
read/write
git@git.ditigal.xyz:~ruther/guix-cross-shells

You can also use your local clone with git send-email.

#cross-shells - get a cross compilation environment in your guix shell!

One problem I have been facing with Guix, as opposed to Nix, is using shells for cross compilation. The problem with Guix in this regard is that Guix doesn't really expose easy ways to have a shell with native and target inputs. (and not just shells! I cannot find a good way to say compile this natively, and cross compile something else. I utilized this a lot on Nix where I deployed the system mostly natively compiled, since there were substitutes, but when I had something custom, I cross compiled it to save time. With guix this is easier as guix makes cross compiled substitutes available as well). Moreover even though you can use cross-gcc and cross-libc, it is not easy to just tell Guix to give you development inputs of a package in Guix for a different target. There seems to be a procedure that is supposed to somewhat take care of this, 'package->development-maifest', but this procedure doesn't really do everything necessary. First of all, even if target is supplied, for whatever reason the inputs you get aren't cross compiled for the target system, and secondly, there aren't search paths necessary for the build. Maybe this is a bug that ought to be solved. When I began thinking of this idea, my skills definitely weren't enough for that and I had to iteratively make my initial ideas work.

Apart from this issue there is, in my opinion, also another deeper issue of having all the binaries and libraries for the target system in the same place as the native libraries, if one used a profile and put both the types in the profile itself. This complicates the case when you would need to compile something natively during a build. When I am dveloping for embedded systems, I sometimes need to compile something natively in the same environment. For example some tests can be made run natively, no need to cross compile. Switching shells isn't something that one would like to do for that.

#Solution

With these limitations in mind, I came up with a solution and implemented a proof of concept of this solution. That is to say it might still be evolving in the future, it is definitely not complete.

The idea was to make sort of a profile-like functionality, but instead of making something completely new, since all the hard work for profiles has already been done, I decided to implement a way to just take this profile and make a package out of it. This package is just a union of build inputs, target inputs and host inputs. The target and host inputs are put to a subfolder #$output/cross/{target}/{name}, while the build inputs are directly in #$output. Additionally search-paths of target and host inputs are taken, the prefix cross/{target}/{name} is appended, and put to native-search-paths, as the search paths now make sense for this package 'natively'.

The splitting of the host inputs to a different folder, it is possible to have the same libraries natively and for the target system. Additionally it could be possible to use multiple cross shells at once in the future, but this would probably require wrapping instead of relying on search paths.

There is cross-profile record that has these fields: native-inputs, inputs, target-inputs, inputs-from. inputs-from are probably the most interesting. This is a list of packages, and their inputs are taken as inputs of the cross-profile. So that if you want to compile bash, you just put bash to inputs-from, sort of like package->development-manifest, but for cross compilation.

To overcome the limitation where it is not easy to say to cross compile a package, I made a new record that I call 'cross-package-job', and I just made a gexp compiler for it that calls 'package->cross-derivation'. Please do let me know if there is already a way to make a cross derivation in gexps in Guix and I just missed it.

#Example

Here is an example for an environment to compile bash for aarch64-linux-gnu

(define profile
  (cross-profile
  (target-system "aarch64-linux-gnu")
  (inputs-from (list bash))))

(define profile-package (make-cross-profile-package
 profile)) ; this makes the package that you put to profile

The idea is then to take this package and put it to a regular guix shell.

Do not follow this link