Skip to content

Commit

Permalink
Auto merge of #3361 - pwoolcoc:default-build-script, r=alexcrichton
Browse files Browse the repository at this point in the history
Assume `build.rs` in the same directory as `Cargo.toml` is a build script (unless explicitly told not to)

So, in May I posted a question in the #cargo IRC room: https://botbot.me/mozilla/cargo/2016-05-26/?msg=66770068&page=1

This PR does what was discussed there. If `cargo` sees a `build.rs` in the same directory as the `Cargo.toml`, it will assume `build.rs` is a build script unless `package.build = false`. Just for completeness I also made `build = true` mean the same as `build = "build.rs"` but I'm not sure if that is okay or not.
  • Loading branch information
bors committed Dec 7, 2016
2 parents 5e3221e + 1b99491 commit 333a798
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 2 deletions.
38 changes: 36 additions & 2 deletions src/cargo/util/toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,18 @@ pub struct TomlProfile {
panic: Option<String>,
}

#[derive(RustcDecodable, Clone, Debug)]
pub enum StringOrBool {
String(String),
Bool(bool),
}

#[derive(RustcDecodable)]
pub struct TomlProject {
name: String,
version: TomlVersion,
authors: Vec<String>,
build: Option<String>,
build: Option<StringOrBool>,
links: Option<String>,
exclude: Option<Vec<String>>,
include: Option<Vec<String>>,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -767,6 +773,34 @@ impl TomlManifest {
}
Ok(replace)
}

fn maybe_custom_build(&self,
build: &Option<StringOrBool>,
project_dir: &Path,
warnings: &mut Vec<String>)
-> Option<PathBuf> {
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.
Expand Down
82 changes: 82 additions & 0 deletions tests/build-script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

0 comments on commit 333a798

Please sign in to comment.