use std::fs::File; use std::path::Path; use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; use rustc::session::config; use rustc::ty::TyCtxt; use rustc_codegen_ssa::METADATA_FILENAME; use rustc_data_structures::owning_ref::{self, OwningRef}; use rustc_data_structures::rustc_erase_owner; use rustc_target::spec::Target; use crate::backend::Product; pub struct CraneliftMetadataLoader; impl MetadataLoader for CraneliftMetadataLoader { fn get_rlib_metadata( &self, _target: &Target, path: &Path, ) -> Result, String> { let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?); // Iterate over all entries in the archive: while let Some(entry_result) = archive.next_entry() { let mut entry = entry_result.map_err(|e| format!("{:?}", e))?; if entry.header().identifier() == METADATA_FILENAME.as_bytes() { let mut buf = Vec::new(); ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?; let buf: OwningRef, [u8]> = OwningRef::new(buf).into(); return Ok(rustc_erase_owner!(buf.map_owner_box())); } } Err("couldn't find metadata entry".to_string()) //self.get_dylib_metadata(target, path) } fn get_dylib_metadata( &self, _target: &Target, path: &Path, ) -> Result, String> { use object::Object; let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?; let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?; let buf = file .section_data_by_name(".rustc") .ok_or("no .rustc section")? .into_owned(); let buf: OwningRef, [u8]> = OwningRef::new(buf).into(); Ok(rustc_erase_owner!(buf.map_owner_box())) } } // Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112 pub fn write_metadata(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata { use flate2::write::DeflateEncoder; use flate2::Compression; use std::io::Write; #[derive(PartialEq, Eq, PartialOrd, Ord)] enum MetadataKind { None, Uncompressed, Compressed, } let kind = tcx .sess .crate_types .borrow() .iter() .map(|ty| match *ty { config::CrateType::Executable | config::CrateType::Staticlib | config::CrateType::Cdylib => MetadataKind::None, config::CrateType::Rlib => MetadataKind::Uncompressed, config::CrateType::Dylib | config::CrateType::ProcMacro => MetadataKind::Compressed, }) .max() .unwrap_or(MetadataKind::None); if kind == MetadataKind::None { return EncodedMetadata::new(); } let metadata = tcx.encode_metadata(); if kind == MetadataKind::Uncompressed { return metadata; } assert!(kind == MetadataKind::Compressed); let mut compressed = tcx.metadata_encoding_version(); DeflateEncoder::new(&mut compressed, Compression::fast()) .write_all(&metadata.raw_data) .unwrap(); product.add_rustc_section( rustc::middle::exported_symbols::metadata_symbol_name(tcx), compressed, tcx.sess.target.target.options.is_like_osx, ); metadata }