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;
// 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(())
});
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 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:"
}
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));
})
}
+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));
{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));
+});