|
| 1 | +//! Process wrapper for `CargoBuildInfo` actions. |
| 2 | +//! |
| 3 | +//! Copies source files into an OUT_DIR and writes metadata files |
| 4 | +//! (env, dep_env, flags, link_flags, link_search_paths) consumed by `BuildInfo`. |
| 5 | +
|
| 6 | +use std::fs; |
| 7 | +use std::path::Path; |
| 8 | + |
| 9 | +struct Args { |
| 10 | + /// Directory path for the `OUT_DIR` output tree. |
| 11 | + out_dir: String, |
| 12 | + /// Files to copy into `out_dir` as `(dest_relative_path, src_path)` pairs. |
| 13 | + files: Vec<(String, String)>, |
| 14 | + /// Output path for the `BuildInfo.rustc_env` file (one `K=V` per line). |
| 15 | + env_out: String, |
| 16 | + /// Output path for the `BuildInfo.flags` file (one rustc flag per line). |
| 17 | + flags_out: String, |
| 18 | + /// Output path for the `BuildInfo.linker_flags` file (one linker flag per line). |
| 19 | + link_flags_out: String, |
| 20 | + /// Output path for the `BuildInfo.link_search_paths` file (one `-Lnative=` path per line). |
| 21 | + link_search_paths_out: String, |
| 22 | + /// Output path for the `BuildInfo.dep_env` file (one `K=V` per line, already prefixed). |
| 23 | + dep_env_out: String, |
| 24 | + /// Extra flags to pass to rustc, written to `flags_out`. |
| 25 | + rustc_flags: Vec<String>, |
| 26 | + /// Extra environment variables for rustc as `K=V`, written to `env_out`. |
| 27 | + rustc_envs: Vec<String>, |
| 28 | + /// Dependency environment variables as `K=V`, written to `dep_env_out`. |
| 29 | + dep_envs: Vec<String>, |
| 30 | + /// Linker flags derived from `CcInfo` (e.g. `-lstatic=crypto`), written to `link_flags_out`. |
| 31 | + link_flags: Vec<String>, |
| 32 | + /// Library search paths derived from `CcInfo`, formatted as `-Lnative=` and written to `link_search_paths_out`. |
| 33 | + link_search_paths: Vec<String>, |
| 34 | +} |
| 35 | + |
| 36 | +impl Args { |
| 37 | + /// Parse command line arguments. |
| 38 | + fn parse() -> Self { |
| 39 | + let mut out_dir: Option<String> = None; |
| 40 | + let mut files = Vec::new(); |
| 41 | + let mut env_out: Option<String> = None; |
| 42 | + let mut flags_out: Option<String> = None; |
| 43 | + let mut link_flags_out: Option<String> = None; |
| 44 | + let mut link_search_paths_out: Option<String> = None; |
| 45 | + let mut dep_env_out: Option<String> = None; |
| 46 | + let mut rustc_flags = Vec::new(); |
| 47 | + let mut rustc_envs = Vec::new(); |
| 48 | + let mut dep_envs = Vec::new(); |
| 49 | + let mut link_flags = Vec::new(); |
| 50 | + let mut link_search_paths = Vec::new(); |
| 51 | + |
| 52 | + for mut arg in std::env::args().skip(1) { |
| 53 | + if arg.starts_with("--out_dir=") { |
| 54 | + out_dir = Some(arg.split_off("--out_dir=".len())); |
| 55 | + } else if arg.starts_with("--file=") { |
| 56 | + let val = arg.split_off("--file=".len()); |
| 57 | + let (dest, src) = val |
| 58 | + .split_once('=') |
| 59 | + .unwrap_or_else(|| panic!("--file value must be dest=src, got: {val}")); |
| 60 | + files.push((dest.to_owned(), src.to_owned())); |
| 61 | + } else if arg.starts_with("--env_out=") { |
| 62 | + env_out = Some(arg.split_off("--env_out=".len())); |
| 63 | + } else if arg.starts_with("--flags_out=") { |
| 64 | + flags_out = Some(arg.split_off("--flags_out=".len())); |
| 65 | + } else if arg.starts_with("--link_flags=") { |
| 66 | + link_flags_out = Some(arg.split_off("--link_flags=".len())); |
| 67 | + } else if arg.starts_with("--link_search_paths=") { |
| 68 | + link_search_paths_out = Some(arg.split_off("--link_search_paths=".len())); |
| 69 | + } else if arg.starts_with("--dep_env_out=") { |
| 70 | + dep_env_out = Some(arg.split_off("--dep_env_out=".len())); |
| 71 | + } else if arg.starts_with("--rustc_flag=") { |
| 72 | + rustc_flags.push(arg.split_off("--rustc_flag=".len())); |
| 73 | + } else if arg.starts_with("--rustc_env=") { |
| 74 | + rustc_envs.push(arg.split_off("--rustc_env=".len())); |
| 75 | + } else if arg.starts_with("--dep_env=") { |
| 76 | + dep_envs.push(arg.split_off("--dep_env=".len())); |
| 77 | + } else if arg.starts_with("--link_flag=") { |
| 78 | + link_flags.push(arg.split_off("--link_flag=".len())); |
| 79 | + } else if arg.starts_with("--link_search_path=") { |
| 80 | + link_search_paths.push(arg.split_off("--link_search_path=".len())); |
| 81 | + } else { |
| 82 | + panic!("cargo_build_info_runner: unknown argument: {arg}"); |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + Args { |
| 87 | + out_dir: out_dir.expect("--out_dir is required"), |
| 88 | + files, |
| 89 | + env_out: env_out.expect("--env_out is required"), |
| 90 | + flags_out: flags_out.expect("--flags_out is required"), |
| 91 | + link_flags_out: link_flags_out.expect("--link_flags is required"), |
| 92 | + link_search_paths_out: link_search_paths_out.expect("--link_search_paths is required"), |
| 93 | + dep_env_out: dep_env_out.expect("--dep_env_out is required"), |
| 94 | + rustc_flags, |
| 95 | + rustc_envs, |
| 96 | + dep_envs, |
| 97 | + link_flags, |
| 98 | + link_search_paths, |
| 99 | + } |
| 100 | + } |
| 101 | +} |
| 102 | + |
| 103 | +fn write_lines(path: &str, lines: &[String]) { |
| 104 | + let content = if lines.is_empty() { |
| 105 | + String::new() |
| 106 | + } else { |
| 107 | + lines.join("\n") |
| 108 | + }; |
| 109 | + fs::write(path, content).unwrap_or_else(|e| panic!("Failed to write {path}: {e}")); |
| 110 | +} |
| 111 | + |
| 112 | +fn main() { |
| 113 | + let args = Args::parse(); |
| 114 | + |
| 115 | + fs::create_dir_all(&args.out_dir) |
| 116 | + .unwrap_or_else(|e| panic!("Failed to create out_dir {:?}: {e}", args.out_dir)); |
| 117 | + |
| 118 | + if args.files.is_empty() { |
| 119 | + fs::write(Path::new(&args.out_dir).join(".empty"), "") |
| 120 | + .unwrap_or_else(|e| panic!("Failed to write .empty sentinel: {e}")); |
| 121 | + } |
| 122 | + |
| 123 | + for (dest_name, src_path) in &args.files { |
| 124 | + let dest = Path::new(&args.out_dir).join(dest_name); |
| 125 | + if let Some(parent) = dest.parent() { |
| 126 | + fs::create_dir_all(parent) |
| 127 | + .unwrap_or_else(|e| panic!("Failed to create parent dir {:?}: {e}", parent)); |
| 128 | + } |
| 129 | + fs::copy(src_path, &dest) |
| 130 | + .unwrap_or_else(|e| panic!("Failed to copy {:?} -> {:?}: {e}", src_path, dest)); |
| 131 | + } |
| 132 | + |
| 133 | + write_lines(&args.flags_out, &args.rustc_flags); |
| 134 | + write_lines(&args.env_out, &args.rustc_envs); |
| 135 | + write_lines(&args.dep_env_out, &args.dep_envs); |
| 136 | + write_lines(&args.link_flags_out, &args.link_flags); |
| 137 | + |
| 138 | + let search_paths: Vec<String> = args |
| 139 | + .link_search_paths |
| 140 | + .iter() |
| 141 | + .map(|p| format!("-Lnative=${{pwd}}/{p}")) |
| 142 | + .collect(); |
| 143 | + write_lines(&args.link_search_paths_out, &search_paths); |
| 144 | +} |
0 commit comments