use std::{
fs,
path::{Path, PathBuf},
process::Command,
};
use crate::{
compiler_wrapper::CompilerKind, error::Error, lto::marker_compile_args,
utils::embed_bitcode_filepath_to_object_file,
};
pub(crate) fn build_marker_object(
bitcode: &Path,
dir: &Path,
compiler: &Path,
kind: CompilerKind,
compile_args: &[String],
) -> Result<PathBuf, Error> {
let extension = match kind {
CompilerKind::Clang => "c",
CompilerKind::ClangXX => "cpp",
};
let source = dir.join(format!("rllvm_marker.{extension}"));
fs::write(
&source,
b"typedef int rllvm_marker_empty_translation_unit;\n",
)?;
let marker = dir.join("rllvm_marker.o");
let status = Command::new(compiler)
.args(marker_compile_args(compile_args))
.arg("-c")
.arg(&source)
.arg("-o")
.arg(&marker)
.status()?;
if !status.success() {
return Err(Error::ExecutionFailure(format!(
"Failed to build the rllvm marker object with {compiler:?}: exit_status={status}"
)));
}
embed_bitcode_filepath_to_object_file::<&Path>(bitcode, &marker, None)?;
Ok(marker)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::extract_bitcode_filepaths_from_object_file;
fn placeholder_bitcode(dir: &Path) -> PathBuf {
let bitcode = dir.join("crate.bc");
fs::write(&bitcode, b"placeholder").expect("failed to write the placeholder bitcode");
bitcode
}
#[test]
fn marker_object_carries_the_bitcode_path() {
let tmp = tempfile::tempdir().unwrap();
let bitcode = placeholder_bitcode(tmp.path());
let clang = crate::config::try_rllvm_config()
.expect("configuration")
.clang_filepath()
.clone();
let marker = build_marker_object(&bitcode, tmp.path(), &clang, CompilerKind::Clang, &[])
.expect("marker built");
let paths =
extract_bitcode_filepaths_from_object_file(&marker).expect("marker carries a section");
assert_eq!(paths, vec![bitcode]);
}
}