当 cabal 正在构建包时,"legacy fallback" 是什么意思?

What does "legacy fallback" mean when cabal is building packages?

当使用 cabal 构建 Haskell 包时,它似乎将某些包标记为 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
...

可以看到有的库是专门标示(lib)的,而有的库标示为(all, legacy fallback).

这些有什么区别? legacy fallback 是什么意思?


我正在使用 cabal-install 版本 3.4.0.0:

$ cabal --version
cabal-install version 3.4.0.0
compiled using version 3.4.0.0 of the Cabal library 

我深入研究了源代码。错误消息来自 here:

    dispname = case elabPkgOrComp pkg of
        ElabPackage _ -> prettyShow pkgid
            ++ " (all, legacy fallback)"
        ElabComponent comp -> prettyShow pkgid
            ++ " (" ++ maybe "custom" prettyShow (compComponentName comp) ++ ")"

所以我开始寻找建造ElabPackage的地方。我发现 this:

    elaborateSolverToPackage
        ...
      where
        ...
        elab1 = elab0 {
                elabUnitId = newSimpleUnitId pkgInstalledId,
                elabComponentId = pkgInstalledId,
                elabLinkedInstantiatedWith = Map.empty,
                elabPkgOrComp = ElabPackage $ ElaboratedPackage {..},
                elabModuleShape = modShape
            }

依次使用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]

现在 why_not_per_component 非常有趣,因为该函数决定了何时使用遗留回退。它被定义为 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

在下面的代码中,我们可以看到它可能是由以下原因引起的:

  • 构建类型是自定义或配置
  • cabal-version 小于 1.8
  • 没有可构建的组件
  • 您通过了 --disable-per-component 标志。
  • 程序覆盖已启用

所以对于 appar 库是因为 cabal-version 是 1.6,低于 1.8,参见 https://github.com/kazu-yamamoto/appar/blob/v0.1.8/appar.cabal#L10