Skip to content

Commit 4482556

Browse files
Qinghao ShiQinghao Shi
Qinghao Shi
authored and
Qinghao Shi
committed
TOOLS: enable build greentea test with gcov options
1 parent 71c6b9a commit 4482556

File tree

5 files changed

+57
-13
lines changed

5 files changed

+57
-13
lines changed

tools/build_api.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ def target_supports_toolchain(target, toolchain_name):
437437
def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
438438
macros=None, clean=False, jobs=1,
439439
notify=None, config=None, app_config=None,
440-
build_profile=None, ignore=None):
440+
build_profile=None, ignore=None, coverage_patterns=None):
441441
""" Prepares resource related objects - toolchain, target, config
442442
443443
Positional arguments:
@@ -477,6 +477,9 @@ def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
477477
target.default_toolchain = "uARM"
478478
toolchain_name = selected_toolchain_name
479479

480+
if coverage_patterns:
481+
target.extra_labels.append(u'COVERAGE')
482+
480483
try:
481484
cur_tc = TOOLCHAIN_CLASSES[toolchain_name]
482485
except KeyError:
@@ -488,7 +491,7 @@ def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
488491
profile[key].extend(contents[toolchain_name].get(key, []))
489492

490493
toolchain = cur_tc(
491-
target, notify, macros, build_dir=build_dir, build_profile=profile)
494+
target, notify, macros, build_dir=build_dir, build_profile=profile, coverage_patterns=coverage_patterns)
492495

493496
toolchain.config = config
494497
toolchain.jobs = jobs
@@ -511,7 +514,7 @@ def build_project(src_paths, build_path, target, toolchain_name,
511514
report=None, properties=None, project_id=None,
512515
project_description=None, config=None,
513516
app_config=None, build_profile=None, stats_depth=None,
514-
ignore=None, resource_filter=None):
517+
ignore=None, resource_filter=None, coverage_patterns=None):
515518
""" Build a project. A project may be a test or a user program.
516519
517520
Positional arguments:
@@ -556,7 +559,7 @@ def build_project(src_paths, build_path, target, toolchain_name,
556559
toolchain = prepare_toolchain(
557560
src_paths, build_path, target, toolchain_name, macros=macros,
558561
clean=clean, jobs=jobs, notify=notify, config=config,
559-
app_config=app_config, build_profile=build_profile, ignore=ignore)
562+
app_config=app_config, build_profile=build_profile, ignore=ignore, coverage_patterns=coverage_patterns)
560563
toolchain.version_check()
561564

562565
# The first path will give the name to the library
@@ -662,7 +665,7 @@ def build_library(src_paths, build_path, target, toolchain_name,
662665
archive=True, notify=None, macros=None, inc_dirs=None, jobs=1,
663666
report=None, properties=None, project_id=None,
664667
remove_config_header_file=False, app_config=None,
665-
build_profile=None, ignore=None, resource_filter=None):
668+
build_profile=None, ignore=None, resource_filter=None, coverage_patterns=None):
666669
""" Build a library
667670
668671
Positional arguments:
@@ -713,7 +716,7 @@ def build_library(src_paths, build_path, target, toolchain_name,
713716
toolchain = prepare_toolchain(
714717
src_paths, build_path, target, toolchain_name, macros=macros,
715718
clean=clean, jobs=jobs, notify=notify, app_config=app_config,
716-
build_profile=build_profile, ignore=ignore)
719+
build_profile=build_profile, ignore=ignore, coverage_patterns=coverage_patterns)
717720
toolchain.version_check()
718721

719722
# The first path will give the name to the library

tools/test.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from tools.config import ConfigException, Config
3030
from tools.test_configs import get_default_config
3131
from tools.test_api import find_tests, get_test_config, print_tests, build_tests, test_spec_from_test_builds
32-
from tools.options import get_default_options_parser, extract_profile, extract_mcus
32+
from tools.options import get_default_options_parser, extract_profile, extract_mcus, argparse_profile_filestring_type
3333
from tools.build_api import build_library
3434
from tools.build_api import print_build_memory_usage
3535
from tools.build_api import merge_build_data
@@ -125,6 +125,9 @@ def main():
125125
parser.add_argument("--ignore", dest="ignore", type=argparse_many(str),
126126
default=None, help="Comma separated list of patterns to add to mbedignore (eg. ./main.cpp)")
127127

128+
parser.add_argument("--coverage-filters", dest="coverage_patterns", nargs='+',
129+
default=[], help="match patterns to build with debug compile and coverage linker options")
130+
128131
parser.add_argument("--icetea",
129132
action="store_true",
130133
dest="icetea",
@@ -230,6 +233,13 @@ def main():
230233
if not base_source_paths:
231234
base_source_paths = ['.']
232235

236+
# Coverage requires debug profile
237+
if options.coverage_patterns:
238+
if toolchain != u'GCC_ARM':
239+
raise ToolException('Coverage supports only GCC_ARM toolchain')
240+
options.profile.append(argparse_profile_filestring_type('debug'))
241+
print("[Warning] Test building with coverage filters %s" % options.coverage_patterns)
242+
233243
build_report = {}
234244
build_properties = {}
235245

@@ -255,6 +265,7 @@ def main():
255265
app_config=config,
256266
build_profile=profile,
257267
ignore=options.ignore,
268+
coverage_patterns=options.coverage_patterns,
258269
resource_filter=resource_filter
259270
)
260271

@@ -299,6 +310,7 @@ def main():
299310
build_profile=profile,
300311
stats_depth=options.stats_depth,
301312
ignore=options.ignore,
313+
coverage_patterns=options.coverage_patterns,
302314
resource_filter=resource_filter)
303315

304316
# If a path to a test spec is provided, write it to a file

tools/test_api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2112,7 +2112,7 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
21122112
silent=False, report=None, properties=None,
21132113
continue_on_build_fail=False, app_config=None,
21142114
build_profile=None, stats_depth=None, ignore=None,
2115-
resource_filter=None):
2115+
resource_filter=None, coverage_patterns=None):
21162116
"""Given the data structure from 'find_tests' and the typical build parameters,
21172117
build all the tests
21182118
@@ -2168,6 +2168,7 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
21682168
'toolchain_paths': TOOLCHAIN_PATHS,
21692169
'stats_depth': stats_depth,
21702170
'notify': MockNotifier(),
2171+
'coverage_patterns': coverage_patterns,
21712172
'resource_filter': resource_filter
21722173
}
21732174

