fn generate_compile_commands()

in src/compiler/msvc.rs [1038:1122]


fn generate_compile_commands(
    path_transformer: &mut dist::PathTransformer,
    executable: &Path,
    parsed_args: &ParsedArguments,
    cwd: &Path,
    env_vars: &[(OsString, OsString)],
) -> Result<(
    SingleCompileCommand,
    Option<dist::CompileCommand>,
    Cacheable,
)> {
    #[cfg(not(feature = "dist-client"))]
    let _ = path_transformer;

    trace!("compile");
    let out_file = match parsed_args.outputs.get("obj") {
        Some(obj) => &obj.path,
        None => bail!("Missing object file output"),
    };

    // See if this compilation will produce a PDB.
    let cacheable = parsed_args
        .outputs
        .get("pdb")
        .map_or(Cacheable::Yes, |pdb| {
            // If the PDB exists, we don't know if it's shared with another
            // compilation. If it is, we can't cache.
            if Path::new(&cwd).join(pdb.path.clone()).exists() {
                Cacheable::No
            } else {
                Cacheable::Yes
            }
        });

    let mut fo = OsString::from("-Fo");
    fo.push(out_file);

    let mut arguments: Vec<OsString> = vec![parsed_args.compilation_flag.clone(), fo];
    arguments.extend_from_slice(&parsed_args.preprocessor_args);
    arguments.extend_from_slice(&parsed_args.dependency_args);
    arguments.extend_from_slice(&parsed_args.unhashed_args);
    arguments.extend_from_slice(&parsed_args.common_args);
    if parsed_args.double_dash_input {
        arguments.push("--".into());
    }
    arguments.push(parsed_args.input.clone().into());
    let command = SingleCompileCommand {
        executable: executable.to_owned(),
        arguments,
        env_vars: env_vars.to_owned(),
        cwd: cwd.to_owned(),
    };

    #[cfg(not(feature = "dist-client"))]
    let dist_command = None;
    #[cfg(feature = "dist-client")]
    let dist_command = (|| {
        // http://releases.llvm.org/6.0.0/tools/clang/docs/UsersManual.html#clang-cl
        // TODO: Use /T... for language?
        let mut fo = String::from("-Fo");
        fo.push_str(&path_transformer.as_dist(out_file)?);

        let mut arguments: Vec<String> =
            vec![parsed_args.compilation_flag.clone().into_string().ok()?, fo];
        // It's important to avoid preprocessor_args because of things like /FI which
        // forcibly includes another file. This does mean we're potentially vulnerable
        // to misidentification of flags like -DYNAMICBASE (though in that specific
        // case we're safe as it only applies to link time, which sccache avoids).
        arguments.extend(dist::osstrings_to_strings(&parsed_args.common_args)?);

        if parsed_args.double_dash_input {
            arguments.push("--".into());
        }
        arguments.push(path_transformer.as_dist(&parsed_args.input)?);

        Some(dist::CompileCommand {
            executable: path_transformer.as_dist(executable)?,
            arguments,
            env_vars: dist::osstring_tuples_to_strings(env_vars)?,
            cwd: path_transformer.as_dist(cwd)?,
        })
    })();

    Ok((command, dist_command, cacheable))
}