summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-04-21 14:22:06 +0200
committerDavid Robillard <d@drobilla.net>2019-04-21 14:22:06 +0200
commit9cd6048f6979e5c5880514eab1ef102874495b69 (patch)
tree60eb8d43b454b57f7340245ac8a21d2b077300a5
parent406f89271452fdb573c7e28113b1ed08ff2b4eda (diff)
downloadsuil-9cd6048f6979e5c5880514eab1ef102874495b69.tar.gz
suil-9cd6048f6979e5c5880514eab1ef102874495b69.tar.bz2
suil-9cd6048f6979e5c5880514eab1ef102874495b69.zip
Squashed 'waflib/' changes from e7a29b6..4f98e1c
4f98e1c Remove recursion hacks 27c5c93 Remove use_lib() b074a1e Support building against local header-only libraries 27a69a7 Add option to filter tests by regular expression ac29b74 Fix configuring with root prefix 6134be6 Print test coverage summary 6d7dd59 Don't attempt to clear coverage when coverage is disabled cddbcb5 Pass file comparison test if difflib finds no changes 6e4e92b Seek to end before checking the size of stderr output git-subtree-dir: waflib git-subtree-split: 4f98e1c2bed7beacf4d303e51f994fb932952f95
-rw-r--r--extras/autowaf.py127
1 files changed, 66 insertions, 61 deletions
diff --git a/extras/autowaf.py b/extras/autowaf.py
index 51077d1..870a69a 100644
--- a/extras/autowaf.py
+++ b/extras/autowaf.py
@@ -7,9 +7,6 @@ import time
from waflib import Configure, ConfigSet, Build, Context, Logs, Options, Utils
from waflib.TaskGen import feature, before, after
-global g_is_child
-g_is_child = False
-
NONEMPTY = -10
if sys.platform == 'win32':
@@ -93,6 +90,9 @@ def set_options(opt, debug_by_default=False):
test_opts.add_option('--wrapper', type='string',
dest='test_wrapper',
help='command prefix for tests (e.g. valgrind)')
+ test_opts.add_option('--test-filter', type='string',
+ dest='test_filter',
+ help='regular expression for tests to run')
# Run options
run_opts = opt.add_option_group('Run options')
@@ -171,7 +171,8 @@ def define(conf, var_name, value):
def check_pkg(conf, name, **args):
"Check for a package iff it hasn't been checked for yet"
- if args['uselib_store'].lower() in conf.env['AUTOWAF_LOCAL_LIBS']:
+ if (args['uselib_store'].lower() in conf.env['AUTOWAF_LOCAL_LIBS'] or
+ args['uselib_store'].lower() in conf.env['AUTOWAF_LOCAL_HEADERS']):
return
class CheckType:
@@ -450,26 +451,6 @@ def append_property(obj, key, val):
else:
setattr(obj, key, val)
-def use_lib(bld, obj, libs):
- abssrcdir = os.path.abspath('.')
- libs_list = libs.split()
- for l in libs_list:
- in_headers = l.lower() in bld.env['AUTOWAF_LOCAL_HEADERS']
- in_libs = l.lower() in bld.env['AUTOWAF_LOCAL_LIBS']
- if in_libs:
- append_property(obj, 'use', ' lib%s ' % l.lower())
- append_property(obj, 'framework', bld.env['FRAMEWORK_' + l])
- if in_headers or in_libs:
- if bld.env.MSVC_COMPILER:
- inc_flag = '/I' + os.path.join(abssrcdir, l.lower())
- else:
- inc_flag = '-iquote ' + os.path.join(abssrcdir, l.lower())
- for f in ['CFLAGS', 'CXXFLAGS']:
- if inc_flag not in bld.env[f]:
- bld.env.prepend_value(f, inc_flag)
- else:
- append_property(obj, 'uselib', ' ' + l)
-
@feature('c', 'cxx')
@before('apply_link')
def version_lib(self):
@@ -480,21 +461,34 @@ def version_lib(self):
if [x for x in applicable if x in self.features]:
self.target = self.target + 'D'
-def set_lib_env(conf, name, version):
+def set_lib_env(conf,
+ name,
+ version,
+ has_objects=True,
+ include_path=None,
+ lib_path=None):
"Set up environment for local library as if found via pkg-config."
NAME = name.upper()
major_ver = version.split('.')[0]
pkg_var_name = 'PKG_' + name.replace('-', '_') + '_' + major_ver
lib_name = '%s-%s' % (name, major_ver)
- lib_path = [str(conf.path.get_bld())]
+
+ if lib_path is None:
+ lib_path = str(conf.path.get_bld())
+
+ if include_path is None:
+ include_path = str(conf.path)
+
if conf.env.PARDEBUG:
lib_name += 'D'
+
conf.env[pkg_var_name] = lib_name
- conf.env['INCLUDES_' + NAME] = ['${INCLUDEDIR}/%s-%s' % (name, major_ver)]
- conf.env['LIBPATH_' + NAME] = lib_path
- conf.env['LIB_' + NAME] = [lib_name]
+ conf.env['INCLUDES_' + NAME] = [include_path]
+ conf.env['LIBPATH_' + NAME] = [lib_path]
+ if has_objects:
+ conf.env['LIB_' + NAME] = [lib_name]
- conf.run_env.append_unique(lib_path_name, lib_path)
+ conf.run_env.append_unique(lib_path_name, [lib_path])
conf.define(NAME + '_VERSION', version)
def display_msg(conf, msg, status=None, color=None):
@@ -521,14 +515,6 @@ def compile_flags(env, lib):
return ' '.join(map(lambda x: env['CPPPATH_ST'] % x,
env['INCLUDES_' + lib]))
-def set_recursive():
- global g_is_child
- g_is_child = True
-
-def is_child():
- global g_is_child
- return g_is_child
-
def build_pc(bld, name, version, version_suffix, libs, subst_dict={}):
"""Build a pkg-config file for a library.
@@ -539,7 +525,7 @@ def build_pc(bld, name, version, version_suffix, libs, subst_dict={}):
"""
pkg_prefix = bld.env['PREFIX']
- if pkg_prefix[-1] == '/':
+ if len(pkg_prefix) > 1 and pkg_prefix[-1] == '/':
pkg_prefix = pkg_prefix[:-1]
target = name.lower()
@@ -583,13 +569,6 @@ def build_pc(bld, name, version, version_suffix, libs, subst_dict={}):
obj.__dict__.update(subst_dict)
-def build_dir(name, subdir):
- if is_child():
- return os.path.join('build', name, subdir)
- else:
- return os.path.join('build', subdir)
-
-
def make_simple_dox(name):
"Clean up messy Doxygen documentation after it is built"
name = name.lower()
@@ -636,12 +615,8 @@ def build_dox(bld, name, version, srcdir, blddir, outdir='', versioned=True):
if not bld.env['DOCS']:
return
- # Doxygen paths in are relative to the doxygen file, not build directory
- if is_child():
- src_dir = os.path.join(srcdir, name.lower())
- else:
- src_dir = srcdir
-
+ # Doxygen paths in are relative to the doxygen file
+ src_dir = bld.path.srcpath()
subst_tg = bld(features='subst',
source='doc/reference.doxygen.in',
target='doc/reference.doxygen',
@@ -807,11 +782,15 @@ def show_diff(from_lines, to_lines, from_filename, to_filename):
import difflib
import sys
+ same = True
for line in difflib.unified_diff(
from_lines, to_lines,
fromfile=os.path.abspath(from_filename),
tofile=os.path.abspath(to_filename)):
sys.stderr.write(line)
+ same = False
+
+ return same
def test_file_equals(patha, pathb):
import filecmp
@@ -827,9 +806,7 @@ def test_file_equals(patha, pathb):
with io.open(patha, 'rU', encoding='utf-8') as fa:
with io.open(pathb, 'rU', encoding='utf-8') as fb:
- show_diff(fa.readlines(), fb.readlines(), patha, pathb)
-
- return False
+ return show_diff(fa.readlines(), fb.readlines(), patha, pathb)
def bench_time():
if hasattr(time, 'perf_counter'): # Added in Python 3.3
@@ -864,12 +841,26 @@ class TestScope:
self.n_total = 0
def run(self, test, **kwargs):
+ if type(test) == list and 'name' not in kwargs:
+ import pipes
+ kwargs['name'] = ' '.join(map(pipes.quote, test))
+
+ if Options.options.test_filter and 'name' in kwargs:
+ import re
+ found = False
+ for scope in self.tst.stack:
+ if re.search(Options.options.test_filter, scope.name):
+ found = True
+ break
+
+ if (not found and
+ not re.search(Options.options.test_filter, self.name) and
+ not re.search(Options.options.test_filter, kwargs['name'])):
+ return True
+
if callable(test):
output = self._run_callable(test, **kwargs)
elif type(test) == list:
- if 'name' not in kwargs:
- import pipes
- kwargs['name'] = ' '.join(map(pipes.quote, test))
output = self._run_command(test, **kwargs)
else:
@@ -888,9 +879,10 @@ class TestScope:
if 'stderr' in kwargs and kwargs['stderr'] == NONEMPTY:
# Run with a temp file for stderr and check that it is non-empty
import tempfile
- with tempfile.TemporaryFile(mode='w') as stderr:
+ with tempfile.TemporaryFile() as stderr:
kwargs['stderr'] = stderr
output = self.run(test, **kwargs)
+ stderr.seek(0, 2) # Seek to end
return (output if not output else
self.run(
lambda: stderr.tell() > 0,
@@ -991,7 +983,7 @@ class TestContext(Build.BuildContext):
Logs.info("Waf: Entering directory `%s'\n", bld_dir)
os.chdir(str(bld_dir))
- if str(node.parent) == Context.top_dir:
+ if not self.env.NO_COVERAGE and str(node.parent) == Context.top_dir:
self.clear_coverage()
self.log_good('=' * 10, 'Running %s tests', group_name)
@@ -1026,7 +1018,7 @@ class TestContext(Build.BuildContext):
self.gen_coverage()
if os.path.exists('coverage/index.html'):
- self.log_good('COVERAGE', '<file://%s>',
+ self.log_good('REPORT', '<file://%s>',
os.path.abspath('coverage/index.html'))
successes = scope.n_total - scope.n_failed
@@ -1098,6 +1090,19 @@ class TestContext(Build.BuildContext):
'cov.lcov'],
stdout=log, stderr=log)
+ summary = subprocess.check_output(
+ ['lcov', '--summary',
+ '--rc', 'lcov_branch_coverage=1',
+ 'cov.lcov'],
+ stderr=subprocess.STDOUT).decode('ascii')
+
+ import re
+ lines = re.search('lines\.*: (.*)%.*', summary).group(1)
+ functions = re.search('functions\.*: (.*)%.*', summary).group(1)
+ branches = re.search('branches\.*: (.*)%.*', summary).group(1)
+ self.log_good('COVERAGE', '%s%% lines, %s%% functions, %s%% branches',
+ lines, functions, branches)
+
except Exception:
Logs.warn('Failed to run lcov to generate coverage report')