Sometimes it is not enough to handle dependencies on ::installed packages only through versions. This might be either due to ABI change or due to switch of compiler. To track that information we can tag installed packages with additional information that should mark dependency in ::installed repository as unsatisfied.
GHC do a pretty good optimizations that can span through several modules in stack. That may render installed libraries broken if one of its dependency (not necessary direct) changes. That's probably why GHC depends not only on package version but also on a special hash value which should change when something changes inside of library or in its dependencies that somehow got exposed outside.
It is a well known issue that GCC compiled C++ libraries are very fragile to compiler changes. Though run-time library slotting will ensure correct runtime-library interface there is a still issue for library-library interface. See https://gcc.gnu.org/wiki/Cxx11AbiCompatibility
As eternaleye pointed out there is also issue between those two packages.
17:10 < eternaleye> virkony: Oh, another possible use case for this: SBCL
17:11 < eternaleye> virkony: Whenever SBCL is rebuilt, it breaks the serialized images of stuff that was built with it, such as Maxima.
Supply installed packages with special tags with values that should match exactly for installed version and for dependency entry in dependant package.
- Allow tagging packages
::*->installed
with an arbitrary key-value tags. May follow approach of parts (expart()
). I.e. at some phase callextag cabal-hash $(get-cabal-hash)
(as suggest by eternaleye function might have namebuild-prop
, but I'd prefer something else) - It makes sense to allow value for tagging being calculated after build finishes to meet GHC requirements (package hash calculated during build process). But I see no reason for restricting it from being declared on an earlier phases.
- In packages that depends on tagged packages there should be a way to
declaring which tags should have their values being locked. Either globally
using something like
TAGS_TO_LOCK=(cabal-hash)
or individually for each dependency spec likedev-haskell/array[.BUILD_CABAL_HASH=(=)]
as suggested by eternaleye. - Package resolver should find prerequisites with unmet tag values and re-install those packages. Ideally whole graph of prerequisites should be checked.
- To handle leaf packages (the one installed directly) or situation when user
restrict analysis of dependencies to part of whole graph we may introduce a
bit more general variant of
cave fix-linkage
that will do that analysis for all installed packages (possibly restricted to specified "tag") and reinstall affected packages.
- Should at some phase (ex.
pkg_postinst
) tag installed package with cabal id (looks likehscolour-1.20.3-3dd6b7e3fe74da25e1b82da895332ef5
). Silly solution:
haskell_pkg_postinst() {
extag cabal-id $(sed -n 's/^id: //p' "${HASKELL_REGISTRATION}/register.sh")
# ... rest stuff ...
}
# Based on https://gcc.gnu.org/wiki/Cxx11AbiCompatibility
cxxabi_nm_all() {
find ${1:-.} -name '*.a' -exec $(exhost --tools-prefix)nm -f posix '{}' '+'
find ${1:-.} -name '*.so' -exec $(exhost --tools-prefix)nm -f posix -D '{}' '+'
}
cxxabi_compat() {
local symbol
while read symbol; do
case "$symbol" in
std::list*|std::_List_impl*|std::_List_base*) return 1 ;;
# other checks
esac
done
return 0
}
cxxabi_tag() {
if cxxabi_nm_all | cut -f1 -d' ' | sort -u | grep '^_Z' | c++filt | compat; then
extag cxxabi compat
else
extag cxxabi sha1-$(gcc --version | sha1sum | cut -f1 -d' ')
fi
}
- Since value of tag is known after build we cannot extend resolution graph
with dependant packages that will get broken dependencies. We can make hash
part of metadata in
.exheres-0
and for Haskell libraries be calculated as a hash ofDOWNLOADS
contents and hashes of files referenced inDEFAULT_SRC_PREPARE_PATCHES
. But as eternaleye noted this may cause suprious reinstalls.
- Alex Elsayed (eternaleye)
- Ciaran McCreesh (ciaranm)