Skip to content

Commit 1b35617

Browse files
committed
Add new compile_intermediates function.
This new function can be used to just compile the files to a bunch of .o files.
1 parent 802399f commit 1b35617

File tree

2 files changed

+96
-42
lines changed

2 files changed

+96
-42
lines changed

src/lib.rs

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,48 +1131,7 @@ impl Build {
11311131
};
11321132
let dst = self.get_out_dir()?;
11331133

1134-
let mut objects = Vec::new();
1135-
for file in self.files.iter() {
1136-
let obj = if file.has_root() || file.components().any(|x| x == Component::ParentDir) {
1137-
// If `file` is an absolute path or might not be usable directly as a suffix due to
1138-
// using "..", use the `basename` prefixed with the `dirname`'s hash to ensure name
1139-
// uniqueness.
1140-
let basename = file
1141-
.file_name()
1142-
.ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "file_name() failure"))?
1143-
.to_string_lossy();
1144-
let dirname = file
1145-
.parent()
1146-
.ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "parent() failure"))?
1147-
.to_string_lossy();
1148-
let mut hasher = hash_map::DefaultHasher::new();
1149-
hasher.write(dirname.to_string().as_bytes());
1150-
dst.join(format!("{:016x}-{}", hasher.finish(), basename))
1151-
.with_extension("o")
1152-
} else {
1153-
dst.join(file).with_extension("o")
1154-
};
1155-
let obj = if !obj.starts_with(&dst) {
1156-
dst.join(obj.file_name().ok_or_else(|| {
1157-
Error::new(ErrorKind::IOError, "Getting object file details failed.")
1158-
})?)
1159-
} else {
1160-
obj
1161-
};
1162-
1163-
match obj.parent() {
1164-
Some(s) => fs::create_dir_all(s)?,
1165-
None => {
1166-
return Err(Error::new(
1167-
ErrorKind::IOError,
1168-
"Getting object file details failed.",
1169-
));
1170-
}
1171-
};
1172-
1173-
objects.push(Object::new(file.to_path_buf(), obj));
1174-
}
1175-
1134+
let objects = objects_from_files(self.files.iter().map(|v| &**v), &dst)?;
11761135
let print = PrintThread::new()?;
11771136

11781137
self.compile_objects(&objects, &print)?;
@@ -1316,6 +1275,33 @@ impl Build {
13161275
}
13171276
}
13181277

1278+
1279+
/// Run the compiler, generating intermediate files, but without linking
1280+
/// them into an archive file.
1281+
///
1282+
/// This will return a list of compiled object files, in the same order
1283+
/// as they were passed in as `file`/`files` methods.
1284+
pub fn compile_intermediates(&self) -> Vec<PathBuf> {
1285+
match self.try_compile_intermediates() {
1286+
Ok(v) => v,
1287+
Err(e) => fail(&e.message),
1288+
}
1289+
}
1290+
1291+
/// Run the compiler, generating intermediate files, but without linking
1292+
/// them into an archive file.
1293+
///
1294+
/// This will return a result instead of panicing; see `compile_intermediates()` for the complete description.
1295+
pub fn try_compile_intermediates(&self) -> Result<Vec<PathBuf>, Error> {
1296+
let dst = self.get_out_dir()?;
1297+
let objects = objects_from_files(self.files.iter().map(|v| &**v), &dst)?;
1298+
let print = PrintThread::new()?;
1299+
1300+
self.compile_objects(&objects, &print)?;
1301+
1302+
Ok(objects.into_iter().map(|v| v.dst).collect())
1303+
}
1304+
13191305
#[cfg(feature = "parallel")]
13201306
fn compile_objects(&self, objs: &[Object], print: &PrintThread) -> Result<(), Error> {
13211307
use std::cell::Cell;
@@ -3830,6 +3816,54 @@ fn wait_on_child(cmd: &Command, program: &str, child: &mut Child) -> Result<(),
38303816
}
38313817
}
38323818

3819+
/// Find the destination object path for each file in the input source files,
3820+
/// and store them in the output Object.
3821+
fn objects_from_files<'a, I: IntoIterator<Item = &'a Path>>(files: I, dst: &Path) -> Result<Vec<Object>, Error> {
3822+
let mut objects = Vec::new();
3823+
for file in files.into_iter() {
3824+
let obj = if file.has_root() || file.components().any(|x| x == Component::ParentDir) {
3825+
// If `file` is an absolute path or might not be usable directly as a suffix due to
3826+
// using "..", use the `basename` prefixed with the `dirname`'s hash to ensure name
3827+
// uniqueness.
3828+
let basename = file
3829+
.file_name()
3830+
.ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "file_name() failure"))?
3831+
.to_string_lossy();
3832+
let dirname = file
3833+
.parent()
3834+
.ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "parent() failure"))?
3835+
.to_string_lossy();
3836+
let mut hasher = hash_map::DefaultHasher::new();
3837+
hasher.write(dirname.to_string().as_bytes());
3838+
dst.join(format!("{:016x}-{}", hasher.finish(), basename))
3839+
.with_extension("o")
3840+
} else {
3841+
dst.join(file).with_extension("o")
3842+
};
3843+
let obj = if !obj.starts_with(&dst) {
3844+
dst.join(obj.file_name().ok_or_else(|| {
3845+
Error::new(ErrorKind::IOError, "Getting object file details failed.")
3846+
})?)
3847+
} else {
3848+
obj
3849+
};
3850+
3851+
match obj.parent() {
3852+
Some(s) => fs::create_dir_all(s)?,
3853+
None => {
3854+
return Err(Error::new(
3855+
ErrorKind::IOError,
3856+
"Getting object file details failed.",
3857+
));
3858+
}
3859+
};
3860+
3861+
objects.push(Object::new(file.to_path_buf(), obj));
3862+
}
3863+
3864+
Ok(objects)
3865+
}
3866+
38333867
#[cfg(feature = "parallel")]
38343868
fn try_wait_on_child(
38353869
cmd: &Command,

tests/test.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,3 +576,23 @@ fn clang_apple_tvsimulator() {
576576
test.cmd(0).must_have("-mappletvsimulator-version-min=9.0");
577577
}
578578
}
579+
580+
#[test]
581+
fn compile_intermediates() {
582+
let test = Test::gnu();
583+
let intermediates = test.gcc()
584+
.file("foo.c")
585+
.file("x86_64.asm")
586+
.file("x86_64.S")
587+
.asm_flag("--abc")
588+
.compile_intermediates();
589+
test.cmd(0).must_not_have("--abc");
590+
test.cmd(1).must_have("--abc");
591+
test.cmd(2).must_have("--abc");
592+
593+
assert_eq!(intermediates.len(), 3);
594+
595+
assert!(intermediates[0].display().to_string().contains("foo"));
596+
assert!(intermediates[1].display().to_string().contains("x86_64"));
597+
assert!(intermediates[2].display().to_string().contains("x86_64"));
598+
}

0 commit comments

Comments
 (0)