in src/compiler/nvcc.rs [1029:1115]
fn fold_env_vars_or_split_into_exe_and_args(
re: &Regex,
env_vars: &mut Vec<(OsString, OsString)>,
env_var_re_map: &mut HashMap<String, regex::Regex>,
cwd: &Path,
line: &str,
host_compiler: &NvccHostCompiler,
) -> Result<Option<(PathBuf, Vec<String>)>> {
fn envvar_in_shell_format(var: &str) -> String {
if cfg!(target_os = "windows") {
format!("%{}%", var) // %CICC_PATH%
} else {
format!("${}", var) // $CICC_PATH
}
}
fn envvar_in_shell_format_re(var: &str) -> Regex {
Regex::new(
&(if cfg!(target_os = "windows") {
regex::escape(&envvar_in_shell_format(var))
} else {
regex::escape(&envvar_in_shell_format(var)) + r"[^\w]"
}),
)
.unwrap()
}
// Intercept the environment variable lines and add them to the env_vars list
if let Some(var) = re.captures(line) {
let (_, [var, val]) = var.extract();
env_var_re_map
.entry(var.to_owned())
.or_insert_with_key(|var| envvar_in_shell_format_re(var));
env_vars.push((var.into(), val.into()));
return Ok(None);
}
// The rest of the lines are subcommands, so parse into a vec of [cmd, args..]
let mut line = if cfg!(target_os = "windows") {
let line = line
.replace("\"\"", "\"")
.replace(r"\\?\", "")
.replace('\\', "/")
.replace(r"//?/", "");
match host_compiler {
NvccHostCompiler::Msvc => line.replace(" -E ", " -P ").replace(" > ", " -Fi"),
_ => line,
}
} else {
line.to_owned()
};
// Expand envvars in nvcc subcommands, i.e. "$CICC_PATH/cicc ..." or "%CICC_PATH%/cicc"
if let Some(env_vars) = dist::osstring_tuples_to_strings(env_vars) {
for (var, val) in env_vars {
if let Some(re) = env_var_re_map.get(&var) {
if re.is_match(&line) {
line = line.replace(&envvar_in_shell_format(&var), &val);
}
}
}
}
let args = match shlex::split(&line) {
Some(args) => args,
None => return Err(anyhow!("Could not parse shell line")),
};
let (exe, args) = match args.split_first() {
Some(exe_and_args) => exe_and_args,
None => return Err(anyhow!("Could not split shell line")),
};
let env_path = env_vars
.iter()
.find(|(k, _)| k == "PATH")
.map(|(_, p)| p.to_owned())
.unwrap();
let exe = which_in(exe, env_path.into(), cwd)?;
Ok(Some((exe.clone(), args.to_vec())))
}