Skip to content
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

Don't require all build script output to be utf-8 #2560

Merged
merged 1 commit into from
Apr 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/cargo/ops/cargo_rustc/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::str;
use std::sync::{Mutex, Arc};

use core::PackageId;
use util::{CargoResult, human, Human};
use util::{CargoResult, Human};
use util::{internal, ChainError, profile, paths};
use util::Freshness;

Expand Down Expand Up @@ -213,10 +213,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
// This is also the location where we provide feedback into the build
// state informing what variables were discovered via our script as
// well.
let output = try!(str::from_utf8(&output.stdout).map_err(|_| {
human("build script output was not valid utf-8")
}));
let parsed_output = try!(BuildOutput::parse(output, &pkg_name));
let parsed_output = try!(BuildOutput::parse(&output.stdout, &pkg_name));
build_state.insert(id, kind, parsed_output);
Ok(())
});
Expand Down Expand Up @@ -270,21 +267,25 @@ impl BuildState {

impl BuildOutput {
pub fn parse_file(path: &Path, pkg_name: &str) -> CargoResult<BuildOutput> {
let contents = try!(paths::read(path));
let contents = try!(paths::read_bytes(path));
BuildOutput::parse(&contents, pkg_name)
}

// Parses the output of a script.
// The `pkg_name` is used for error messages.
pub fn parse(input: &str, pkg_name: &str) -> CargoResult<BuildOutput> {
pub fn parse(input: &[u8], pkg_name: &str) -> CargoResult<BuildOutput> {
let mut library_paths = Vec::new();
let mut library_links = Vec::new();
let mut cfgs = Vec::new();
let mut metadata = Vec::new();
let mut rerun_if_changed = Vec::new();
let whence = format!("build script of `{}`", pkg_name);

for line in input.lines() {
for line in input.split(|b| *b == b'\n') {
let line = match str::from_utf8(line) {
Ok(line) => line.trim(),
Err(..) => continue,
};
let mut iter = line.splitn(2, ':');
if iter.next() != Some("cargo") {
// skip this line since it doesn't start with "cargo:"
Expand Down
13 changes: 12 additions & 1 deletion src/cargo/util/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn without_prefix<'a>(a: &'a Path, b: &'a Path) -> Option<&'a Path> {
}

pub fn read(path: &Path) -> CargoResult<String> {
(|| -> CargoResult<String> {
(|| -> CargoResult<_> {
let mut ret = String::new();
let mut f = try!(File::open(path));
try!(f.read_to_string(&mut ret));
Expand All @@ -78,6 +78,17 @@ pub fn read(path: &Path) -> CargoResult<String> {
})
}

pub fn read_bytes(path: &Path) -> CargoResult<Vec<u8>> {
(|| -> CargoResult<_> {
let mut ret = Vec::new();
let mut f = try!(File::open(path));
try!(f.read_to_end(&mut ret));
Ok(ret)
})().map_err(human).chain_error(|| {
human(format!("failed to read `{}`", path.display()))
})
}

pub fn write(path: &Path, contents: &[u8]) -> CargoResult<()> {
(|| -> CargoResult<()> {
let mut f = try!(File::create(path));
Expand Down
33 changes: 33 additions & 0 deletions tests/test_cargo_compile_custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1866,3 +1866,36 @@ test!(please_respect_the_dag {
{running} `rustc [..] -L native=foo -L native=bar[..]`
", running = RUNNING)));
});

test!(non_utf8_output {
let p = project("foo")
.file("Cargo.toml", r#"
[project]
name = "foo"
version = "0.5.0"
authors = []
build = "build.rs"
"#)
.file("build.rs", r#"
use std::io::prelude::*;

fn main() {
let mut out = std::io::stdout();
// print something that's not utf8
out.write_all(b"\xff\xff\n").unwrap();

// now print some cargo metadata that's utf8
println!("cargo:rustc-cfg=foo");

// now print more non-utf8
out.write_all(b"\xff\xff\n").unwrap();
}
"#)
.file("src/main.rs", r#"
#[cfg(foo)]
fn main() {}
"#);

assert_that(p.cargo_process("build").arg("-v"),
execs().with_status(0));
});