Directly call in-library functions to build packages#11703
Directly call in-library functions to build packages#11703sheaf wants to merge 4 commits intohaskell:masterfrom
Conversation
cff8372 to
0a2b46e
Compare
d100f9c to
72c1495
Compare
|
I now consider this patch ready for review. Significant changes since #9871:
I still need to check stackage compilation. With the changes in (1) implemented, I am now significantly more confident that we are not changing behaviour. |
geekosaur
left a comment
There was a problem hiding this comment.
I think that, despite not intending to change behavior, this probably warrants a changelog entry marked significant.
72c1495 to
43fd73b
Compare
I've written a changelog entry now, please let me know what you think! |
This commit adds 'Structured' instances for the 'RuleCommands' and 'RuleData' datatypes. This allows us to serialise and deserialise them, which allows us to compute which rules have changed across builds. This is necessary for recompilation checking for pre-build rules.
This commit adds recompilation logic for SetupHooks pre-build rules.
This implements the behaviour described in the SetupHooks API. That is,
a rule is considered stale if:
[N] The rule is new, or
[S1] A dependency of the rule is stale. That is, either we have
re-run another rule that this rule depends on, or one of the
file inputs to the rule is newer than the oldest output of the
rule (or the rule output doesn't exist at all), or
[S2] The rule itself has changed, e.g. the parameters stored in
RuleData have changed.
Fixes haskell#11730
afeb1b3 to
4cc4945
Compare
|
I have successfully built all of I will instrument this version of |
|
I have spent this morning diffing the output of
I also found a harmless minor inconsistency in I've attached dumps of the |
4cc4945 to
29f2db4
Compare
29f2db4 to
bb4ba48
Compare
bb4ba48 to
7a05966
Compare
|
I believe I've addressed everything. I would appreciate a review on #11731 so that I can land that first; that's a self-contained change to recompilation checking for |
| Just hWrite -> | ||
| case hooksExeArgs of | ||
| hookName : _ -> | ||
| case lookup hookName allHookHandlers of |
There was a problem hiding this comment.
Maybe 5 nested case ... of is a lot? :)
I haven't tested it, but I hope it works.
hooksMain :: SetupHooks -> IO ()
hooksMain setupHooks = do
(inputFd, outputFd, hookName) <- getArgs >>= \case
(i : o : n : _) -> pure (i, o, n)
(_ : _ : []) -> dieWithException hooksExeVerbosity NoHookType
_ -> dieWithException hooksExeVerbosity (NoHandle Nothing)
hRead <- (readMaybe inputFd >>= openCommunicationHandleRead)
>>= justOrDie (dieWithException hooksExeVerbosity (NoHandle $ Just $ "hook input communication handle '" ++ inputFd ++ "'"))
hWrite <- (readMaybe outputFd >>= openCommunicationHandleWrite)
>>= justOrDie (dieWithException hooksExeVerbosity (NoHandle $ Just $ "hook output communication handle '" ++ outputFd ++ "'"))
handleAction <- (lookup hookName allHookHandlers)
`justOrDie` (dieWithException hooksExeVerbosity (BadHooksExeArgs hookName (UnknownHookType (map fst allHookHandlers))))
handleAction (hRead, hWrite) setupHooks
where
justOrDie :: IO a -> Maybe a -> IO a
justOrDie die = maybe die pure
allHookHandlers = [(hookName h, hookHandler h) | h <- hookHandlers]30c4250 to
7aee7a3
Compare
This architectural change ensures that we build packages using Cabal library functions (using a Haskell library interface) instead of going via the command-line interface of Setup.hs, as much as possible. The main changes are in SetupWrapper: the old InternalMethod becomes LibraryMethod, which builds the package by calling Cabal library functions. This is used to build all packages unless build-type: Custom or there is a Cabal library version mismatch which requires us to fall back to compiling Setup.hs and running that. The SelfExec method as well as forceExternalSetupMethod are removed: they no longer have any purpose, as builds can now be carried out concurrently thanks to 7b90583 and edb808a. This change required a bit of GADT trickery to accomodate the fact that configure returns a LocalBuildInfo which must then be passed to subsequent phases, while with the old Setup interface everything returns `IO ()` and communication is done through the filesystem (the local build info file). The new Distribution.Client.InLibrary module contains all the necessary framework for taking information that cabal-install has and invoking Cabal library functions to perform the appropriate action (configure, build, test, bench, ...). Most of these are pretty simple; the main difficulty is with configure as we need to jump to the part of the Cabal configure code that continues after figuring out information about the system (e.g. compiler information, dependency information determined by the solver), to avoid wasting work with Cabal rediscovering things that cabal-install already knows. This required a bit of refactoring in Distribution.Simple.Configure. Packages with 'build-type: Hooks' are now compiled with the in-library method (instead of going via Setup.hs). This is achieved as follows: - The Cabal library provides 'Distribution.Simple.SetupHooks.HooksMain', which exposes `hooksMain :: SetupHooks -> IO ()`. This allows us to turn any definition of `SetupHooks` into an external hooks executable. - The new `hooks-exe` library, which `cabal-install` depends on, provides the logic for communicating with the external hooks executable (using the `CommunicationHandle` functionality from haskell/process#308). This change has been extensively tested by compiling clc-stackage and diffing the differences in LocalBuildInfo (i.e. the output of the configure step).
7aee7a3 to
89448e8
Compare


This is a rebase of #9871. I had to create a new PR as Matthew is no longer active (and that PR was made from his personal fork).
Template B: This PR does not modify behaviour or interface.
This is a major refactoring in how
cabal-installworks, with a few knock-on internal changes to someCaballibrary functionality.It should not cause any breakage for users (I tested
clc-stackageand it all builds unchanged with this branch).This PR modifies
cabal-installto directly go through theCaballibrary when building packages, instead of theSetupinterface (except of course forbuild-type: Custompackages).In particular, to build a package with
build-type: Hooks,cabal-installwill compile the package'sSetupHooksfile into an external hooks executable using the newhooks-exepackage. All hooked operations are then performed by communicating with this external executable, instead of going through an opaqueSetupexecutable. Thehooks-exepackage provides both functionality for compiling an external hooks executable and for interfacing with it. This makes use of theCommunicationHandleAPI that I added toprocess.The main change is to
SetupWrapper: the oldInternalMethodbecomesLibraryMethod, which builds the package by callingCaballibrary functions. This is used to build all packages unlessbuild-type: Customor there is aCaballibrary version mismatch which requires us to fall back to compilingSetup.hsand running that. TheSelfExecmethod as well asforceExternalSetupMethodare removed: they no longer have any purpose, as builds can now be carried out concurrently thanks to 7b90583 and edb808a.The new
Distribution.Client.InLibrarymodule contains all the necessary framework for taking information thatcabal-installhas and invokingCaballibrary functions to perform the appropriate action (configure,build,test,bench, ...). Most of these are pretty simple; the main difficulty is withconfigureas we need to jump to the part of theCabalconfigure code that continues after figuring out information about the system (e.g. compiler information), to avoid wasting work withCabalrediscovering things thatcabal-installalready knows. This required a bit of refactoring inDistribution.Simple.Configure.TODO:
clc-stackageand update the PR description accordingly.