scripts/unit-test: Add meson support
Tested:
Converted sdeventplus to meson as a demo to make sure this works as
expected.
Change-Id: I5a518cf6e7d574468c4a6529780ec1d91e9bf7df
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/scripts/unit-test.py b/scripts/unit-test.py
index befc801..587488d 100755
--- a/scripts/unit-test.py
+++ b/scripts/unit-test.py
@@ -17,6 +17,7 @@
import re
import sets
import subprocess
+import shutil
import platform
@@ -292,6 +293,32 @@
return found_deps
+def get_meson_deps(pkgdir):
+ """
+ Parse the given 'meson.build' file for package dependencies and return
+ a list of the dependencies found. If the package is not meson compatible
+ it is just ignored.
+
+ Parameter descriptions:
+ pkgdir Directory where package source is located
+ """
+ meson_build = os.path.join(pkgdir, 'meson.build')
+ if not os.path.exists(meson_build):
+ return []
+
+ found_deps = []
+ for root, dirs, files in os.walk(pkgdir):
+ if 'meson.build' not in files:
+ continue
+ with open(os.path.join(root, 'meson.build'), 'rt') as f:
+ build_contents = f.read()
+ for match in re.finditer(r"dependency\('([^']*)'.*?\)\n", build_contents):
+ maybe_dep = DEPENDENCIES['PKG_CHECK_MODULES'].get(match.group(1))
+ if maybe_dep is not None:
+ found_deps.append(maybe_dep)
+
+ return found_deps
+
make_parallel = [
'make',
# Run enough jobs to saturate all the cpus
@@ -312,6 +339,27 @@
"""
return '--' + ('enable' if enabled else 'disable') + '-' + flag
+def mesonFeature(val):
+ """
+ Returns the meson flag which signifies the value
+
+ True is enabled which requires the feature.
+ False is disabled which disables the feature.
+ None is auto which autodetects the feature.
+
+ Parameters:
+ val The value being converted
+ """
+ if val is True:
+ return "enabled"
+ elif val is False:
+ return "disabled"
+ elif val is None:
+ return "auto"
+ else:
+ raise Exception("Bad meson feature value")
+
+
def build_and_install(pkg, build_for_testing=False):
"""
Builds and installs the package in the environment. Optionally
@@ -328,23 +376,42 @@
check_call_cmd(pkgdir, 'sudo', '-n', '--', 'ldconfig')
# Build & install this package
- conf_flags = [
- enFlag('silent-rules', False),
- enFlag('examples', build_for_testing),
- enFlag('tests', build_for_testing),
- enFlag('code-coverage', build_for_testing),
- enFlag('valgrind', build_for_testing),
- ]
- # Add any necessary configure flags for package
- if CONFIGURE_FLAGS.get(pkg) is not None:
- conf_flags.extend(CONFIGURE_FLAGS.get(pkg))
- for bootstrap in ['bootstrap.sh', 'bootstrap', 'autogen.sh']:
- if os.path.exists(bootstrap):
- check_call_cmd(pkgdir, './' + bootstrap)
- break
- check_call_cmd(pkgdir, './configure', *conf_flags)
- check_call_cmd(pkgdir, *make_parallel)
- check_call_cmd(pkgdir, 'sudo', '-n', '--', *(make_parallel + [ 'install' ]))
+ # Always try using meson first
+ if os.path.exists('meson.build'):
+ meson_flags = [
+ '-Db_colorout=never',
+ '-Dtests=' + mesonFeature(build_for_testing),
+ '-Dexamples=' + str(build_for_testing).lower(),
+ '-Db_coverage=' + str(build_for_testing).lower(),
+ ]
+ if MESON_FLAGS.get(pkg) is not None:
+ meson_flags.extend(MESON_FLAGS.get(pkg))
+ try:
+ check_call_cmd(pkgdir, 'meson', 'setup', '--reconfigure', 'build', *meson_flags)
+ except:
+ shutil.rmtree('build')
+ check_call_cmd(pkgdir, 'meson', 'setup', 'build', *meson_flags)
+ check_call_cmd(pkgdir, 'ninja', '-C', 'build')
+ check_call_cmd(pkgdir, 'sudo', '-n', '--', 'ninja', '-C', 'build', 'install')
+ # Assume we are autoconf otherwise
+ else:
+ conf_flags = [
+ enFlag('silent-rules', False),
+ enFlag('examples', build_for_testing),
+ enFlag('tests', build_for_testing),
+ enFlag('code-coverage', build_for_testing),
+ enFlag('valgrind', build_for_testing),
+ ]
+ # Add any necessary configure flags for package
+ if CONFIGURE_FLAGS.get(pkg) is not None:
+ conf_flags.extend(CONFIGURE_FLAGS.get(pkg))
+ for bootstrap in ['bootstrap.sh', 'bootstrap', 'autogen.sh']:
+ if os.path.exists(bootstrap):
+ check_call_cmd(pkgdir, './' + bootstrap)
+ break
+ check_call_cmd(pkgdir, './configure', *conf_flags)
+ check_call_cmd(pkgdir, *make_parallel)
+ check_call_cmd(pkgdir, 'sudo', '-n', '--', *(make_parallel + [ 'install' ]))
def build_dep_tree(pkg, pkgdir, dep_added, head, dep_tree=None):
"""
@@ -369,6 +436,7 @@
# Read out pkg dependencies
pkg_deps = []
pkg_deps += get_autoconf_deps(pkgdir)
+ pkg_deps += get_meson_deps(pkgdir)
for dep in sets.Set(pkg_deps):
if dep in cache:
@@ -507,6 +575,10 @@
'YAML_DIR=/usr/local/share/phosphor-dbus-yaml/yaml']
}
+ # MESON_FLAGS = [GIT REPO]:[MESON FLAGS]
+ MESON_FLAGS = {
+ }
+
# DEPENDENCIES = [MACRO]:[library/header]:[GIT REPO]
DEPENDENCIES = {
'AC_CHECK_LIB': {'mapper': 'phosphor-objmgr'},
@@ -570,8 +642,9 @@
CODE_SCAN_DIR = WORKSPACE + "/" + UNIT_TEST_PKG
check_call_cmd(WORKSPACE, "./format-code.sh", CODE_SCAN_DIR)
- # Automake
- if os.path.isfile(CODE_SCAN_DIR + "/configure.ac"):
+ # Automake and meson
+ if (os.path.isfile(CODE_SCAN_DIR + "/configure.ac") or
+ os.path.isfile(CODE_SCAN_DIR + '/meson.build')):
prev_umask = os.umask(000)
# Determine dependencies and add them
dep_added = dict()
@@ -598,9 +671,14 @@
os.chdir(top_dir)
# Run package unit tests
build_and_install(UNIT_TEST_PKG, True)
- run_unit_tests(top_dir)
- maybe_run_valgrind(top_dir)
- maybe_run_coverage(top_dir)
+ if os.path.isfile(CODE_SCAN_DIR + '/meson.build'):
+ check_call_cmd(top_dir, 'meson', 'test', '-C', 'build')
+ check_call_cmd(top_dir, 'ninja', '-C', 'build', 'coverage-html')
+ check_call_cmd(top_dir, 'meson', 'test', '-C', 'build', '--wrap', 'valgrind')
+ else:
+ run_unit_tests(top_dir)
+ maybe_run_valgrind(top_dir)
+ maybe_run_coverage(top_dir)
run_cppcheck(top_dir)
os.umask(prev_umask)