Merge "Add a --copy-out flag for build.rs output files."
diff --git a/scripts/cargo2android.py b/scripts/cargo2android.py
index 8004d2b..99f8976 100755
--- a/scripts/cargo2android.py
+++ b/scripts/cargo2android.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# Copyright (C) 2019 The Android Open Source Project
#
@@ -49,10 +49,12 @@
from __future__ import print_function
import argparse
+import glob
import os
import os.path
import platform
import re
+import shutil
import sys
# Some Rust packages include extra unwanted crates.
@@ -593,6 +595,17 @@
return name3
return self.runner.claim_module_name(name1, self, 0)
+ def dump_srcs_list(self):
+ """Dump the srcs list, for defaults or regular modules."""
+ if len(self.srcs) > 1:
+ srcs = sorted(set(self.srcs)) # make a copy and dedup
+ else:
+ srcs = [self.main_src]
+ copy_out = self.runner.copy_out_module_name()
+ if copy_out:
+ srcs.append(':' + copy_out)
+ self.dump_android_property_list('srcs', '"%s"', srcs)
+
def dump_defaults_module(self):
"""Dump a rust_defaults module to be shared by other modules."""
name = self.build_default_name()
@@ -606,7 +619,7 @@
self.default_srcs = True
if self.has_warning and not self.cap_lints:
self.write(' // has rustc warnings')
- self.write(' srcs: ["' + self.main_src + '"],')
+ self.dump_srcs_list()
if 'test' in self.crate_types:
self.write(' test_suites: ["general-tests"],')
self.write(' auto_gen_config: true,')
@@ -769,10 +782,15 @@
self.write(' ' + (fmt % escape_quotes(v)) + ',')
def dump_android_property_list(self, name, fmt, values):
- if values:
+ if not values:
+ return
+ if len(values) > 1:
self.write(' ' + name + ': [')
self.dump_android_property_list_items(fmt, values)
self.write(' ],')
+ else:
+ self.write(' ' + name + ': [' +
+ (fmt % escape_quotes(values[0])) + '],')
def dump_android_core_properties(self):
"""Dump the module header, name, stem, etc."""
@@ -790,11 +808,8 @@
self.write(' host_supported: true,')
if not self.defaults:
self.write(' crate_name: "' + self.crate_name + '",')
- if len(self.srcs) > 1:
- self.srcs = sorted(set(self.srcs))
- self.dump_android_property_list('srcs', '"%s"', self.srcs)
- elif not self.default_srcs:
- self.write(' srcs: ["' + self.main_src + '"],')
+ if not self.default_srcs:
+ self.dump_srcs_list()
if 'test' in self.crate_types and not self.defaults:
# self.root_pkg can have multiple test modules, with different *_tests[n]
# names, but their executables can all be installed under the same _tests
@@ -1021,6 +1036,8 @@
self.dry_run = not args.run
self.skip_cargo = args.skipcargo
self.cargo_path = './cargo' # path to cargo, will be set later
+ self.checked_out_files = False # to check only once
+ self.build_out_files = [] # output files generated by build.rs
# All cc/ar objects, crates, dependencies, and warning files
self.cc_objects = list()
self.pkg_obj2cc = {}
@@ -1099,11 +1116,56 @@
rust_version = version
return '.'.join(rust_version)
+ def copy_out_files(self):
+ """Copy build.rs output files to ./out and set up build_out_files."""
+ if not self.args.copy_out or self.checked_out_files:
+ return
+ self.checked_out_files = True
+ # list1 has build.rs output for normal crates
+ list1 = glob.glob(TARGET_TMP + '/*/*/build/' + self.root_pkg + '-*/out/*')
+ # list2 has build.rs output for proc-macro crates
+ list2 = glob.glob(TARGET_TMP + '/*/build/' + self.root_pkg + '-*/out/*')
+ out_files = set()
+ if list1 or list2:
+ os.makedirs('out', exist_ok=True)
+ for path in (list1 + list2):
+ file_name = path.split('/')[-1]
+ out_files.add(file_name)
+ shutil.copy(path, 'out/' + file_name)
+ self.build_out_files = sorted(out_files)
+
+ def copy_out_module_name(self):
+ if self.args.copy_out and self.build_out_files:
+ return 'copy_' + self.root_pkg + '_build_out'
+ else:
+ return ''
+
+ def dump_copy_out_module(self, outf):
+ """Output the genrule module to copy out/* to $(genDir)."""
+ copy_out = self.copy_out_module_name()
+ if not copy_out:
+ return
+ outf.write('\ngenrule {\n')
+ outf.write(' name: "' + copy_out + '",\n')
+ outf.write(' srcs: ["out/*"],\n')
+ outf.write(' cmd: "cp $(in) $(genDir)",\n')
+ if len(self.build_out_files) > 1:
+ outf.write(' out: [\n')
+ for f in self.build_out_files:
+ outf.write(' "' + f + '",\n')
+ outf.write(' ],\n')
+ else:
+ outf.write(' out: ["' + self.build_out_files[0] + '"],\n')
+ outf.write('}\n')
+
def init_bp_file(self, name):
+ # name could be Android.bp or sub_dir_path/Android.bp
if name not in self.bp_files:
self.bp_files.add(name)
with open(name, 'w') as outf:
outf.write(ANDROID_BP_HEADER.format(args=' '.join(sys.argv[1:])))
+ # at most one copy_out module per .bp file
+ self.dump_copy_out_module(outf)
def dump_test_mapping_files(self):
"""Dump all TEST_MAPPING files."""
@@ -1248,6 +1310,7 @@
print('Dry-run skip: read', CARGO_OUT, 'write Android.bp')
elif os.path.exists(CARGO_OUT):
self.find_root_pkg()
+ self.copy_out_files()
with open(CARGO_OUT, 'r') as cargo_out:
self.parse(cargo_out, 'Android.bp')
self.crates.sort(key=get_module_name)
@@ -1402,6 +1465,14 @@
type=str,
help='use cargo in the cargo_bin directory instead of the prebuilt one')
parser.add_argument(
+ '--copy-out',
+ action='store_true',
+ default=False,
+ help=('only for root directory, ' +
+ 'copy build.rs output to ./out/* and add a genrule to copy ' +
+ './out/* to genrule output; for crates with code pattern: ' +
+ 'include!(concat!(env!("OUT_DIR"), "/<some_file>.rs"))'))
+ parser.add_argument(
'--debug',
action='store_true',
default=False,