diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index 5e5dc93a669..18b4d4c6cfc 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -286,12 +286,18 @@ pub struct TomlProfile { panic: Option, } +#[derive(RustcDecodable, Clone, Debug)] +pub enum StringOrBool { + String(String), + Bool(bool), +} + #[derive(RustcDecodable)] pub struct TomlProject { name: String, version: TomlVersion, authors: Vec, - build: Option, + build: Option, links: Option, exclude: Option>, include: Option>, @@ -540,7 +546,7 @@ impl TomlManifest { } // processing the custom build script - let new_build = project.build.as_ref().map(PathBuf::from); + let new_build = self.maybe_custom_build(&project.build, &layout.root, &mut warnings); // Get targets let targets = normalize(&lib, @@ -767,6 +773,34 @@ impl TomlManifest { } Ok(replace) } + + fn maybe_custom_build(&self, + build: &Option, + project_dir: &Path, + warnings: &mut Vec) + -> Option { + let build_rs = project_dir.join("build.rs"); + match *build { + Some(StringOrBool::Bool(false)) => None, // explicitly no build script + Some(StringOrBool::Bool(true)) => Some(build_rs.into()), + Some(StringOrBool::String(ref s)) => Some(PathBuf::from(s)), + None => { + match fs::metadata(&build_rs) { + // Enable this after the warning has been visible for some time + // Ok(ref e) if e.is_file() => Some(build_rs.into()), + Ok(ref e) if e.is_file() => { + warnings.push("`build.rs` files in the same directory \ + as your `Cargo.toml` will soon be treated \ + as build scripts. Add `build = false` to \ + your `Cargo.toml` to prevent this".into()); + None + }, + Ok(_) => None, + Err(_) => None, + } + } + } + } } /// Will check a list of toml targets, and make sure the target names are unique within a vector. diff --git a/tests/build-script.rs b/tests/build-script.rs index 46d8e144063..01ea55f9a51 100644 --- a/tests/build-script.rs +++ b/tests/build-script.rs @@ -2334,3 +2334,85 @@ fn switch_features_rerun() { assert_that(build.cargo("run").arg("-v").arg("--features=foo"), execs().with_status(0).with_stdout("foo\n")); } + +#[test] +fn assume_build_script_when_build_rs_present() { + let p = project("builder") + .file("Cargo.toml", r#" + [package] + name = "builder" + version = "0.0.1" + authors = [] + "#) + .file("src/main.rs", r#" + use std::path::Path; + fn main() { + let f = env!("OUT_DIR"); + assert!( + ! Path::new(f).join("output").exists() + ); + } + "#) + .file("build.rs", r#" + use std::env; + use std::fs::File; + use std::io::Write; + use std::path::Path; + + fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = Path::new(&out_dir).join("output"); + let mut f = File::create(&out_dir).unwrap(); + f.write_all(b"foo").unwrap(); + } + "#); + p.build(); + + assert_that(p.cargo("run").arg("-v"), + execs().with_status(0).with_stderr("\ +warning: `build.rs` files in the same directory as your `Cargo.toml` will soon be treated \ +as build scripts. Add `build = false` to your `Cargo.toml` to prevent this + Compiling builder v0.0.1 ([..]) + Running [..] + Finished [..] + Running [..] +")); +} + +#[test] +fn if_build_set_to_false_dont_treat_build_rs_as_build_script() { + let p = project("builder") + .file("Cargo.toml", r#" + [package] + name = "builder" + version = "0.0.1" + authors = [] + build = false + "#) + .file("src/main.rs", r#" + use std::path::Path; + fn main() { + let f = env!("OUT_DIR"); + assert!( + ! Path::new(f).join("output").exists() + ) + } + "#) + .file("build.rs", r#" + use std::env; + use std::fs::File; + use std::io::Write; + use std::path::Path; + + fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = Path::new(&out_dir).join("output"); + let mut f = File::create(&out_dir).unwrap(); + f.write_all(b"foo").unwrap(); + } + "#); + p.build(); + + assert_that(p.cargo("run").arg("-v"), + execs().with_status(0)); +}