in src/compiler/c.rs [1307:1412]
fn write_pkg(self: Box<Self>, f: fs::File) -> Result<()> {
use std::os::unix::ffi::OsStringExt;
info!("Generating toolchain {}", self.executable.display());
let mut package_builder = pkg::ToolchainPackageBuilder::new();
package_builder.add_common()?;
package_builder.add_executable_and_deps(self.executable.clone())?;
// Helper to use -print-file-name and -print-prog-name to look up
// files by path.
let named_file = |kind: &str, name: &str| -> Option<PathBuf> {
let mut output = process::Command::new(&self.executable)
.arg(format!("-print-{}-name={}", kind, name))
.output()
.ok()?;
debug!(
"find named {} {} output:\n{}\n===\n{}",
kind,
name,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
if !output.status.success() {
debug!("exit failure");
return None;
}
// Remove the trailing newline (if present)
if output.stdout.last() == Some(&b'\n') {
output.stdout.pop();
}
// Create our PathBuf from the raw bytes. Assume that relative
// paths can be found via PATH.
let path: PathBuf = OsString::from_vec(output.stdout).into();
if path.is_absolute() {
Some(path)
} else {
which::which(path).ok()
}
};
// Helper to add a named file/program by to the package.
// We ignore the case where the file doesn't exist, as we don't need it.
let add_named_prog =
|builder: &mut pkg::ToolchainPackageBuilder, name: &str| -> Result<()> {
if let Some(path) = named_file("prog", name) {
builder.add_executable_and_deps(path)?;
}
Ok(())
};
let add_named_file =
|builder: &mut pkg::ToolchainPackageBuilder, name: &str| -> Result<()> {
if let Some(path) = named_file("file", name) {
builder.add_file(path)?;
}
Ok(())
};
// Add basic |as| and |objcopy| programs.
add_named_prog(&mut package_builder, "as")?;
add_named_prog(&mut package_builder, "objcopy")?;
// Linker configuration.
if Path::new("/etc/ld.so.conf").is_file() {
package_builder.add_file("/etc/ld.so.conf".into())?;
}
// Compiler-specific handling
match self.kind {
CCompilerKind::Clang => {
// Clang uses internal header files, so add them.
if let Some(limits_h) = named_file("file", "include/limits.h") {
info!("limits_h = {}", limits_h.display());
package_builder.add_dir_contents(limits_h.parent().unwrap())?;
}
}
CCompilerKind::Gcc => {
// Various external programs / files which may be needed by gcc
add_named_prog(&mut package_builder, "cc1")?;
add_named_prog(&mut package_builder, "cc1plus")?;
add_named_file(&mut package_builder, "specs")?;
add_named_file(&mut package_builder, "liblto_plugin.so")?;
}
CCompilerKind::Cicc
| CCompilerKind::CudaFE
| CCompilerKind::Ptxas
| CCompilerKind::Nvcc => {}
CCompilerKind::Nvhpc => {
// Various programs called by the nvc nvc++ front end.
add_named_file(&mut package_builder, "cpp1")?;
add_named_file(&mut package_builder, "cpp2")?;
add_named_file(&mut package_builder, "opt")?;
add_named_prog(&mut package_builder, "llc")?;
add_named_prog(&mut package_builder, "acclnk")?;
}
_ => unreachable!(),
}
// Bundle into a compressed tarfile.
package_builder.into_compressed_tar(f)
}