[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

transition to gcc-7, ALI version updates



Hello.

The migration of most [α] Ada packages to gcc-7 to the testing
distribution should be completed in a few hours.

Thanks to all maintainers implied in this update.

You may be interested in what follows if you maintain a library.

The policy requires a change of the ALI version in the name of a -dev
binary package when the Ada source change (β).

The attached python script may be run after a successful build of your
source package. It attempts to automatically warn about such issues by
downloading a previous version of each -dev package, and comparing the
ALI checksums. If a package with the same ALI version is available
with different ALI checksums, it exits with a non-zero exit status.

If a -dev package requires a renaming, the attached map should help
finding its reverse dependencies.  Each node represents a source
package, and each arrow from A to B means that B mentions the ALI
version of A in its build, run-time or test dependencies.

Feel free to test and report any problem or suggestion.

[α] The only exception for now is blocked by a trivial, unrelated and
patched issue that I must admit I am fully responsible for :-).

(β) GNAT is granted an exception to spare a passage through the NEW
queue for all GCC packages. In other words, libgnat7-dev will *not*
change its name when it breaks all other Ada -dev packages.

Attachment: debian_ada_library_dependencies.pdf
Description: Adobe PDF document

#!/usr/bin/python3

# Each Ada -dev package must be renamed when a .ali file changes
# compared to the current version in unstable.

# This script should be executed in the source tree after a build.
# For each -dev package in the control file, it opens the freshly built .deb
# and searches for the directory containing the .ali files.
# If no such directory found, the package is ignored.
# If no package with the same name is available via apt-get, a warning
#   is displayed. The -dev package has probably already been renamed.
# Else, any difference is reported and the exit status is 1.

# It requires the python3-debian package.

# The gnat-BV binary, from the gcc-BV source, uses an unusual scheme
# for the Ada standard library, so it must be handled as a special case.

import os
import re
import subprocess
import sys
import tempfile
import debian.deb822
import debian.debfile

# Global constants

# I use pbuilder. Adapt to your needs.
# fresh_binary_dir = ".."
fresh_binary_dir = "/var/cache/pbuilder/result"

def output (args):
    return subprocess.run (args, check=True, stdout=subprocess.PIPE) \
        .stdout.rstrip ().decode ()

arch        = output (("dpkg-architecture", "-qDEB_HOST_ARCH"))
multiarch   = output (("dpkg-architecture", "-qDEB_HOST_MULTIARCH"))
deb_source  = output (("dpkg-parsechangelog", "-SSource"))
deb_version = output (("dpkg-parsechangelog", "-SVersion"))

exit_status = 0
def error (message):
    global exit_status
    print ("error: " + message)
    exit_status = 1

# Store all temp files in a common temp directory.
with tempfile.TemporaryDirectory () as tempdir:

    # Select 1 or 2 consecutive lines in ali_file matching pattern, then
    # extract the first subgroup of each one. Concatenate the results.
    def checksum (pattern, ali_file):
        previous = None
        for line in ali_file:
            match = re.match (pattern, line.decode ())
            if match:
                checksum = match.group (1)
                if previous:
                    return previous + checksum
                else:
                    previous = checksum
            elif previous:
                return previous
        assert False, "failed to parse a .ali file"

    def check_binary (package, ali_dir):
        global exit_status

        new_deb = package + "_" + deb_version + "_" + arch + ".deb"
        new = debian.debfile.DebFile (filename = fresh_binary_dir + "/" + new_deb)
        if new.data.has_file (ali_dir):
            # This test fails for non-Ada -dev packages.

            # Check if the package exists in unstable. "apt-get -t unstable" would
            # look in experimental when no match exists in unstable.
            aptitude = subprocess.run (("aptitude", "search", "-q",
                                        "?and(?exact-name(" + package + "),?archive(unstable))"))
            assert aptitude.returncode in (0, 1) # report normal errors
            if aptitude.returncode == 1:
                print ("Package {} not in unstable, assuming a new aliversion.".format (package))
            else:
                subprocess.run (("apt-get", "download", "-q", "-t", "unstable", package),
                                cwd = tempdir, check = True)
                for old_deb in os.listdir (tempdir):
                    if old_deb.startswith (package + "_") \
                       and old_deb.endswith ("_"  + arch + ".deb"):
                        break
                old = debian.debfile.DebFile (filename = tempdir + "/" + old_deb)
                print ("Comparing .ali files with {}.".format (new_deb))
                for ali in old.data:
                    match = re.fullmatch ("\./" + ali_dir + "/(.*)\.ali", ali)
                    if match:
                        if new.data.has_file (ali):
                            unit = match.group (1)
                            pattern = "D " + unit + "\.ad[bs][ \t]+([0-9]{14} [0-9a-f]{8}) "
                            old_cs = checksum (pattern, old.data.get_file (ali))
                            new_cs = checksum (pattern, new.data.get_file (ali))
                            if old_cs != new_cs:
                                error ("{} has changed.".format (unit))
                        else:
                            error ("{} is missing".format (unit))

    # Is the source package gcc-BV?
    match = re.fullmatch ("gcc-([0-9]+(?:\.[0-9]+)*)", deb_source)
    if match:
        BV = match.group (1)
        check_binary (package = "gnat-" + BV,
                      ali_dir = "usr/lib/gcc/" + multiarch + "/" + BV +  "/adalib")
        # The default behaviour below would only find libgnatvsnBV-dev,
        # spare many package extractions by hardcoding the result.
        check_binary (package = "libgnatvsn" + BV + "-dev",
                      ali_dir = "usr/lib/" + multiarch + "/ada/adalib/gnatvsn")
    else:
        with open ("debian/control") as control_file:
            paragraphs = debian.deb822.Deb822.iter_paragraphs (control_file)
            next (paragraphs)   # Skip source paragraph.
            for paragraph in paragraphs:
                package = paragraph ["Package"]
                match = re.fullmatch ("lib(.*[a-z])[0-9]+(?:\.[0-9]+)*-dev", package)
                if match:
                    library = match.group (1).replace ("-", "_")
                    check_binary (package = package,
                                  ali_dir = "usr/lib/" + multiarch + "/ada/adalib/" + library)

sys.exit (exit_status)

Reply to: