diff options
author | Stephen Crane <cranes@google.com> | 2024-04-11 00:49:06 +0000 |
---|---|---|
committer | Stephen Crane <cranes@google.com> | 2024-04-15 21:40:12 +0000 |
commit | b05d4a2f35622df7ca8a71a0f8ec116b0de0305b (patch) | |
tree | 9c8dc398d390cc177cac94d5570c058a8ee3d616 | |
parent | 06afe25b6c1ea3ea76eadeb7e590a829038d5084 (diff) | |
download | development-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.rs | 142 |
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)] |