Что означает «резервный вариант наследия» , когда кабал создает пакеты?

#haskell #build #cabal

Вопрос:

При использовании 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 
 

Ответ №1:

Я погрузился в исходный код. Здесь появляется сообщение об ошибке:

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

Поэтому я начал искать места, где ElabPackage это строится. Я нашел это:

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

Это, в свою очередь, используется здесь:

     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 это очень интересно, так как эта функция определяет, когда следует использовать устаревший запасной вариант. Это определено здесь:

         -- 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
 

Там, в коде прямо ниже, мы видим, что это может быть вызвано этими причинами:

  • Тип сборки является пользовательским или настраиваемым
  • Кабал-версия составляет менее 1,8
  • Здесь нет сборных компонентов
  • Вы передали --disable-per-component флаг.
  • Охват программы включен

Так что для appar библиотеки это связано с тем, что cabal-версия 1.6, которая ниже, чем 1.8, см. https://github.com/kazu-yamamoto/appar/blob/v0.1.8/appar.cabal#L10.