diff --git a/tools/cargo_embargo/src/cargo.rs b/tools/cargo_embargo/src/cargo.rs index 23e644765..9a9949c89 100644 --- a/tools/cargo_embargo/src/cargo.rs +++ b/tools/cargo_embargo/src/cargo.rs @@ -72,11 +72,11 @@ pub struct Crate { pub package_name: String, pub version: Option, pub types: Vec, - pub target: Option, // --target - pub features: Vec, // --cfg feature= - pub cfgs: Vec, // non-feature --cfg - pub externs: Vec<(String, Option)>, // name => rlib file - pub codegens: Vec, // -C + pub target: Option, // --target + pub features: Vec, // --cfg feature= + pub cfgs: Vec, // non-feature --cfg + pub externs: Vec, + pub codegens: Vec, // -C pub cap_lints: String, pub static_libs: Vec, pub shared_libs: Vec, @@ -84,3 +84,17 @@ pub struct Crate { pub package_dir: PathBuf, // canonicalized pub main_src: PathBuf, // relative to package_dir } + +/// A dependency of a Rust crate. +#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] +pub struct Extern { + pub name: String, + pub lib_name: String, + pub extern_type: ExternType, +} + +#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] +pub enum ExternType { + Rust, + ProcMacro, +} diff --git a/tools/cargo_embargo/src/cargo/cargo_out.rs b/tools/cargo_embargo/src/cargo/cargo_out.rs index 74acf5c04..f04c01348 100644 --- a/tools/cargo_embargo/src/cargo/cargo_out.rs +++ b/tools/cargo_embargo/src/cargo/cargo_out.rs @@ -13,7 +13,7 @@ // limitations under the License. use super::metadata::WorkspaceMetadata; -use super::{Crate, CrateType}; +use super::{Crate, CrateType, Extern, ExternType}; use anyhow::anyhow; use anyhow::bail; use anyhow::Context; @@ -236,12 +236,32 @@ impl Crate { // example: memoffset=/some/path/libmemoffset-2cfda327d156e680.rmeta let arg = arg_iter.next().unwrap(); if let Some((name, path)) = arg.split_once('=') { - out.externs.push(( - name.to_string(), - Some(path.split('/').last().unwrap().to_string()), - )); - } else { - out.externs.push((arg.to_string(), None)); + let filename = path.split('/').last().unwrap(); + + // Example filename: "libgetrandom-fd8800939535fc59.rmeta" + static REGEX: Lazy = Lazy::new(|| { + Regex::new(r"^lib(.*)-[0-9a-f]*.(rlib|so|rmeta)$").unwrap() + }); + + let Some(lib_name) = REGEX.captures(filename).and_then(|x| x.get(1)) else { + bail!("bad filename for extern {}: {}", name, filename); + }; + let extern_type = + if filename.ends_with(".rlib") || filename.ends_with(".rmeta") { + ExternType::Rust + } else if filename.ends_with(".so") { + // Assume .so files are always proc_macros. May not always be right. + ExternType::ProcMacro + } else { + bail!("Unexpected extension for extern filename {}", filename); + }; + out.externs.push(Extern { + name: name.to_string(), + lib_name: lib_name.as_str().to_string(), + extern_type, + }); + } else if arg != "proc_macro" { + panic!("No filename for {}", arg); } } _ if arg.starts_with("-C") => { diff --git a/tools/cargo_embargo/src/main.rs b/tools/cargo_embargo/src/main.rs index cbcac394d..84638ca72 100644 --- a/tools/cargo_embargo/src/main.rs +++ b/tools/cargo_embargo/src/main.rs @@ -36,10 +36,8 @@ use anyhow::bail; use anyhow::Context; use anyhow::Result; use bp::*; -use cargo::{cargo_out::parse_cargo_out, Crate, CrateType}; +use cargo::{cargo_out::parse_cargo_out, Crate, CrateType, ExternType}; use clap::Parser; -use once_cell::sync::Lazy; -use regex::Regex; use std::collections::BTreeMap; use std::collections::VecDeque; use std::fs::File; @@ -505,27 +503,10 @@ fn crate_to_bp_modules( let mut rust_libs = Vec::new(); let mut proc_macro_libs = Vec::new(); - for (extern_name, filename) in &crate_.externs { - if extern_name == "proc_macro" { - continue; - } - let filename = - filename.as_ref().unwrap_or_else(|| panic!("no filename for {}", extern_name)); - // Example filename: "libgetrandom-fd8800939535fc59.rmeta" - static REGEX: Lazy = - Lazy::new(|| Regex::new(r"^lib(.*)-[0-9a-f]*.(rlib|so|rmeta)$").unwrap()); - let lib_name = if let Some(x) = REGEX.captures(filename).and_then(|x| x.get(1)) { - x - } else { - bail!("bad filename for extern {}: {}", extern_name, filename); - }; - if filename.ends_with(".rlib") || filename.ends_with(".rmeta") { - rust_libs.push(lib_name.as_str().to_string()); - } else if filename.ends_with(".so") { - // Assume .so files are always proc_macros. May not always be right. - proc_macro_libs.push(lib_name.as_str().to_string()); - } else { - unreachable!(); + for extern_dep in &crate_.externs { + match extern_dep.extern_type { + ExternType::Rust => rust_libs.push(extern_dep.lib_name.clone()), + ExternType::ProcMacro => proc_macro_libs.push(extern_dep.lib_name.clone()), } } diff --git a/tools/cargo_embargo/testdata/either/crates.json b/tools/cargo_embargo/testdata/either/crates.json index aa38632c8..27f597751 100644 --- a/tools/cargo_embargo/testdata/either/crates.json +++ b/tools/cargo_embargo/testdata/either/crates.json @@ -24,7 +24,9 @@ "target": "x86_64-unknown-linux-gnu", "features": ["default", "use_std"], "cfgs": [], - "externs": [["serde_json", "libserde_json-a330ac0e36ca324c.rlib"]], + "externs": [ + { "name": "serde_json", "lib_name": "serde_json", "extern_type": "Rust" } + ], "codegens": [], "cap_lints": "", "static_libs": [], diff --git a/tools/cargo_embargo/testdata/plotters/crates.json b/tools/cargo_embargo/testdata/plotters/crates.json index 04851c9ab..b65bbf984 100644 --- a/tools/cargo_embargo/testdata/plotters/crates.json +++ b/tools/cargo_embargo/testdata/plotters/crates.json @@ -8,9 +8,17 @@ "features": ["area_series", "line_series", "plotters-svg", "svg_backend"], "cfgs": [], "externs": [ - ["num_traits", "libnum_traits-93a69c224ed38166.rmeta"], - ["plotters_backend", "libplotters_backend-4110c43be89cf520.rmeta"], - ["plotters_svg", "libplotters_svg-e0f639cce7c4701c.rmeta"] + { "name": "num_traits", "lib_name": "num_traits", "extern_type": "Rust" }, + { + "name": "plotters_backend", + "lib_name": "plotters_backend", + "extern_type": "Rust" + }, + { + "name": "plotters_svg", + "lib_name": "plotters_svg", + "extern_type": "Rust" + } ], "codegens": [], "cap_lints": "",