Generate TEST_MAPPING for test modules in .bp file

* Share srcs in rust_defaults if len(srcs) is 1.

Test: regenerate .bp and TEST_MAPPING files in external/rust/crates
Test: make
Test: atest -c  --include-subdirs external/rust/crates
Bug: 161259631
Change-Id: I22a1d567ccabcd945e4cac870049ac3ce7a3049a
This commit is contained in:
Chih-Hung Hsieh
2020-07-16 15:36:22 -07:00
parent 781e401ba0
commit f7eff158a9

View File

@@ -48,6 +48,9 @@ The Cargo.toml file should work at least for the host platform.
--cargo "build --target x86_64-unknown-linux-gnu"
--cargo "build --tests --target x86_64-unknown-linux-gnu"
Note that when there are test modules generated into Android.bp,
corresponding test entries will also be added into the TEST_MAPPING file.
If there are rustc warning messages, this script will add
a warning comment to the owner crate module in Android.bp.
"""
@@ -180,6 +183,38 @@ def escape_quotes(s): # replace '"' with '\\"'
return s.replace('"', '\\"')
class TestMapping(object):
"""Entries for a TEST_MAPPING file."""
def __init__(self):
self.entries = []
def add_test(self, name, host):
self.entries.append((name, host))
def is_empty(self):
return not self.entries
def dump(self, outf_name):
"""Append all entries into the output file."""
if self.is_empty():
return
with open(outf_name, 'w') as outf:
outf.write('// Generated by cargo2android.py for tests in Android.bp\n')
outf.write('{\n "presubmit": [\n')
is_first = True
for (name, host) in self.entries:
if not is_first: # add comma and '\n' after the previous entry
outf.write(',\n')
is_first = False
outf.write(' {\n "name": "' + name + '"')
if host:
outf.write(',\n "host": true\n }')
else:
outf.write('\n }')
outf.write('\n ]\n}\n')
class Crate(object):
"""Information of a Rust crate to collect/emit for an Android.bp module."""
@@ -198,6 +233,7 @@ class Crate(object):
self.module_name = '' # unique in Android build system
self.module_type = '' # rust_{binary,library,test}[_host] etc.
self.defaults = '' # rust_defaults used by rust_test* modules
self.default_srcs = False # use 'srcs' defined in self.defaults
self.root_pkg = '' # parent package name of a sub/test packge, from -L
self.srcs = list() # main_src or merged multiple source files
self.stem = '' # real base name of output file
@@ -560,6 +596,11 @@ class Crate(object):
self.write('\nrust_defaults {')
self.write(' name: "' + name + '",')
self.write(' crate_name: "' + self.crate_name + '",')
if len(self.srcs) == 1: # only one source file; share it in defaults
self.default_srcs = True
if self.has_warning and not self.cap_lints:
self.write(' // has rustc warnings')
self.write(' srcs: ["' + self.main_src + '"],')
if 'test' in self.crate_types:
self.write(' test_suites: ["general-tests"],')
self.write(' auto_gen_config: true,')
@@ -591,12 +632,14 @@ class Crate(object):
self.module_name = self.test_module_name()
self.decide_one_module_type(crate_type)
self.dump_one_android_module(crate_type)
self.runner.add_test(self.outf_name, self.module_name, True)
if saved_device_supported:
self.device_supported = True
self.host_supported = False
self.module_name = self.test_module_name()
self.decide_one_module_type(crate_type)
self.dump_one_android_module(crate_type)
self.runner.add_test(self.outf_name, self.module_name, False)
self.host_supported = saved_host_supported
self.device_supported = saved_device_supported
self.main_src = saved_main_src
@@ -734,7 +777,7 @@ class Crate(object):
self.write(' defaults: ["' + self.defaults + '"],')
if self.stem != self.module_name:
self.write(' stem: "' + self.stem + '",')
if self.has_warning and not self.cap_lints:
if self.has_warning and not self.cap_lints and not self.default_srcs:
self.write(' // has rustc warnings')
if self.host_supported and self.device_supported:
self.write(' host_supported: true,')
@@ -743,7 +786,7 @@ class Crate(object):
if len(self.srcs) > 1:
self.srcs = sorted(set(self.srcs))
self.dump_android_property_list('srcs', '"%s"', self.srcs)
else:
elif not self.default_srcs:
self.write(' srcs: ["' + self.main_src + '"],')
if 'test' in self.crate_types and not self.defaults:
# self.root_pkg can have multiple test modules, with different *_tests[n]
@@ -964,6 +1007,7 @@ class Runner(object):
def __init__(self, args):
self.bp_files = set() # Remember all output Android.bp files.
self.test_mappings = {} # Map from Android.bp file path to TestMapping.
self.root_pkg = '' # name of package in ./Cargo.toml
# Saved flags, modes, and data.
self.args = args
@@ -1004,6 +1048,21 @@ class Runner(object):
with open(name, 'w') as outf:
outf.write(ANDROID_BP_HEADER.format(args=' '.join(sys.argv[1:])))
def dump_test_mapping_files(self):
if self.dry_run:
print('Dry-run skip dump of TEST_MAPPING')
else:
for bp_file_name in self.test_mappings:
name = os.path.join(os.path.dirname(bp_file_name), 'TEST_MAPPING')
self.test_mappings[bp_file_name].dump(name)
return self
def add_test(self, bp_file_name, test_name, host):
if bp_file_name not in self.test_mappings:
self.test_mappings[bp_file_name] = TestMapping()
mapping = self.test_mappings[bp_file_name]
mapping.add_test(test_name, host)
def try_claim_module_name(self, name, owner):
"""Reserve and return True if it has not been reserved yet."""
if name not in self.name_owners or owner == self.name_owners[name]:
@@ -1316,7 +1375,7 @@ def main():
args = parse_args()
if not args.run: # default is dry-run
print(DRY_RUN_NOTE)
Runner(args).run_cargo().gen_bp()
Runner(args).run_cargo().gen_bp().dump_test_mapping_files()
if __name__ == '__main__':