Skip to content

Commit 2d1df7d

Browse files
committed
Implemented cargo build plan based compilation artifact discovery.
1 parent ea32a4a commit 2d1df7d

File tree

2 files changed

+60
-17
lines changed

2 files changed

+60
-17
lines changed

Cargo.toml

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ name = "rust-semverver"
2323
path = "src/bin/rust_semverver.rs"
2424

2525
[dependencies]
26-
cargo-semverver = "0.34"
27-
failure = "0.1"
26+
cargo = "0.32"
2827
crates-io = "0.20"
2928
env_logger = "0.6"
29+
failure = "0.1"
3030
log = "0.4"
31-
semver = "0.9"
3231
rand = "0.6"
32+
semver = "0.9"
33+
serde_json = "1.0.34"
3334

3435
[dev-dependencies]
3536
quickcheck = "0.7"

src/bin/cargo_semver.rs

+56-14
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
#![feature(rustc_private)]
22
#![feature(uniform_paths)]
3+
#![feature(set_stdio)]
34

45
extern crate getopts;
6+
extern crate serde_json;
57

8+
use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace};
69
use log::debug;
10+
use serde_json::Value;
711
use std::{
8-
io::Write,
912
env,
13+
io::BufReader,
14+
io::Write,
15+
fs::File,
1016
path::{Path, PathBuf},
1117
process::{Command, Stdio},
1218
};
13-
use cargo::core::{Package, PackageId, PackageSet, Source, SourceId, SourceMap, Workspace};
1419

1520
pub type Result<T> = cargo::util::CargoResult<T>;
1621

@@ -106,6 +111,9 @@ fn run(config: &cargo::Config, matches: &getopts::Matches, explain: bool) -> Res
106111
let (current_rlib, current_deps_output) = current.rlib_and_dep_output(config, &name, true)?;
107112
let (stable_rlib, stable_deps_output) = stable.rlib_and_dep_output(config, &name, false)?;
108113

114+
println!("current_rlib: {:?}", current_rlib);
115+
println!("stable_rlib: {:?}", stable_rlib);
116+
109117
if matches.opt_present("d") {
110118
println!(
111119
"--extern old={} -L{} --extern new={} -L{}",
@@ -335,7 +343,7 @@ impl<'a> WorkInfo<'a> {
335343
) -> Result<WorkInfo<'a>> {
336344
// TODO: fall back to locally cached package instance, or better yet, search for it
337345
// first.
338-
let package_ids = [PackageId::new(name, version, source.id)?];
346+
let package_ids = [PackageId::new(name, version, &source.id)?];
339347
debug!("(remote) package id: {:?}", package_ids[0]);
340348
let sources = {
341349
let mut s = SourceMap::new();
@@ -344,7 +352,7 @@ impl<'a> WorkInfo<'a> {
344352
};
345353

346354
let package_set = PackageSet::new(&package_ids, sources, config)?;
347-
let package = package_set.get_one(package_ids[0])?;
355+
let package = package_set.get_one(&package_ids[0])?;
348356
let workspace = Workspace::ephemeral(package.clone(), config, None, false)?;
349357

350358
Ok(Self {
@@ -360,21 +368,55 @@ impl<'a> WorkInfo<'a> {
360368
name: &str,
361369
current: bool,
362370
) -> Result<(PathBuf, PathBuf)> {
363-
let opts =
364-
cargo::ops::CompileOptions::new(config, cargo::core::compiler::CompileMode::Build)
365-
.unwrap();
371+
let mut opts =
372+
cargo::ops::CompileOptions::new(config, cargo::core::compiler::CompileMode::Build)?;
373+
// we need the build plan to find our build artifacts
374+
opts.build_config.build_plan = true;
375+
// TODO: this is where we could insert feature flag builds (or using the CLI mechanisms)
376+
377+
env::set_var("RUSTFLAGS",
378+
format!("-C metadata={}", if current { "new" } else { "old" }));
379+
380+
let mut outdir = env::temp_dir();
381+
outdir.push(&format!("cargo_semver_{}_{}", name, current));
382+
383+
// redirection gang
384+
let outfile = File::create(&outdir)?;
385+
let old_stdio = std::io::set_print(Some(Box::new(outfile)));
386+
387+
let _ = cargo::ops::compile(&self.workspace, &opts)?;
388+
389+
std::io::set_print(old_stdio);
390+
391+
// actually compile things now
392+
opts.build_config.build_plan = false;
366393

367-
env::set_var("RUSTFLAGS", format!("-C metadata={}", if current { "new" } else { "old" }));
368394
let compilation = cargo::ops::compile(&self.workspace, &opts)?;
369395
env::remove_var("RUSTFLAGS");
370396

371-
// TODO: use cargo metadata to fetch the rlib path here:
372-
let rlib = compilation.libraries[&self.package.package_id()]
373-
.iter()
374-
.find(|t| t.0.name() == name)
375-
.ok_or_else(|| failure::err_msg("lost a build artifact".to_owned()))?;
397+
let build_plan: Value =
398+
serde_json::from_reader(BufReader::new(File::open(&outdir)?))?;
399+
400+
// FIXME: yuck drilling
401+
if let Value::Object(m) = build_plan {
402+
if let Some(Value::Array(v)) = m.get("invocations") {
403+
for s in v {
404+
if let Value::Object(m2) = s {
405+
if let Some(Value::String(s2)) = m2.get("package_name") {
406+
if s2 != name { continue; }
407+
}
408+
409+
if let Some(Value::Array(v2)) = m2.get("outputs") {
410+
if let Some(Value::String(s)) = v2.get(0) {
411+
return Ok((PathBuf::from(s), compilation.deps_output));
412+
}
413+
}
414+
}
415+
}
416+
}
417+
}
376418

377-
Ok((rlib.1.clone(), compilation.deps_output))
419+
Err(failure::err_msg("lost build artifact".to_owned()))
378420
}
379421
}
380422

0 commit comments

Comments
 (0)