docs: Add initial readme
feat: Use inputs from bags in inputs-from
chore: add example with u-boot cross profile
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.
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.
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.