summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Crane <cranes@google.com>2024-04-11 00:49:06 +0000
committerStephen Crane <cranes@google.com>2024-04-15 21:40:12 +0000
commitb05d4a2f35622df7ca8a71a0f8ec116b0de0305b (patch)
tree9c8dc398d390cc177cac94d5570c058a8ee3d616
parent06afe25b6c1ea3ea76eadeb7e590a829038d5084 (diff)
downloaddevelopment-b05d4a2f35622df7ca8a71a0f8ec116b0de0305b.tar.gz
cargo_embargo: Implement rules.mk generation
Implement the generation of Trusty makefile rules from cargo embargo. This change adds all the messy logic to generate the actual rules file contents. Test: m cargo_embargo Test: cargo_embargo generate cargo_embargo.json (and inspect resulting rules) Bug: 307615277 Change-Id: I4fa301cfd238b180fa584e064908f9897aeb0624
-rw-r--r--tools/cargo_embargo/src/main.rs142
1 files changed, 130 insertions, 12 deletions
diff --git a/tools/cargo_embargo/src/main.rs b/tools/cargo_embargo/src/main.rs
index c45a78237..5589c4e61 100644
--- a/tools/cargo_embargo/src/main.rs
+++ b/tools/cargo_embargo/src/main.rs
@@ -83,18 +83,38 @@ pub static RENAME_MAP: Lazy<BTreeMap<&str, &str>> = Lazy::new(|| {
.collect()
});
+/// This map tracks Rust crates that have special rules.mk modules that were not
+/// generated automatically by this script. Examples include compiler builtins
+/// and other foundational libraries. It also tracks the location of rules.mk
+/// build files for crates that are not under external/rust/crates.
+pub static RULESMK_RENAME_MAP: Lazy<BTreeMap<&str, &str>> = Lazy::new(|| {
+ [
+ ("liballoc", "trusty/user/base/lib/liballoc-rust"),
+ ("libcompiler_builtins", "trusty/user/base/lib/libcompiler_builtins-rust"),
+ ("libcore", "trusty/user/base/lib/libcore-rust"),
+ ("libhashbrown", "trusty/user/base/lib/libhashbrown-rust"),
+ ("libpanic_abort", "trusty/user/base/lib/libpanic_abort-rust"),
+ ("libstd", "trusty/user/base/lib/libstd-rust"),
+ ("libstd_detect", "trusty/user/base/lib/libstd_detect-rust"),
+ ("libunwind", "trusty/user/base/lib/libunwind-rust"),
+ ]
+ .into_iter()
+ .collect()
+});
+
/// Given a proposed module name, returns `None` if it is blocked by the given config, or
/// else apply any name overrides and returns the name to use.
fn override_module_name(
module_name: &str,
blocklist: &[String],
module_name_overrides: &BTreeMap<String, String>,
+ rename_map: &BTreeMap<&str, &str>,
) -> Option<String> {
if blocklist.iter().any(|blocked_name| blocked_name == module_name) {
None
} else if let Some(overridden_name) = module_name_overrides.get(module_name) {
Some(overridden_name.to_string())
- } else if let Some(renamed) = RENAME_MAP.get(module_name) {
+ } else if let Some(renamed) = rename_map.get(module_name) {
Some(renamed.to_string())
} else {
Some(module_name.to_string())
@@ -639,6 +659,7 @@ fn generate_android_bp(
&format!("copy_{}_build_out", package_name),
&cfg.module_blocklist,
&cfg.module_name_overrides,
+ &RENAME_MAP,
) {
m.props.set("name", module_name.clone());
m.props.set("srcs", vec!["out/*"]);
@@ -687,7 +708,7 @@ fn generate_rules_mk(
crates: &[Crate],
out_files: &[PathBuf],
) -> Result<String> {
- let extra_srcs = if package_cfg.copy_out && !out_files.is_empty() {
+ let out_files = if package_cfg.copy_out && !out_files.is_empty() {
out_files.iter().map(|f| f.file_name().unwrap().to_str().unwrap().to_string()).collect()
} else {
vec![]
@@ -714,7 +735,7 @@ fn generate_rules_mk(
rules.mk, found: {crates:?}"
);
};
- crate_to_rulesmk(crate_, cfg, package_cfg, &extra_srcs).with_context(|| {
+ crate_to_rulesmk(crate_, cfg, package_cfg, &out_files).with_context(|| {
format!(
"failed to generate rules.mk for crate \"{}\" with package name \"{}\"",
crate_.name, crate_.package_name
@@ -831,9 +852,12 @@ fn crate_to_bp_modules(
};
let mut m = BpModule::new(module_type.clone());
- let Some(module_name) =
- override_module_name(&module_name, &cfg.module_blocklist, &cfg.module_name_overrides)
- else {
+ let Some(module_name) = override_module_name(
+ &module_name,
+ &cfg.module_blocklist,
+ &cfg.module_name_overrides,
+ &RENAME_MAP,
+ ) else {
continue;
};
if matches!(
@@ -928,6 +952,7 @@ fn crate_to_bp_modules(
&module_name,
&package_cfg.dep_blocklist,
&cfg.module_name_overrides,
+ &RENAME_MAP,
) {
result.push(module_name);
}
@@ -1010,13 +1035,106 @@ fn crate_to_bp_modules(
///
/// If messy business logic is necessary, prefer putting it here.
fn crate_to_rulesmk(
- _crate_: &Crate,
- _cfg: &VariantConfig,
- _package_cfg: &PackageVariantConfig,
- _extra_srcs: &[String],
+ crate_: &Crate,
+ cfg: &VariantConfig,
+ package_cfg: &PackageVariantConfig,
+ out_files: &[String],
) -> Result<String> {
- // TODO: Implement rules generation
- Ok(String::new())
+ let mut contents = String::new();
+
+ contents += "LOCAL_DIR := $(GET_LOCAL_DIR)\n";
+ contents += "MODULE := $(LOCAL_DIR)\n";
+ contents += &format!("MODULE_CRATE_NAME := {}\n", crate_.name);
+
+ if !crate_.types.is_empty() {
+ contents += "MODULE_RUST_CRATE_TYPES :=";
+ for crate_type in &crate_.types {
+ contents += match crate_type {
+ CrateType::Lib => " rlib",
+ CrateType::StaticLib => " staticlib",
+ CrateType::ProcMacro => " proc-macro",
+ _ => bail!("Cannot generate rules.mk for crate type {crate_type:?}"),
+ };
+ }
+ contents += "\n";
+ }
+
+ contents += &format!("MODULE_SRCS := $(LOCAL_DIR)/{}\n", crate_.main_src.display());
+
+ if !out_files.is_empty() {
+ contents += &format!("OUT_FILES := {}\n", out_files.join(" "));
+ contents += "BUILD_OUT_FILES := $(addprefix $(call TOBUILDDIR,$(MODULE))/,$(OUT_FILES))\n";
+ contents += "$(BUILD_OUT_FILES): $(call TOBUILDDIR,$(MODULE))/% : $(MODULE)/out/%\n";
+ contents += "\t@echo copying $^ to $@\n";
+ contents += "\t@$(MKDIR)\n";
+ contents += "\t@cp $^ $@\n\n";
+ contents += "MODULE_RUST_ENV += OUT_DIR=$(call TOBUILDDIR,$(MODULE))\n\n";
+ contents += "MODULE_SRCDEPS += $(BUILD_OUT_FILES)\n\n";
+ contents += "OUT_FILES :=\n";
+ contents += "BUILD_OUT_FILES :=\n";
+ contents += "\n";
+ }
+
+ // crate dependencies without lib- prefix
+ let mut library_deps: Vec<_> = crate_.externs.iter().map(|dep| dep.lib_name.clone()).collect();
+ if package_cfg.no_std {
+ contents += "MODULE_ADD_IMPLICIT_DEPS := false\n";
+ library_deps.push("compiler_builtins".to_string());
+ library_deps.push("core".to_string());
+ if package_cfg.alloc {
+ library_deps.push("alloc".to_string());
+ }
+ }
+
+ contents += &format!("MODULE_RUST_EDITION := {}\n", crate_.edition);
+
+ let mut flags = Vec::new();
+ if !crate_.cap_lints.is_empty() {
+ flags.push(crate_.cap_lints.clone());
+ }
+ flags.extend(crate_.codegens.iter().map(|codegen| format!("-C {}", codegen)));
+ flags.extend(crate_.features.iter().map(|feat| format!("--cfg 'feature=\"{feat}\"'")));
+ flags.extend(
+ crate_
+ .cfgs
+ .iter()
+ .filter(|crate_cfg| !cfg.cfg_blocklist.contains(crate_cfg))
+ .chain(cfg.extra_cfg.iter())
+ .map(|cfg| format!("--cfg '{cfg}'")),
+ );
+ if !flags.is_empty() {
+ contents += "MODULE_RUSTFLAGS += \\\n\t";
+ contents += &flags.join(" \\\n\t");
+ contents += "\n\n";
+ }
+
+ let mut library_deps: Vec<String> = library_deps
+ .into_iter()
+ .flat_map(|dep| {
+ override_module_name(
+ &format!("lib{dep}"),
+ &package_cfg.dep_blocklist,
+ &cfg.module_name_overrides,
+ &RULESMK_RENAME_MAP,
+ )
+ })
+ .map(|dep| {
+ // Rewrite dependency name to module path for Trusty build system
+ if let Some(dep) = dep.strip_prefix("lib") {
+ format!("external/rust/crates/{dep}")
+ } else {
+ dep
+ }
+ })
+ .collect();
+ library_deps.sort();
+ library_deps.dedup();
+ contents += "MODULE_LIBRARY_DEPS := \\\n\t";
+ contents += &library_deps.join(" \\\n\t");
+ contents += "\n\n";
+
+ contents += "include make/library.mk\n";
+ Ok(contents)
}
#[cfg(test)]