hadrian
hadrian copied to clipboard
Explore novel ways to produce multi-target builds.
The iOS cross compiler1 needs to be able to target multiple architectures. And hence needs to build at least two cross compilers (one targeting arm
for the actual device, one i386
for the simulator). Hence maybe we can teach the build system to produce a multi backend compiler. The first step certainly would be to produce a proper wrapper script. As we are unlikely going to add this directly into ghc
right now.
One complication I see is that we would have to run multiple configure
passes, as autoconf
apparently cannot deal with multiple tool chains. Then, maybe if the tool chains are identical (think llvm
). Maybe that's not so much of an issue?
Just a note about multiple passes of configure
: if we do that in the same folder, modifying the same files, and need
some of these files during the build, then Shake will complain with a lint error.
Yes. I think running multiple configure passes should be avoided at all costs. And I'm not even certain that's a viable way. Currently though, that's what is required to get all the AC stuff right.
@angerman Can we make these two passes in different directories?
@angerman I'm not sure, but GHC is purely single-lib compiler. A lot was done in order to support multi-lib setup, but it's not there yet. So I would suggest to start with GHC first...
@kgardas I see two approaches here: one is the soft multi-arch targeting ghc, which basically is just one ghc for each arch under the hood, but tied together through a wrapper script that dispatched according to the requested arch. On the other hand full multi-arch support in GHC, which will likely take very long to get right, but would allow to maybe reuse type checker results (I'm not certain how much these change per target architecture); this would likely reduce compile times for multiple archs dramatically.
Can we make these two passes in different directories?
@snowleopard I think we should be able to. We could also just put the build artifacts into say .build-$host-$target
or something to separate them per architecture.
The preprocessing symbols will be different per host so sharing even hi wil be tricky.
I suppose it should be mentioned that this now exists https://ghc.haskell.org/trac/ghc/ticket/11470 :)
I've been mucking around with ghcjs the last few days, and have definitely felt the need for this. Instead of the wrapper approach, I'd propose experimenting with the Nix Haskell Infrastructure instead---basically because there is a need to manage multiple package database separately and that infrastructure is already battle tested for that / forking Cabal/Stack is way more work. Some things I can think of:
- Mirror builds across targets as @angerman mentions in the OP, of course.
- Build
Setup.hs
with native compiler, not cross compiler. I can't think of any good reason why this should be the case. - Maybe it's possible to "statically link" a compiler plugin to GHC---i.e. avoid run-time code loading? If this is easier than the long term ideal proposed here and in the linked issue, it would be trivial to get the Nix infrastructure to do it and not have it interfere with the normal package set/database.
Long term, I'm thinking more of the booting process should be exposed to users / offloaded to cabal/stack/nix infra. Other code has bootstrapping concerns concerns (e.g. testing tool depends on library being tested), which I hope is sufficient motivation for all these tools to first understand bootstrapping phases in isolation, and eventually tying the bootstrapping knot.
- Every publicly released compiler should double as a stage1 cross compiler (no TH support, etc) for all supported platforms.
- Simply building a plugin that can talk to some separate process (run with the iOS simulator, node.js, etc), should be enough to add stage2 capabilities for a given platform. [The user then effectively finishes the boot process as needed.] What @angerman proposed in the thread linked in the GHC issue, I believe.
- In order build that additional process, would be nice if e.g.
cabal/stack install base
with the stage1 compiler Just Worked™.
- In order build that additional process, would be nice if e.g.
- It should also be possible to install plugins that support additional back-ends (GHCJS, Clash). This means being careful about
hi
files` as @ndmitchell says. - Cabal should not be a boot library---this presumes non-cross-compilation, see number 2 above.
While everything down on my second list requires changes to GHC, it should be greatly aided by this :). Likewise, everything above can be done before tree-tremble, "testing the waters" as it were.
Here's what I've done so far: https://github.com/NixOS/nixpkgs/compare/master...Ericson2314:haskell-cross. Next step could be using nativeGhc
to build Setup.hs
.