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