When using cabal to build a Haskell package, it appears to mark some packages as legacy fallback:
$ cabal build
Resolving dependencies...
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
 - appar-0.1.8 (lib:appar) (requires build)
 - auto-update-0.1.6 (lib) (requires build)
 - base-compat-0.11.2 (lib) (requires build)
...
Building     base-orphans-0.8.4 (lib)
Building     appar-0.1.8 (all, legacy fallback)
Downloaded   memory-0.16.0
Downloading  cryptonite-0.29
Installing   base-orphans-0.8.4 (lib)
Downloaded   cryptonite-0.29
Downloading  some-1.0.3
...
You can see that for some libraries, they are specifically marked (lib), but other libraries are marked (all, legacy fallback).
What is the difference between these?  What does legacy fallback mean?
I am using cabal-install version 3.4.0.0:
$ cabal --version
cabal-install version 3.4.0.0
compiled using version 3.4.0.0 of the Cabal library 
I took a dive in the source code. The error message comes form here:
    dispname = case elabPkgOrComp pkg of
        ElabPackage _ -> prettyShow pkgid
            ++ " (all, legacy fallback)"
        ElabComponent comp -> prettyShow pkgid
            ++ " (" ++ maybe "custom" prettyShow (compComponentName comp) ++ ")"
So I started looking for places where ElabPackage is constructed. I found this:
    elaborateSolverToPackage
        ...
      where
        ...
        elab1 = elab0 {
                elabUnitId = newSimpleUnitId pkgInstalledId,
                elabComponentId = pkgInstalledId,
                elabLinkedInstantiatedWith = Map.empty,
                elabPkgOrComp = ElabPackage $ ElaboratedPackage {..},
                elabModuleShape = modShape
            }
This in turn is used here:
    elaborateSolverToComponents mapDep spkg@(SolverPackage _ _ _ deps0 exe_deps0)
        = case mkComponentsGraph (elabEnabledSpec elab0) pd of
           Right g -> do
            ...
            let not_per_component_reasons = why_not_per_component src_comps
            if null not_per_component_reasons
                then return comps
                else do checkPerPackageOk comps not_per_component_reasons
                        return [elaborateSolverToPackage spkg g $
                                comps ++ maybeToList setupComponent]
Now the why_not_per_component is very interesting as that function determines when to use the legacy fallback. It is defined here:
        -- You are eligible to per-component build if this list is empty
        why_not_per_component g
            = cuz_buildtype ++ cuz_spec ++ cuz_length ++ cuz_flag ++ cuz_coverage
There in the code right below that we can see that it can be caused by these reasons:
--disable-per-component flag.So for the appar library it is because the cabal-version is 1.6 which is lower than 1.8, see https://github.com/kazu-yamamoto/appar/blob/v0.1.8/appar.cabal#L10.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With