diff --git a/helpers/create-abi-dump.py b/helpers/create-abi-dump.py --- a/helpers/create-abi-dump.py +++ b/helpers/create-abi-dump.py @@ -1,20 +1,41 @@ #!/usr/bin/python3 -import os -import re +import argparse import logging +import os import pathlib -import argparse -import tempfile +import re import subprocess import sys +import tempfile +import yaml + from collections import defaultdict from typing import Dict, List, Union, Set -from helperslib import Packages, EnvironmentHandler +from helperslib import Buildable, CommonUtils +from helperslib import Packages, EnvironmentHandler, Settings # Make sure logging is ready to go #logging.basicConfig(level=logging.DEBUG) +ACCXMLTMPL = """{version} + + {headers} + + + {libs} + + + {skipIncludePaths} + + + {additionalIncludes} + + + {gccOptions} + +""" + def cmake_parser(lines: List) -> Dict: """A small cmake parser, if you search for a better solution think about using a proper one based on ply. @@ -102,9 +123,10 @@ # This class stores information on the library in question and assists in extracting information concerning it class Library: # Make sure we initialize everything we are going to need - def __init__(self, name: str) -> None: + def __init__(self, name: str, accSettings: Dict) -> None: # name of the library self.name = name # type: str + self.accSettings = accSettings # type: Dict # The raw cmake Parser output, available for debugging purposes # see cmake_parser function for the return value @@ -208,7 +230,10 @@ version = self.version headers = set() # type: Set[str] libs = set() # type: Set[str] - additionalIncludes = set() # type: Set[str] + skipIncludePaths = set(self.accSettings['skip_include_paths']) # type: Set[str] + additionalIncludes = set(self.accSettings['add_include_paths']) # type: Set[str] + gccOptions = set(self.accSettings['gcc_options']) # type: Set[str] + # list of general include directories prefixHeaders = [os.path.abspath(i) for i in buildEnvironment.get('CMAKE_PREFIX_PATH').split(":")] @@ -233,32 +258,24 @@ libs.add(target['path']) # Now we can go ahead and generate the XML file for abi-compliance-checker - xml = """ - {version} - - {headers} - - - {libs} - - - /usr/lib/python3.6/site-packages/utils/fake_libc_include - /usr/include/clang/AST - /usr/lib64/clang/6.0.1/include - - - {additionalIncludes} - /usr/lib64/qt5/mkspecs/linux-g++ - - """.format(version=version, headers="\n".join(headers), libs="\n".join(libs), additionalIncludes="\n".join(additionalIncludes)) # replace with f-String in Python 3.6 - + def _(l): + return "\n ".join(l) + + xml = ACCXMLTMPL.format(version=version, + headers=_(headers), + libs=_(libs), + additionalIncludes=_(additionalIncludes), + skipIncludePaths=_(skipIncludePaths), + gccOptions=_(gccOptions), + ) + # Write the generated XML out to a file to pass to abi-compliance-checker # We will give this to abi-compliance-checker using it's --dump parameter with open("{version}.xml".format(version=version),"w") as f: # replace with f-String in python 3.6 f.write(xml) # acc is compatible for C/C++ as Qt using C++11 and -fPic we need to set the gcc settings explitly - subprocess.check_call(["abi-compliance-checker", "-gcc-options", "-std=c++11 -fPIC", "-l", self.name, "--dump", f.name], env=runtimeEnvironment) + subprocess.check_call(["abi-compliance-checker", "--lang", "C++", "-l", self.name, "--dump", f.name], env=runtimeEnvironment) # Parse the command line arguments we've been given parser = argparse.ArgumentParser(description='Utility to create abi checker tarballs.') @@ -273,6 +290,21 @@ # Make sure we have an environment ready for executing commands buildEnvironment = EnvironmentHandler.generateFor( installPrefix=arguments.usingInstall ) +# Initialise the dependnecy resolver +resolver = Buildable.DependencyResolver() + +# Ask the resolver to load the list of projects... +projectsTreeLocation = os.path.join( CommonUtils.scriptsBaseDirectory(), 'repo-metadata', 'projects' ) +resolver.loadProjectsFromTree( projectsTreeLocation ) + +resolverProject = resolver.retrieveProject( arguments.project ) + +# get acc settings +localMetadataPath = os.path.join( CommonUtils.scriptsBaseDirectory(), 'local-metadata', 'abi-complience-checker.yaml' ) +localMetadata = yaml.load(open(localMetadataPath)) + +accSettings = Settings.settings(localMetadata, resolverProject.path, arguments.platform) + # Get ready to start searching for libraries foundLibraries = [] @@ -283,7 +315,7 @@ for line in log.readlines(): match = cmakeConfig.match(line) if match: - foundLibrary = Library( match.group(2) ) + foundLibrary = Library( match.group(2), accSettings ) foundLibraries.append(foundLibrary) # Initialize the archive manager diff --git a/helpers/helperslib/Settings.py b/helpers/helperslib/Settings.py new file mode 100644 --- /dev/null +++ b/helpers/helperslib/Settings.py @@ -0,0 +1,28 @@ +import fnmatch +import copy +from typing import Dict + +def settings(metadata: Dict, repopath: str, platform: str) -> Dict: + """returns a dictonary of settings for the repo and platform. + It starts with the dict taken from default and updates the dict for every fnmatching key. + For every matching key platform specific entries are searched. + """ + entries = [] + for key in metadata: + if fnmatch.fnmatch(repopath, key): + entries.append(key) + + # sorting all entries - the entries at the end overwrites the former settings + # len is efficient, but would fail if we have single letter repo names + entries.sort(key=len) + entries.insert(0, 'default') # add default settings at the start + + d = dict() + for entry in entries: + try: + content = metadata[entry] + d.update(content) + d.update(content[platform]) # try to load platform specific settings + except KeyError: + pass + return d diff --git a/local-metadata/abi-complience-checker.yaml b/local-metadata/abi-complience-checker.yaml new file mode 100644 --- /dev/null +++ b/local-metadata/abi-complience-checker.yaml @@ -0,0 +1,28 @@ +default: + gcc_options: + - "-std=c++11" + - "-fPIC" + skip_include_paths: + - /usr/lib/python3.6/site-packages/utils/fake_libc_include + - /usr/include/clang/AST + - /usr/lib64/clang/6.0.1/include + add_include_paths: + - /usr/lib64/qt5/mkspecs/linux-g++ +# "SUSEQt5.10": # special settings for one platform +# gcc_options: +# - something +# - nextsetting + +# "kde/*": # special settings for all repos in kde (fnmatch) +# add_include_paths: +# - special1 + +"kde/pim/akonadi-search": + gcc_options: + - "-std=c++11" + - "-fPIC" + - "-DQT_NO_KEYWORDS" +# "SUSEQt5.10": # or overwrite the setting for one specific platform +# gcc_options: +# - "-bla" +# - "-fasel"