Add options to work in a subdirectory.

* Problem to solve:
  When cargo2android.py is run under external/crosvm,
  it does not generate .bp file in some subdirectories like kvm.
* Use --add_workspace flag to append [workspace] in Cargo.toml
  temporarily to generate correct relative source file paths.
  Otherwise, the path will be based on parent/root package
  such as external/crosvm.
* Use --global_defaults=default_name flag to insert a global
  default module name like "crosvm_defaults" in every module.
* Use --no-subdir flag to generate .bp file in one directory,
  and skip all changes to subdirectories.
* Sort the option names so they show up in order with --help.
* Use relative path for local dependent packages.
* Example: run in external/crosvm with flags;
    --run --tests --dependencies --no-subdir
  fix-up external/crosvm/Android.bp file,
  and then run in each subdirectory with flags:
    --run --tests --dependencies --add_workspace
    --global_defaults=crosvm_defaults
* Add rename mapping:
    libminijail ==> libminijail_rust

Bug: 161716839
Test: regen .bp files in external/crosvm subdirectories
Test: make && atest -m -c --include-subdirs external/crosvm
Change-Id: I0c08d358cc2f88f66e99b59032613d2a5b4ea5eb
This commit is contained in:
Chih-Hung Hsieh
2020-07-24 15:34:06 -07:00
parent e27e2c5448
commit 07119865a0

View File

