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