hadrian icon indicating copy to clipboard operation
hadrian copied to clipboard

Explore novel ways to produce multi-target builds.

Open angerman opened this issue 8 years ago • 9 comments

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?

angerman avatar Jan 17 '16 11:01 angerman

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.

snowleopard avatar Jan 17 '16 11:01 snowleopard

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 avatar Jan 17 '16 14:01 angerman

@angerman Can we make these two passes in different directories?

snowleopard avatar Jan 17 '16 16:01 snowleopard

@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 avatar Jan 17 '16 17:01 kgardas

@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.

angerman avatar Jan 18 '16 02:01 angerman

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.

angerman avatar Jan 18 '16 02:01 angerman

The preprocessing symbols will be different per host so sharing even hi wil be tricky.

ndmitchell avatar Jan 18 '16 06:01 ndmitchell

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:

  1. Mirror builds across targets as @angerman mentions in the OP, of course.
  2. Build Setup.hs with native compiler, not cross compiler. I can't think of any good reason why this should be the case.
  3. 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™.
  • 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.

Ericson2314 avatar Jan 23 '16 20:01 Ericson2314

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.

Ericson2314 avatar Jan 23 '16 22:01 Ericson2314