@@ -74,6 +74,7 @@ RENAME_MAP = {
'libbacktrace': 'libbacktrace_rust',
'libgcc': 'libgcc_rust',
'liblog': 'liblog_rust',
'libminijail': 'libminijail_rust',
'libsync': 'libsync_rust',
'libx86_64': 'libx86_64_rust',
'protoc_gen_rust': 'protoc-gen-rust',
@@ -450,7 +451,10 @@ class Crate(object):
self.main_src = re.sub(r'^\.\.\./github.com-[0-9a-f]*/', '.../',
self.main_src)
self.find_cargo_dir()
if self.cargo_dir and not self.runner.args.onefile:
if self.cargo_dir: # for a subdirectory
if self.runner.args.no_subdir: # all .bp content to /dev/null
self.outf_name = '/dev/null'
elif not self.runner.args.onefile:
# Write to Android.bp in the subdirectory with Cargo.toml.
self.outf_name = self.cargo_dir + '/Android.bp'
self.main_src = self.main_src[len(self.cargo_dir) + 1:]
@@ -501,6 +505,8 @@ class Crate(object):
pkg = self.main_src
if pkg.startswith('.../'): # keep only the main package name
pkg = re.sub('/.*', '', pkg[4:])
elif pkg.startswith('/'): # use relative path for a local package
pkg = os.path.relpath(pkg)
if not self.features:
return pkg
return pkg + ' "' + ','.join(self.features) + '"'
@@ -605,6 +611,8 @@ class Crate(object):
self.defaults = name
self.write('\nrust_defaults {')
self.write(' name: "' + name + '",')
if self.runner.args.global_defaults:
self.write(' defaults: ["' + self.runner.args.global_defaults + '"],')
self.write(' crate_name: "' + self.crate_name + '",')
if len(self.srcs) == 1: # only one source file; share it in defaults
self.default_srcs = True
@@ -784,6 +792,8 @@ class Crate(object):
# see properties shared by dump_defaults_module
if self.defaults:
self.write(' defaults: ["' + self.defaults + '"],')
elif self.runner.args.global_defaults:
self.write(' defaults: ["' + self.runner.args.global_defaults + '"],')
if self.stem != self.module_name:
self.write(' stem: "' + self.stem + '",')
if self.has_warning and not self.cap_lints and not self.default_srcs:
@@ -1112,10 +1122,12 @@ class Runner(object):
outf.write(ANDROID_BP_HEADER.format(args=' '.join(sys.argv[1:])))
def dump_test_mapping_files(self):
"""Dump all TEST_MAPPING files."""
if self.dry_run:
print('Dry-run skip dump of TEST_MAPPING')
else:
for bp_file_name in self.test_mappings:
if bp_file_name != '/dev/null':
name = os.path.join(os.path.dirname(bp_file_name), 'TEST_MAPPING')
self.test_mappings[bp_file_name].dump(name)
return self
@@ -1163,16 +1175,31 @@ class Runner(object):
"""Calls cargo -v and save its output to ./cargo.out."""
if self.skip_cargo:
return self
cargo = './Cargo.toml'
if not os.access(cargo, os.R_OK):
print('ERROR: Cannot find or read', cargo)
cargo_toml = './Cargo.toml'
cargo_out = './cargo.out'
if not os.access(cargo_toml, os.R_OK):
print('ERROR: Cannot find or read', cargo_toml)
return self
if not self.dry_run and os.path.exists('cargo.out'):
os.remove('cargo.out')
cmd_tail = ' --target-dir ' + TARGET_TMP + ' >> cargo.out 2>&1'
if not self.dry_run and os.path.exists(cargo_out):
os.remove(cargo_out)
cmd_tail = ' --target-dir ' + TARGET_TMP + ' >> ' + cargo_out + ' 2>&1'
# set up search PATH for cargo to find the correct rustc
saved_path = os.environ['PATH']
os.environ['PATH'] = os.path.dirname(self.cargo_path) + ':' + saved_path
# Add [workspace] to Cargo.toml if it is not there.
added_workspace = False
if self.args.add_workspace:
with open(cargo_toml, 'r') as in_file:
cargo_toml_lines = in_file.readlines()
found_workspace = '[workspace]\n' in cargo_toml_lines
if found_workspace:
print('### WARNING: found [workspace] in Cargo.toml')
else:
with open(cargo_toml, 'a') as out_file:
out_file.write('[workspace]\n')
added_workspace = True
if self.args.verbose:
print('### INFO: added [workspace] to Cargo.toml')
for c in self.cargo:
features = ''
if c != 'clean':
@@ -1190,9 +1217,14 @@ class Runner(object):
else:
if self.args.verbose:
print('Running:', cmd)
with open('cargo.out', 'a') as cargo_out:
cargo_out.write('### Running: ' + cmd + '\n')
with open(cargo_out, 'a') as out_file:
out_file.write('### Running: ' + cmd + '\n')
os.system(cmd)
if added_workspace: # restore original Cargo.toml
with open(cargo_toml, 'w') as out_file:
out_file.writelines(cargo_toml_lines)
if self.args.verbose:
print('### INFO: restored original Cargo.toml')
os.environ['PATH'] = saved_path
return self
@@ -1367,6 +1399,14 @@ class Runner(object):
def parse_args():
"""Parse main arguments."""
parser = argparse.ArgumentParser('cargo2android')
parser.add_argument(
'--add_workspace',
action='store_true',
default=False,
help=('append [workspace] to Cargo.toml before calling cargo,' +
' to treat current directory as root of package source;' +
' otherwise the relative source file path in generated' +
' .bp file will be from the parent directory.'))
parser.add_argument(
'--cargo',
action='append',
@@ -1393,10 +1433,14 @@ def parse_args():
default=False,
help='run cargo also for a default device target')
parser.add_argument(
'--no-host',
action='store_true',
default=False,
help='do not run cargo for the host; only for the device target')
'--features',
type=str,
help=('pass features to cargo build, ' +
'empty string means no default features'))
parser.add_argument(
'--global_defaults',
type=str,
help='add a defaults name to every module')
parser.add_argument(
'--host-first-multilib',
action='store_true',
@@ -1404,10 +1448,15 @@ def parse_args():
help=('add a compile_multilib:"first" property ' +
'to Android.bp host modules.'))
parser.add_argument(
'--features',
type=str,
help=('pass features to cargo build, ' +
'empty string means no default features'))
'--no-host',
action='store_true',
default=False,
help='do not run cargo for the host; only for the device target')
parser.add_argument(
'--no-subdir',
action='store_true',
default=False,
help='do not output anything for sub-directories')
parser.add_argument(
'--onefile',
action='store_true',