On Tue, Aug 4, 2015 at 5:46 PM, Edward Z. Yang <
ezy...@mit.edu> wrote:
> What do you mean by the "inferred package list"? Surely you don't mean
> the -package-id flags which you passed to GHC? Do you mean the set of
> installed packages which GHC considers in scope? Do you actually just
> mean that you want to create a giant module graph of multiple packages
> for building? Or is it something more like you want to know given a
> module name where its hi file lives? (You can, TODAY, get all of this
> information from the GHC API.)
When you do --make, it will look at the imports, and figure out which
packages to link based on that. Of course, that means you don't have
an opportunity to select versions. I build a bunch of binaries from
the same source, so I just have a list of all the packages and
versions needed, and give that list to every binary. This works ok,
but is not so ideal since it's one giant global list for everyone, so
even a rarely built binary will contribute its heavy dependency to
every build. Or I could manually maintain a package list for every
binary separately, as cabal does, but that's annoying.
So if I could ask ghc about its inferred packages, I could then go
trim down the package list automatically.
This is also a lot like installing a cabal sandbox of consistent
versions, and then using --make to link in only the ones needed for a
particular binary.
> I think it would be most productive to talk about specific use-cases.
> I think hsc2hs is a good example. I think how people imagined hsc2hs
> would work is:
>
> 1. Your build system runs hsc2hs to generate some hs files
> (Cabal knows how to do this)
> 2. You then run ghc --make which slurps in the hs files
>
> So, in the normal case, there's no interleaving: you compile the hsc2hs
> C programs and run them, and then you compile the Haskell code. I'm
> curious to know what is going on in your setup that requires
> interleaving. Does the C program need to link against some Haskell
> libraries? (Surely not the libraries you are compiling?)
Well, I'm probably overstating the complexity of my situation. I just
mean that the actual compiling and preprocessing is interleaved just
due to them all being in the same dependency graph. E.g. a change in
a .h file will cause the .hsc that includes it to rebuild. Back when
I used make + ghc --make, there would be phase 1 which is compiling
C++ and hsc2hs in parallel, and then when that's all done, run a ghc
--make, which would then be single threaded, and then possibly a phase
3 which is running whatever tests I compiled, generating haddock,
running binaries to produce intermediate files, or whatever. Now that
I'm using shake, all those things happen in parallel and interleaved.
ghc --make also doesn't understand how to rebuild when things like
external configuration or library versions change. I think it can
basically figure out .hs dependencies and CPP #include dependencies
(presumably by virtue of check for recompilation post-CPP), but that's
about it.
If I had C generated from haskell and then linked back into haskell
then --make would get increasingly awkward as I'd have to stack more
phases on, but fortunately I'm not that bad yet :) The ability to
avoid the multiple-phase problem due to generated files was one of
shake's original selling points.
> More generally, it seems wrong for GHC to be used as a build system.
> You might *link* it as a library to your Haskell-based build system,
> but it not actually be in the business of building your Haskell and
> your Fortran and your CUDA and your...
Yeah, it does seem weird to use GHC to compile, say, C. But come to
think of it... it already kind of does that, doesn't it? Just in a
very basic way. Since building means doing lots of non-haskell stuff,
ghc --make won't be able to integrate with the rest of the system.
That's fine since you can use traditional 'ghc -c'... but meanwhile
ghc --make has nice features that you lose when you do that.
So how to get the nice features out of ghc --make so a larger system
can use them? Maybe dump the cache in some file which is really fast
to save and load? Or even a memcache kind of thing? Or keep ghcs
running persistently like my ghc-server attempt? Or, as you say, link
ghc in as a library to the shakefile so the cache can be passed around
in memory. In fact, this is probably already possible with the GHC
API. In practice it would just be another variant on ghc-server.
> At least in 7.10.1, -include-pkg-deps with -dep-suffix generates
> external deps for me. For example, here was a simple program:
>
> A.o-boot : A.hs-boot
> A.o-boot : Dev/ghc-7.10.1/usr/lib/ghc-7.10.1/base_I5BErHzyOm07EBNpKBEeUv/Prelude.hi
Hmm, I tried this again and it works now, I was probably just doing it
wrong. That's almost what I want... I'd rather have a package name,
but it could be parsed out of the path.
>> And maybe for those flags to have a
>> machine-readable stdout version, instead of wanting to modify a
>> Makefile.
>
> Sure, this is easy to do. Can you file a feature request? Propose a
> flag for it and the desired semantics.
Sure, done at
https://ghc.haskell.org/trac/ghc/ticket/10741
Maybe I should give this a try myself, I imagine I'd just have to see
what -M does, and make a simpler version of that.