tools/toolchains/gcc.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
limitations under the License.
1616
"""
1717
import re
18+
import fnmatch
1819
from os.path import join, basename, splitext, dirname, exists
1920
from os import getenv
2021
from distutils.spawn import find_executable
@@ -36,14 +37,15 @@ class GCC(mbedToolchain):
3637
GCC_VERSION_RE = re.compile(b"\d+\.\d+\.\d+")
3738

3839
def __init__(self, target, notify=None, macros=None, build_profile=None,
39-
build_dir=None):
40+
build_dir=None, coverage_patterns=None):
4041
mbedToolchain.__init__(
4142
self,
4243
target,
4344
notify,
4445
macros,
4546
build_profile=build_profile,
46-
build_dir=build_dir
47+
build_dir=build_dir,
48+
coverage_patterns=coverage_patterns
4749
)
4850

4951
tool_path = TOOLCHAIN_PATHS['GCC_ARM']
@@ -115,7 +117,7 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
115117
self.cpu.append("-mno-unaligned-access")
116118

117119
self.flags["common"] += self.cpu
118-
120+
self.coverage_supported = True
119121
main_cc = join(tool_path, "arm-none-eabi-gcc")
120122
main_cppc = join(tool_path, "arm-none-eabi-g++")
121123
self.asm = [main_cc] + self.flags['asm'] + self.flags["common"]
@@ -135,6 +137,19 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
135137
self.use_distcc = (bool(getenv("DISTCC_POTENTIAL_HOSTS", False))
136138
and not getenv("MBED_DISABLE_DISTCC", False))
137139

140+
self.coverage_cc = self.cc + ["--coverage", "-DENABLE_LIBGCOV_PORT"]
141+
self.coverage_cppc = self.cppc + ["--coverage", "-DENABLE_LIBGCOV_PORT"]
142+
self.coverage_ld = self.ld + ['--coverage', '-Wl,--wrap,GREENTEA_SETUP', '-Wl,--wrap,_Z25GREENTEA_TESTSUITE_RESULTi']
143+
144+
for flag in ["-DMBED_DEBUG"]:
145+
if flag in self.coverage_cc:
146+
self.coverage_cc.remove(flag)
147+
if flag in self.coverage_cppc:
148+
self.coverage_cppc.remove(flag)
149+
for flag in ['-Wl,--wrap,exit', '-Wl,--wrap,atexit']:
150+
if flag in self.coverage_ld:
151+
self.coverage_ld.remove(flag)
152+
138153
def version_check(self):
139154
stdout, _, retcode = run_cmd([self.cc[0], "--version"], redirect=True)
140155
msg = None
@@ -208,6 +223,12 @@ def get_compile_options(self, defines, includes, for_asm=False):
208223
opts = opts + self.get_config_option(config_header)
209224
return opts
210225

226+
def match_coverage_patterns(self, source):
227+
for pattern in self.coverage_patterns:
228+
if fnmatch.fnmatch(source, pattern):
229+
return True
230+
return False
231+
211232
def assemble(self, source, object, includes):
212233
# Build assemble command
213234
cmd = self.asm + self.get_compile_options(
@@ -231,9 +252,13 @@ def compile(self, cc, source, object, includes):
231252
return [cmd]
232253

233254
def compile_c(self, source, object, includes):
255+
if self.coverage_patterns and self.match_coverage_patterns(source):
256+
return self.compile(self.coverage_cc, source, object, includes)
234257
return self.compile(self.cc, source, object, includes)
235258

236259
def compile_cpp(self, source, object, includes):
260+
if self.coverage_patterns and self.match_coverage_patterns(source):
261+
return self.compile(self.coverage_cppc, source, object, includes)
237262
return self.compile(self.cppc, source, object, includes)
238263

239264
def link(self, output, objects, libraries, lib_dirs, mem_map):
@@ -257,7 +282,7 @@ def link(self, output, objects, libraries, lib_dirs, mem_map):
257282
# Build linker command
258283
map_file = splitext(output)[0] + ".map"
259284
cmd = (
260-
self.ld +
285+
(self.coverage_ld if self.coverage_patterns else self.ld) +
261286
["-o", output, "-Wl,-Map=%s" % map_file] +
262287
objects +
263288
["-Wl,--start-group"] +

tools/toolchains/mbed_toolchain.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ class mbedToolchain:
132132
profile_template = {'common': [], 'c': [], 'cxx': [], 'asm': [], 'ld': []}
133133

134134
def __init__(self, target, notify=None, macros=None, build_profile=None,
135-
build_dir=None):
135+
build_dir=None, coverage_patterns=None):
136136
self.target = target
137137
self.name = self.__class__.__name__
138138

@@ -190,6 +190,9 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
190190
# Used by the mbed Online Build System to build in chrooted environment
191191
self.CHROOT = None
192192

193+
self.coverage_supported = False
194+
self.coverage_patterns = coverage_patterns
195+
193196
# post-init hook used by the online compiler TODO: remove this.
194197
self.init()
195198

0 commit comments

Comments
 (0)