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 CommonUtils, ToolingSettings
from helperslib import Packages, EnvironmentHandler
# 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)
+ # acc is compatible for C/C++ (but --lang C++ doesn't remove the warning about C++ only settings).
+ 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,13 @@
# Make sure we have an environment ready for executing commands
buildEnvironment = EnvironmentHandler.generateFor( installPrefix=arguments.usingInstall )
+
+# get acc settings
+localMetadataPath = os.path.join( CommonUtils.scriptsBaseDirectory(), 'local-metadata', 'abi-compliance-checker.yaml' )
+
+accSettings = ToolingSettings.Loader( arguments.project, arguments.platform )
+accSettings.loadSpecificationFile( localMetadataPath )
+
# Get ready to start searching for libraries
foundLibraries = []
@@ -283,7 +307,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
@@ -333,7 +357,7 @@
ourArchive.storePackage(packageName, fileName, scmRevision, extraMetadata)
except subprocess.CalledProcessError as e:
retval = e.returncode
- logging.error("abi-complience-checker exited with {retval}".format(retval=retval))
+ logging.error("abi-compliance-checker exited with {retval}".format(retval=retval))
# We had an issue with one of the ABIs
if retval != 0:
diff --git a/helpers/helperslib/ToolingSettings.py b/helpers/helperslib/ToolingSettings.py
new file mode 100644
--- /dev/null
+++ b/helpers/helperslib/ToolingSettings.py
@@ -0,0 +1,66 @@
+import fnmatch
+import copy
+import os
+import yaml
+
+from typing import Dict, Union, List
+
+from helperslib import Buildable, CommonUtils
+
+# Class to make it convenient to read configs for working with settings for tooling
+class Loader(object):
+
+ def __init__(self, project: str, platform: str) -> None:
+
+ self.project = project
+ self.platform = platform
+ self.config = dict()
+
+ # Initialise the dependnecy resolver
+ self.resolver = Buildable.DependencyResolver()
+
+ # Ask the resolver to load the list of projects...
+ projectsTreeLocation = os.path.join( CommonUtils.scriptsBaseDirectory(), 'repo-metadata', 'projects' )
+ self.resolver.loadProjectsFromTree( projectsTreeLocation )
+
+ self.resolverProject = self.resolver.retrieveProject( project )
+
+ # Allow fetching our config
+ def __getitem__(self, name: str) -> Union[List, str, Dict]:
+ # Do we know about this attribute?
+ if name in self.config:
+ # Then return it
+ return self.config[name]
+
+ # We don't know about it
+ raise KeyError
+
+ # Load the given specification file
+ def loadSpecificationFile(self, configFileLocation: str):
+ # Does the file exist?
+ # If it does not, then we don't need to do anything else
+ if not os.path.isfile( configFileLocation ):
+ return
+
+ # Load the file now
+ with open( configFileLocation, 'r' ) as configFile:
+ # Parse the YAML file
+ projectConfig = yaml.load( configFile )
+
+ entries = []
+ for key in projectConfig:
+ if fnmatch.fnmatch( self.resolverProject.path, 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 )
+
+ self.config = dict()
+ for entry in entries:
+ content = projectConfig[entry]
+ try:
+ self.config.update( content['general'] )
+ self.config.update( content[self.platform] ) # try to load platform specific settings
+ except KeyError:
+ pass
diff --git a/local-metadata/abi-compliance-checker.yaml b/local-metadata/abi-compliance-checker.yaml
new file mode 100644
--- /dev/null
+++ b/local-metadata/abi-compliance-checker.yaml
@@ -0,0 +1,40 @@
+# This file is used to specify the builds of abi-compliance-checker.
+# So far following settings are used:
+#
+# - gcc_options:
+# specify the gcc options to build of headers
+#
+# - skip_include_paths:
+# list pf paths to exclude from searching for headers
+#
+# - add_include_paths:
+# list of paths to search for headers
+#
+# for more information about the settings: abi-compliance-checker --info
+"*":
+ general:
+ 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)
+# general:
+# add_include_paths:
+# - special1
+
+"kde/pim/akonadi-search":
+ general:
+ gcc_options:
+ - "-std=c++11"
+ - "-fPIC"
+ - "-DQT_NO_KEYWORDS"