-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support crate-type=bin and --tests with dependencies #1260
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
da756cf
Support crate-type=bin and --tests with dependencies
tedinski 3ffa00f
Update kani-compiler/src/codegen_cprover_gotoc/compiler_interface.rs
tedinski a8bfed1
fix comments
tedinski edc6148
Merge remote-tracking branch 'origin/main' into crate-type-bin
tedinski 3e93e79
remove use of ranlib, which caused additional warnings on macos
tedinski 165593e
Merge branch 'main' into crate-type-bin
tedinski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
// | ||
// Modifications Copyright Kani Contributors | ||
// See GitHub history for details. | ||
// This file is a lightly modified version of upstream rustc: | ||
// compiler/rustc_codegen_cranelift/src/archive.rs | ||
|
||
// Along with lifting the deps: | ||
// object = { version = "0.27.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } | ||
// ar = "0.8.0" | ||
|
||
// Also: I removed all mentions of 'ranlib' which caused issues on macos. | ||
// We don't actually need these to be passed to a real linker anyway. | ||
// 'ranlib' is about building a global symbol table out of all the object | ||
// files in the archive, and we just don't put object files in our archives. | ||
|
||
//! Creation of ar archives like for the lib and staticlib crate type | ||
|
||
use std::fs::File; | ||
use std::io::{self, Read, Seek}; | ||
use std::path::{Path, PathBuf}; | ||
|
||
use rustc_codegen_ssa::back::archive::ArchiveBuilder; | ||
use rustc_session::Session; | ||
|
||
use object::read::archive::ArchiveFile; | ||
use object::ReadCache; | ||
|
||
#[derive(Debug)] | ||
enum ArchiveEntry { | ||
FromArchive { archive_index: usize, file_range: (u64, u64) }, | ||
File(PathBuf), | ||
} | ||
|
||
pub(crate) struct ArArchiveBuilder<'a> { | ||
sess: &'a Session, | ||
dst: PathBuf, | ||
use_gnu_style_archive: bool, | ||
|
||
src_archives: Vec<File>, | ||
// Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at | ||
// the end of an archive for linkers to not get confused. | ||
entries: Vec<(Vec<u8>, ArchiveEntry)>, | ||
} | ||
|
||
impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { | ||
fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self { | ||
let (src_archives, entries) = if let Some(input) = input { | ||
let read_cache = ReadCache::new(File::open(input).unwrap()); | ||
let archive = ArchiveFile::parse(&read_cache).unwrap(); | ||
let mut entries = Vec::new(); | ||
|
||
for entry in archive.members() { | ||
let entry = entry.unwrap(); | ||
entries.push(( | ||
entry.name().to_vec(), | ||
ArchiveEntry::FromArchive { archive_index: 0, file_range: entry.file_range() }, | ||
)); | ||
} | ||
|
||
(vec![read_cache.into_inner()], entries) | ||
} else { | ||
(vec![], Vec::new()) | ||
}; | ||
|
||
ArArchiveBuilder { | ||
sess, | ||
dst: output.to_path_buf(), | ||
use_gnu_style_archive: sess.target.archive_format == "gnu", | ||
src_archives, | ||
entries, | ||
} | ||
} | ||
|
||
fn src_files(&mut self) -> Vec<String> { | ||
self.entries.iter().map(|(name, _)| String::from_utf8(name.clone()).unwrap()).collect() | ||
} | ||
|
||
fn remove_file(&mut self, name: &str) { | ||
let index = self | ||
.entries | ||
.iter() | ||
.position(|(entry_name, _)| entry_name == name.as_bytes()) | ||
.expect("Tried to remove file not existing in src archive"); | ||
self.entries.remove(index); | ||
} | ||
|
||
fn add_file(&mut self, file: &Path) { | ||
self.entries.push(( | ||
file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), | ||
ArchiveEntry::File(file.to_owned()), | ||
)); | ||
} | ||
|
||
fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> | ||
where | ||
F: FnMut(&str) -> bool + 'static, | ||
{ | ||
let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?); | ||
let archive = ArchiveFile::parse(&read_cache).unwrap(); | ||
let archive_index = self.src_archives.len(); | ||
|
||
for entry in archive.members() { | ||
let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; | ||
let file_name = String::from_utf8(entry.name().to_vec()) | ||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; | ||
if !skip(&file_name) { | ||
self.entries.push(( | ||
file_name.into_bytes(), | ||
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, | ||
)); | ||
} | ||
} | ||
|
||
self.src_archives.push(read_cache.into_inner()); | ||
Ok(()) | ||
} | ||
|
||
fn build(mut self) { | ||
enum BuilderKind { | ||
Bsd(ar::Builder<File>), | ||
Gnu(ar::GnuBuilder<File>), | ||
} | ||
|
||
let sess = self.sess; | ||
|
||
let mut entries = Vec::new(); | ||
|
||
for (entry_name, entry) in self.entries { | ||
// FIXME only read the symbol table of the object files to avoid having to keep all | ||
// object files in memory at once, or read them twice. | ||
let data = match entry { | ||
ArchiveEntry::FromArchive { archive_index, file_range } => { | ||
// FIXME read symbols from symtab | ||
let src_read_cache = &mut self.src_archives[archive_index]; | ||
|
||
src_read_cache.seek(io::SeekFrom::Start(file_range.0)).unwrap(); | ||
let mut data = std::vec::from_elem(0, usize::try_from(file_range.1).unwrap()); | ||
src_read_cache.read_exact(&mut data).unwrap(); | ||
|
||
data | ||
} | ||
ArchiveEntry::File(file) => std::fs::read(file).unwrap_or_else(|err| { | ||
sess.fatal(&format!( | ||
"error while reading object file during archive building: {}", | ||
err | ||
)); | ||
}), | ||
}; | ||
|
||
entries.push((entry_name, data)); | ||
} | ||
|
||
let mut builder = if self.use_gnu_style_archive { | ||
BuilderKind::Gnu(ar::GnuBuilder::new( | ||
File::create(&self.dst).unwrap_or_else(|err| { | ||
sess.fatal(&format!( | ||
"error opening destination during archive building: {}", | ||
err | ||
)); | ||
}), | ||
entries.iter().map(|(name, _)| name.clone()).collect(), | ||
)) | ||
} else { | ||
BuilderKind::Bsd(ar::Builder::new(File::create(&self.dst).unwrap_or_else(|err| { | ||
sess.fatal(&format!("error opening destination during archive building: {}", err)); | ||
}))) | ||
}; | ||
|
||
// Add all files | ||
for (entry_name, data) in entries.into_iter() { | ||
let header = ar::Header::new(entry_name, data.len() as u64); | ||
match builder { | ||
BuilderKind::Bsd(ref mut builder) => builder.append(&header, &mut &*data).unwrap(), | ||
BuilderKind::Gnu(ref mut builder) => builder.append(&header, &mut &*data).unwrap(), | ||
} | ||
} | ||
|
||
// Finalize archive | ||
std::mem::drop(builder); | ||
} | ||
|
||
fn inject_dll_import_lib( | ||
&mut self, | ||
_lib_name: &str, | ||
_dll_imports: &[rustc_session::cstore::DllImport], | ||
_tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir, | ||
) { | ||
unimplemented!("injecting dll imports is not supported"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,19 @@ pub fn alter_extension(path: &Path, ext: &str) -> PathBuf { | |
path.with_extension(ext) | ||
} | ||
|
||
/// Attempt to guess the rlib name for rust source file. | ||
/// This is only used by 'kani', never 'cargo-kani', so we hopefully don't have too many corner | ||
/// cases to deal with. | ||
/// In rustc, you can find some code dealing this this naming in: | ||
/// compiler/rustc_codegen_ssa/src/back/link.rs | ||
pub fn guess_rlib_name(path: &Path) -> PathBuf { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a more reliable way to get the rlib name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not as far as I can tell, will at least add a quick ref to rustc sources... |
||
let basedir = path.parent().unwrap_or(Path::new(".")); | ||
let stem = path.file_stem().expect("has filename").to_str().expect("utf-8 filename"); | ||
let rlib_name = format!("lib{}.rlib", stem.replace('-', "_")); | ||
|
||
basedir.join(rlib_name) | ||
} | ||
|
||
/// Add an extension to an existing file path (amazingly Rust doesn't support this well) | ||
pub fn append_path(path: &Path, ext: &str) -> PathBuf { | ||
let mut str = path.to_owned().into_os_string(); | ||
|
@@ -90,6 +103,14 @@ mod tests { | |
assert_eq!(alter_extension(&q, "symtab.json"), PathBuf::from("file.more.symtab.json")); | ||
} | ||
|
||
#[test] | ||
fn check_guess_rlib_name() { | ||
assert_eq!(guess_rlib_name(Path::new("mycrate.rs")), PathBuf::from("libmycrate.rlib")); | ||
assert_eq!(guess_rlib_name(Path::new("my-crate.rs")), PathBuf::from("libmy_crate.rlib")); | ||
assert_eq!(guess_rlib_name(Path::new("./foo.rs")), PathBuf::from("./libfoo.rlib")); | ||
assert_eq!(guess_rlib_name(Path::new("a/b/foo.rs")), PathBuf::from("a/b/libfoo.rlib")); | ||
} | ||
|
||
#[test] | ||
fn check_append_path() { | ||
assert_eq!(append_path(&PathBuf::from("./file"), "tar"), PathBuf::from("./file.tar")); | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want a tracking issue for the "FIXMEs" here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not our fixme, it's from the upstream file. I didn't remove it because I wanted to modify the file as minimally as possible.