Skip to content

Instantly share code, notes, and snippets.

@ony
Last active August 29, 2015 14:23
Show Gist options
  • Save ony/17ef2294818601e001f9 to your computer and use it in GitHub Desktop.
Save ony/17ef2294818601e001f9 to your computer and use it in GitHub Desktop.
Arbitrary build tags for Exherbo

Background

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 (Haskell) packages

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.

GCC C++ ABI incompatibility

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

SBCL and Maxima

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.

Proposal

Supply installed packages with special tags with values that should match exactly for installed version and for dependency entry in dependant package.

Paludis support

  • Allow tagging packages ::*->installed with an arbitrary key-value tags. May follow approach of parts (expart()). I.e. at some phase call extag cabal-hash $(get-cabal-hash) (as suggest by eternaleye function might have name build-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 like dev-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.

haskell.exlib support

  • Should at some phase (ex. pkg_postinst) tag installed package with cabal id (looks like hscolour-1.20.3-3dd6b7e3fe74da25e1b82da895332ef5). Silly solution:
        haskell_pkg_postinst() {
            extag cabal-id $(sed -n 's/^id: //p' "${HASKELL_REGISTRATION}/register.sh")
            # ... rest stuff ...
        }

cxxabi.exlib (just an example)

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

Drawbacks and possible mitigations

  • 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 of DOWNLOADS contents and hashes of files referenced in DEFAULT_SRC_PREPARE_PATCHES. But as eternaleye noted this may cause suprious reinstalls.

Credits

  • Alex Elsayed (eternaleye)
  • Ciaran McCreesh (ciaranm)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment