Skip to content
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
3 changes: 0 additions & 3 deletions src/bin/cargo-build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
}))
};

let update = options.update_remotes;
let jobs = options.jobs;

let env = if options.release {
"release"
} else {
Expand Down
9 changes: 7 additions & 2 deletions src/bin/cargo-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern crate serialize;
extern crate hammer;

use std::os;
use std::io::fs;
use std::io::{UserExecute, fs};

use cargo::ops;
use cargo::{execute_main_without_stdin};
Expand Down Expand Up @@ -65,7 +65,7 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
// TODO: The proper fix is to have target knows its expected
// output and only run expected executables.
if file.display().to_str().as_slice().contains("dSYM") { continue; }
if !file.is_file() { continue; }
if !is_executable(&file) { continue; }

try!(util::process(file).exec().map_err(|e| {
CliError::from_boxed(e.box_error(), 1)
Expand All @@ -74,3 +74,8 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {

Ok(None)
}

fn is_executable(path: &Path) -> bool {
if !path.is_file() { return false; }
path.stat().map(|stat| stat.perm.intersects(UserExecute)).unwrap_or(false)
}
4 changes: 4 additions & 0 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,10 @@ impl Target {
}
}

pub fn get_name<'a>(&'a self) -> &'a str {
self.name.as_slice()
}

pub fn get_path<'a>(&'a self) -> &'a Path {
&self.path
}
Expand Down
11 changes: 7 additions & 4 deletions src/cargo/ops/cargo_read_manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use util;
use core::{Package,Manifest,SourceId};
use util::{CargoResult, human};
use util::important_paths::find_project_manifest_exact;
use util::toml::{Layout, project_layout};

pub fn read_manifest(contents: &[u8], source_id: &SourceId)
pub fn read_manifest(contents: &[u8], layout: Layout, source_id: &SourceId)
-> CargoResult<(Manifest, Vec<Path>)>
{
util::toml::to_manifest(contents, source_id).map_err(human)
util::toml::to_manifest(contents, source_id, layout).map_err(human)
}

pub fn read_package(path: &Path, source_id: &SourceId)
Expand All @@ -17,8 +18,10 @@ pub fn read_package(path: &Path, source_id: &SourceId)
log!(5, "read_package; path={}; source-id={}", path.display(), source_id);
let mut file = try!(File::open(path));
let data = try!(file.read_to_end());
let (manifest, nested) = try!(read_manifest(data.as_slice(),
source_id));

let layout = project_layout(&path.dir_path());
let (manifest, nested) =
try!(read_manifest(data.as_slice(), layout, source_id));

Ok((Package::new(manifest, path, source_id), nested))
}
Expand Down
17 changes: 13 additions & 4 deletions src/cargo/ops/cargo_rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ fn rustc(root: &Path, target: &Target, cx: &mut Context) -> Job {

log!(5, "command={}", rustc);

cx.config.shell().verbose(|shell| shell.status("Running", rustc.to_str()));
let _ = cx.config.shell().verbose(|shell| shell.status("Running", rustc.to_str()));

proc() {
if primary {
Expand Down Expand Up @@ -249,12 +249,16 @@ fn build_base_args(into: &mut Args, target: &Target, crate_types: Vec<&str>,
cx: &Context) {
// TODO: Handle errors in converting paths into args
into.push(target.get_path().display().to_str());

into.push("--crate-name".to_str());
into.push(target.get_name().to_str());

for crate_type in crate_types.iter() {
into.push("--crate-type".to_str());
into.push(crate_type.to_str());
}

let mut out = cx.dest.clone();
let out = cx.dest.clone();
let profile = target.get_profile();

if profile.get_opt_level() != 0 {
Expand All @@ -270,8 +274,13 @@ fn build_base_args(into: &mut Args, target: &Target, crate_types: Vec<&str>,
into.push("--test".to_str());
}

into.push("--out-dir".to_str());
into.push(out.display().to_str());
if target.is_lib() {
into.push("--out-dir".to_str());
into.push(out.display().to_str());
} else {
into.push("-o".to_str());
into.push(out.join(target.get_name()).display().to_str());
}
}

fn build_deps_args(dst: &mut Args, cx: &Context) {
Expand Down
148 changes: 135 additions & 13 deletions src/cargo/util/toml.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serialize::Decodable;
use std::collections::HashMap;
use std::str;
use std::io::fs;
use toml;

use core::{SourceId, GitKind};
Expand All @@ -9,8 +10,52 @@ use core::{Summary, Manifest, Target, Dependency, PackageId};
use core::source::Location;
use util::{CargoResult, Require, human};

#[deriving(Clone)]
pub struct Layout {
lib: Option<Path>,
bins: Vec<Path>
}

impl Layout {
fn main<'a>(&'a self) -> Option<&'a Path> {
self.bins.iter().find(|p| {
match p.filename_str() {
Some(s) => s == "main.rs",
None => false
}
})
}
}

pub fn project_layout(root: &Path) -> Layout {
let mut lib = None;
let mut bins = vec!();

if root.join("src/lib.rs").exists() {
lib = Some(root.join("src/lib.rs"));
}

if root.join("src/main.rs").exists() {
bins.push(root.join("src/main.rs"));
}

fs::readdir(&root.join("src/bin"))
.map(|v| v.move_iter())
.map(|i| i.filter(|f| f.extension_str() == Some("rs")))
.map(|mut i| i.collect())
.map(|found| bins.push_all_move(found));

Layout {
lib: lib,
bins: bins
}
}

pub fn to_manifest(contents: &[u8],
source_id: &SourceId) -> CargoResult<(Manifest, Vec<Path>)> {
source_id: &SourceId,
layout: Layout)
-> CargoResult<(Manifest, Vec<Path>)>
{
let contents = try!(str::from_utf8(contents).require(|| {
human("Cargo.toml is not valid UTF-8")
}));
Expand All @@ -22,7 +67,7 @@ pub fn to_manifest(contents: &[u8],
manifest\n\n{}", e)))
};

let pair = try!(toml_manifest.to_manifest(source_id).map_err(|err| {
let pair = try!(toml_manifest.to_manifest(source_id, &layout).map_err(|err| {
human(format!("Cargo.toml is not a valid manifest\n\n{}", err))
}));
let (mut manifest, paths) = pair;
Expand Down Expand Up @@ -51,8 +96,6 @@ pub fn to_manifest(contents: &[u8],
_ => m.add_unused_key(key),
}
}


}

pub fn parse(toml: &str, file: &str) -> CargoResult<toml::Table> {
Expand Down Expand Up @@ -135,16 +178,98 @@ struct Context<'a> {
nested_paths: &'a mut Vec<Path>
}

// These functions produce the equivalent of specific manifest entries. One
// wrinkle is that certain paths cannot be represented in the manifest due
// to Toml's UTF-8 requirement. This could, in theory, mean that certain
// otherwise acceptable executable names are not used when inside of
// `src/bin/*`, but it seems ok to not build executables with non-UTF8
// paths.
fn inferred_lib_target(name: &str, layout: &Layout) -> Option<Vec<TomlTarget>> {
layout.lib.as_ref().map(|lib| {
vec![TomlTarget {
name: name.to_str(),
crate_type: None,
path: Some(lib.display().to_str()),
test: None
}]
})
}

fn inferred_bin_targets(name: &str, layout: &Layout) -> Option<Vec<TomlTarget>> {
Some(layout.bins.iter().filter_map(|bin| {
let name = if bin.as_str() == Some("src/main.rs") {
Some(name.to_str())
} else {
bin.filestem_str().map(|f| f.to_str())
};

name.map(|name| {
TomlTarget {
name: name,
crate_type: None,
path: Some(bin.display().to_str()),
test: None
}
})
}).collect())
}

impl TomlManifest {
pub fn to_manifest(&self, source_id: &SourceId)
pub fn to_manifest(&self, source_id: &SourceId, layout: &Layout)
-> CargoResult<(Manifest, Vec<Path>)>
{
let mut sources = vec!();
let mut nested_paths = vec!();

let project = self.project.as_ref().or_else(|| self.package.as_ref());
let project = try!(project.require(|| {
human("No `package` or `project` section found.")
}));


// If we have no lib at all, use the inferred lib if available
// If we have a lib with a path, we're done
// If we have a lib with no path, use the inferred lib or_else package name

let lib = if self.lib.is_none() || self.lib.get_ref().is_empty() {
inferred_lib_target(project.name.as_slice(), layout)
} else {
Some(self.lib.get_ref().iter().map(|t| {
if layout.lib.is_some() && t.path.is_none() {
TomlTarget {
name: t.name.clone(),
crate_type: t.crate_type.clone(),
path: layout.lib.as_ref().map(|p| p.display().to_str()),
test: t.test
}
} else {
t.clone()
}
}).collect())
};

let bins = if self.bin.is_none() || self.bin.get_ref().is_empty() {
inferred_bin_targets(project.name.as_slice(), layout)
} else {
let bin = layout.main();

Some(self.bin.get_ref().iter().map(|t| {
if bin.is_some() && t.path.is_none() {
TomlTarget {
name: t.name.clone(),
crate_type: t.crate_type.clone(),
path: bin.as_ref().map(|p| p.display().to_str()),
test: t.test
}
} else {
t.clone()
}
}).collect())
};

// Get targets
let targets = normalize(self.lib.as_ref().map(|l| l.as_slice()),
self.bin.as_ref().map(|b| b.as_slice()));
let targets = normalize(lib.as_ref().map(|l| l.as_slice()),
bins.as_ref().map(|b| b.as_slice()));

if targets.is_empty() {
debug!("manifest has no build targets; project={}", self.project);
Expand All @@ -166,11 +291,6 @@ impl TomlManifest {
try!(process_dependencies(&mut cx, true, self.dev_dependencies.as_ref()));
}

let project = self.project.as_ref().or_else(|| self.package.as_ref());
let project = try!(project.require(|| {
human("No `package` or `project` section found.")
}));

let pkgid = try!(project.to_package_id(source_id.get_location()));
let summary = Summary::new(&pkgid, deps.as_slice());
Ok((Manifest::new(
Expand Down Expand Up @@ -243,7 +363,9 @@ struct TomlTarget {
}

fn normalize(lib: Option<&[TomlLibTarget]>,
bin: Option<&[TomlBinTarget]>) -> Vec<Target> {
bin: Option<&[TomlBinTarget]>)
-> Vec<Target>
{
log!(4, "normalizing toml targets; lib={}; bin={}", lib, bin);

fn target_profiles(target: &TomlTarget) -> Vec<Profile> {
Expand Down
Loading