Skip to content
Open
1 change: 1 addition & 0 deletions psm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ readme = "README.mkd"

[build-dependencies]
cc = "1.1.22"
ar_archive_writer = "0.2.0"
57 changes: 54 additions & 3 deletions psm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,61 @@ fn main() {
// directly to `ar` to assemble an archive. Otherwise we're actually
// compiling the source assembly file.
if asm.ends_with(".o") {
cfg.object(asm);
use ar_archive_writer::{write_archive_to_stream, NewArchiveMember, ArchiveKind};
use std::fs::{read, metadata};
use std::path::PathBuf;
use std::io::Cursor;

let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable not set");
let output_path = PathBuf::from(&out_dir).join("libpsm_s.a");

let object_data = read(asm).expect("Failed to read object file");
let file_metadata = metadata(asm).expect("Failed to read file metadata");

// Extract file metadata
let mtime = file_metadata.modified().ok()
.and_then(|time| time.duration_since(std::time::UNIX_EPOCH).ok())
.map(|duration| duration.as_secs())
.unwrap_or(0);

#[cfg(unix)]
let (uid, gid, perms) = {
use std::os::unix::fs::MetadataExt;
(file_metadata.uid(), file_metadata.gid(), file_metadata.mode())
};

#[cfg(not(unix))]
let (uid, gid, perms) = (0, 0, 0o644);

let filename = asm.rsplit('/').next().unwrap_or(asm);
let member = NewArchiveMember {
buf: Box::new(object_data),
get_symbols: |_data: &[u8], _callback: &mut dyn FnMut(&[u8]) -> Result<(), std::io::Error>| Ok(true),
member_name: filename.to_string(),
mtime,
uid,
gid,
perms,
};

let mut output_bytes = Cursor::new(Vec::new());
write_archive_to_stream(
&mut output_bytes,
&[member],
// Unfortunately, getDefaultKind() is not available in ar_archive_writer
// however looking at the llvm-ar source it looks like for wasm32-any-any
// it falls through to Gnu https://llvm.org/doxygen/Object_2Archive_8cpp_source.html
ArchiveKind::Gnu,
false,
).expect("Failed to write archive");

std::fs::write(&output_path, output_bytes.into_inner()).expect("Failed to write archive file");

println!("cargo:rustc-link-search=native={}", out_dir);
println!("cargo:rustc-link-lib=static=psm_s");
} else {
cfg.file(asm);
cfg.compile("libpsm_s.a");
}

cfg.compile("libpsm_s.a");
}
}
Loading