~ruther/guix-cross-shells

70a2087d244f757bec823f67380f9d46a0e8d915 — Rutherther 2 days ago 4caa677 master
docs: Add initial readme
1 files changed, 83 insertions(+), 0 deletions(-)

A README.md
A README.md => README.md +83 -0
@@ 0,0 1,83 @@
# 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