haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.57k stars 676 forks source link

Add support for logging handles in the Cabal library #9987

Open sheaf opened 3 weeks ago

sheaf commented 3 weeks ago

Users of the Cabal library API should be able to choose where Cabal output should be sent to.

In cabal-install, we currently achieve this by using --act-as-setup (see Distribution.Client.SetupWrapper.selfExecSetupMethod): we spawn a separate process through which we run the Cabal library functions, using Distribution.Client.SetupWrapper.invoke:

  let loggingHandle = case useLoggingHandle options of
        Nothing -> Inherit
        Just hdl -> UseHandle hdl
      cp =
        (proc path args)
          { Process.cwd = fmap getSymbolicPath $ useWorkingDir options
          , Process.env = env
          , Process.std_out = loggingHandle
          , Process.std_err = loggingHandle
          , Process.delegate_ctlc = isInteractive options
          }
  maybeExit $ rawSystemProc verbosity cp

As you can see here, there are three pieces of process-global state involved:

(NB: there is also "Delegate Ctrl+C", but that is really needed for Setup repl, and directly calling the Cabal repl library function will provide the correct behaviour, so we don't need to concern ourselves about that.)

This means we need to make the Cabal library able to choose where to redirect all logging output.

The proposed change in this ticket is to modify Verbosity to store an optional logging handle. This seems natural: any time we log output we have to consult the Verbosity to decide whether to log, so it would make sense to also have it inform us about where to log.

The main subtlety, as far as I can see, is that we will have to ensure that all process invocations within the Cabal library also set the logging handle of spawned processes, as this will no longer be done automatically through inheritance of process-global state. This step is necessary to ensure that e.g. GHC output continues to be redirected properly to the logging handle.

As a result of this change, we will be able to entirely remove the self-exec setup method in Distribution.Client.SetupWrapper. The only remaining setup methods would be: