Merge with upstream and update Cargo.lock

Conflicts:
	src/bin/new.rs
	src/cargo/ops/cargo_new.rs
This commit is contained in:
Сухарик 2014-09-04 13:37:09 +04:00
commit cc9ed63222
19 changed files with 544 additions and 80 deletions

4
Cargo.lock generated
View file

@ -35,7 +35,7 @@ dependencies = [
[[package]]
name = "encoding"
version = "0.1.0"
source = "git+https://github.com/lifthrasiir/rust-encoding#15de58b9cb1fb5998aa6217e794d557eaf80a31f"
source = "git+https://github.com/lifthrasiir/rust-encoding#35f0d70f65f73ba16f296f9ec675eddee661ba79"
[[package]]
name = "flate2"
@ -99,6 +99,6 @@ name = "url"
version = "0.1.0"
source = "git+https://github.com/servo/rust-url#bb68de835ad945a72fba44979944a587ba83941a"
dependencies = [
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#15de58b9cb1fb5998aa6217e794d557eaf80a31f)",
"encoding 0.1.0 (git+https://github.com/lifthrasiir/rust-encoding#35f0d70f65f73ba16f296f9ec675eddee661ba79)",
]

View file

@ -14,7 +14,9 @@ Usage:
Options:
-h, --help Print this message
--git Initialize a new git repository with a .gitignore
--no-git Don't initialize a new git repository
--git Initialize a new git repository, overriding a
global `git = false` configuration
--travis Create a .travis.yml file
--bin Use a binary instead of a library template
-v, --verbose Use verbose output
@ -24,9 +26,10 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
debug!("executing; cmd=cargo-new; args={}", os::args());
shell.set_verbose(options.flag_verbose);
let Options { flag_git, flag_travis, flag_bin, arg_path, .. } = options;
let Options { flag_no_git, flag_travis, flag_bin, arg_path, flag_git, .. } = options;
let opts = ops::NewOptions {
no_git: flag_no_git,
git: flag_git,
travis: flag_travis,
path: arg_path.as_slice(),

View file

@ -1,3 +1,5 @@
use std::collections::HashSet;
use core::{Source, SourceId, SourceMap, Summary, Dependency, PackageId, Package};
use util::{CargoResult, ChainError, Config, human, profile};
@ -100,11 +102,14 @@ impl<'a> PackageRegistry<'a> {
fn query_overrides(&mut self, dep: &Dependency)
-> CargoResult<Vec<Summary>> {
let mut seen = HashSet::new();
let mut ret = Vec::new();
for s in self.overrides.iter() {
let src = self.sources.get_mut(s).unwrap();
let dep = Dependency::new_override(dep.get_name(), s);
ret.push_all_move(try!(src.query(&dep)));
ret.extend(try!(src.query(&dep)).move_iter().filter(|s| {
seen.insert(s.get_name().to_string())
}));
}
Ok(ret)
}

View file

@ -71,7 +71,7 @@ pub fn compile(manifest_path: &Path,
let override_ids = try!(source_ids_from_config(&user_configs,
manifest_path.dir_path()));
let (packages, resolve, resolve_with_overrides, sources) = {
let (packages, resolve_with_overrides, sources) = {
let _p = profile::start("resolving...");
let lockfile = manifest_path.dir_path().join("Cargo.lock");
let source_id = package.get_package_id().get_source_id();
@ -90,6 +90,7 @@ pub fn compile(manifest_path: &Path,
let resolved = try!(resolver::resolve(package.get_package_id(),
package.get_dependencies(),
&mut registry));
try!(ops::write_resolve(&package, &resolved));
try!(registry.add_overrides(override_ids));
let resolved_with_overrides =
@ -104,7 +105,7 @@ pub fn compile(manifest_path: &Path,
human("Unable to get packages from source")
}));
(packages, resolved, resolved_with_overrides, registry.move_sources())
(packages, resolved_with_overrides, registry.move_sources())
};
debug!("packages={}", packages);
@ -128,8 +129,6 @@ pub fn compile(manifest_path: &Path,
&mut config))
};
try!(ops::write_resolve(&package, &resolve));
return Ok(ret);
}

View file

@ -3,16 +3,23 @@ use std::io::{mod, fs, File};
use git2::{Repository, Config};
use util::{CargoResult, human, ChainError};
use util::{CargoResult, human, ChainError, config, internal};
use core::shell::MultiShell;
pub struct NewOptions<'a> {
pub no_git: bool,
pub git: bool,
pub travis: bool,
pub bin: bool,
pub path: &'a str,
}
struct CargoNewConfig {
name: Option<String>,
email: Option<String>,
git: Option<bool>,
}
pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
let path = os::getcwd().join(opts.path);
if path.exists() {
@ -27,23 +34,33 @@ pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
}
fn mk(path: &Path, name: &str, opts: &NewOptions) -> CargoResult<()> {
if opts.git {
let cfg = try!(global_config());
if !opts.git && (opts.no_git || cfg.git == Some(false)) {
try!(fs::mkdir(path, io::UserRWX));
} else {
try!(Repository::init(path));
let mut gitignore = "/target\n".to_string();
if !opts.bin {
gitignore.push_str("/Cargo.lock\n");
}
try!(File::create(&path.join(".gitignore")).write(gitignore.as_bytes()));
} else {
try!(fs::mkdir(path, io::UserRWX));
}
let (author_name, email) = try!(discover_author());
// Hoo boy, sure glad we've got exhaustivenes checking behind us.
let author = match (cfg.name, cfg.email, author_name, email) {
(Some(name), Some(email), _, _) |
(Some(name), None, _, Some(email)) |
(None, Some(email), name, _) |
(None, None, name, Some(email)) => format!("{} <{}>", name, email),
(Some(name), None, _, None) |
(None, None, name, None) => name,
};
if opts.travis {
try!(File::create(&path.join(".travis.yml")).write_str("language: rust\n"));
}
let author = try!(discover_author());
try!(File::create(&path.join("Cargo.toml")).write_str(format!(
r#"[package]
@ -71,7 +88,7 @@ fn it_works() {
Ok(())
}
fn discover_author() -> CargoResult<String> {
fn discover_author() -> CargoResult<(String, Option<String>)> {
let git_config = Config::open_default().ok();
let git_config = git_config.as_ref();
let name = git_config.and_then(|g| g.get_str("user.name").ok())
@ -87,8 +104,46 @@ fn discover_author() -> CargoResult<String> {
let name = name.as_slice().trim().to_string();
let email = email.map(|s| s.as_slice().trim().to_string());
Ok(match (name, email) {
(name, Some(email)) => format!("{} <{}>", name, email),
(name, None) => name,
})
Ok((name, email))
}
fn global_config() -> CargoResult<CargoNewConfig> {
let user_configs = try!(config::all_configs(os::getcwd()));
let mut cfg = CargoNewConfig {
name: None,
email: None,
git: None,
};
let cargo_new = match user_configs.find_equiv(&"cargo-new") {
None => return Ok(cfg),
Some(target) => try!(target.table().chain_error(|| {
internal("invalid configuration for the key `cargo-new`")
})),
};
cfg.name = match cargo_new.find_equiv(&"name") {
None => None,
Some(name) => {
Some(try!(name.string().chain_error(|| {
internal("invalid configuration for key `cargo-new.name`")
})).ref0().to_string())
}
};
cfg.email = match cargo_new.find_equiv(&"email") {
None => None,
Some(email) => {
Some(try!(email.string().chain_error(|| {
internal("invalid configuration for key `cargo-new.email`")
})).ref0().to_string())
}
};
cfg.git = match cargo_new.find_equiv(&"git") {
None => None,
Some(git) => {
Some(try!(git.boolean().chain_error(|| {
internal("invalid configuration for key `cargo-new.git`")
})).val0())
}
};
Ok(cfg)
}

View file

@ -242,7 +242,7 @@ fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>,
cx: &Context, req: PlatformRequirement)
-> CargoResult<Vec<(ProcessBuilder, Kind)>> {
let base = process("rustc", package, cx);
let base = build_base_args(base, target, crate_types.as_slice());
let base = build_base_args(cx, base, target, crate_types.as_slice());
let target_cmd = build_plugin_args(base.clone(), cx, package, target, KindTarget);
let plugin_cmd = build_plugin_args(base, cx, package, target, KindPlugin);
@ -303,7 +303,7 @@ fn rustdoc(package: &Package, target: &Target,
})
}
fn build_base_args(mut cmd: ProcessBuilder,
fn build_base_args(cx: &Context, mut cmd: ProcessBuilder,
target: &Target,
crate_types: &[&str]) -> ProcessBuilder {
let metadata = target.get_metadata();
@ -317,18 +317,24 @@ fn build_base_args(mut cmd: ProcessBuilder,
cmd = cmd.arg("--crate-type").arg(*crate_type);
}
let profile = target.get_profile();
// Despite whatever this target's profile says, we need to configure it
// based off the profile found in the root package's targets.
let mut profile = target.get_profile().clone();
let root_package = cx.get_package(cx.resolve.root());
for target in root_package.get_manifest().get_targets().iter() {
let root_profile = target.get_profile();
if root_profile.get_env() != profile.get_env() { continue }
profile = profile.opt_level(root_profile.get_opt_level())
.debug(root_profile.get_debug());
}
if profile.get_opt_level() != 0 {
cmd = cmd.arg("--opt-level").arg(profile.get_opt_level().to_string());
}
// Right now -g is a little buggy, so we're not passing -g just yet
// if profile.get_debug() {
// into.push("-g".to_string());
// }
if !profile.get_debug() {
if profile.get_debug() {
cmd = cmd.arg("-g");
} else {
cmd = cmd.args(["--cfg", "ndebug"]);
}
@ -399,6 +405,10 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package,
if target.is_bin() {
for target in targets {
if target.is_staticlib() {
continue;
}
cmd = try!(link_to(cmd, target, cx, kind, LocalLib));
}
}

View file

@ -81,6 +81,7 @@ pub enum ConfigValue {
String(String, Path),
List(Vec<(String, Path)>),
Table(HashMap<String, ConfigValue>),
Boolean(bool, Path),
}
impl fmt::Show for ConfigValue {
@ -98,6 +99,7 @@ impl fmt::Show for ConfigValue {
write!(f, "]")
}
Table(ref table) => write!(f, "{}", table),
Boolean(b, ref path) => write!(f, "{} (from {})", b, path.display()),
}
}
}
@ -111,6 +113,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for ConfigValue {
list.encode(s)
}
Table(ref table) => table.encode(s),
Boolean(b, _) => b.encode(s),
}
}
}
@ -119,6 +122,7 @@ impl ConfigValue {
fn from_toml(path: &Path, toml: toml::Value) -> CargoResult<ConfigValue> {
match toml {
toml::String(val) => Ok(String(val, path.clone())),
toml::Boolean(b) => Ok(Boolean(b, path.clone())),
toml::Array(val) => {
Ok(List(try!(result::collect(val.move_iter().map(|toml| {
match toml {
@ -140,6 +144,7 @@ impl ConfigValue {
fn merge(&mut self, from: ConfigValue) -> CargoResult<()> {
match (self, from) {
(me @ &String(..), from @ String(..)) => *me = from,
(me @ &Boolean(..), from @ Boolean(..)) => *me = from,
(&List(ref mut old), List(ref mut new)) => {
let new = mem::replace(new, Vec::new());
old.extend(new.move_iter());
@ -165,25 +170,33 @@ impl ConfigValue {
pub fn string(&self) -> CargoResult<(&str, &Path)> {
match *self {
Table(..) => Err(internal("expected a string, but found a table")),
List(..) => Err(internal("expected a string, but found a list")),
String(ref s, ref p) => Ok((s.as_slice(), p)),
_ => Err(internal(format!("expected a string, but found a {}",
self.desc()))),
}
}
pub fn table(&self) -> CargoResult<&HashMap<String, ConfigValue>> {
match *self {
String(..) => Err(internal("expected a table, but found a string")),
List(..) => Err(internal("expected a table, but found a list")),
Table(ref table) => Ok(table),
_ => Err(internal(format!("expected a table, but found a {}",
self.desc()))),
}
}
pub fn list(&self) -> CargoResult<&[(String, Path)]> {
match *self {
String(..) => Err(internal("expected a list, but found a string")),
Table(..) => Err(internal("expected a list, but found a table")),
List(ref list) => Ok(list.as_slice()),
_ => Err(internal(format!("expected a list, but found a {}",
self.desc()))),
}
}
pub fn boolean(&self) -> CargoResult<(bool, &Path)> {
match *self {
Boolean(b, ref p) => Ok((b, p)),
_ => Err(internal(format!("expected a bool, but found a {}",
self.desc()))),
}
}
@ -192,6 +205,7 @@ impl ConfigValue {
Table(..) => "table",
List(..) => "array",
String(..) => "string",
Boolean(..) => "boolean",
}
}
}

View file

@ -4,6 +4,7 @@ use std::io::fs;
use std::os;
use std::slice;
use std::str;
use std::default::Default;
use toml;
use semver;
use serialize::{Decodable, Decoder};
@ -198,6 +199,7 @@ pub struct DetailedTomlDependency {
pub struct TomlManifest {
package: Option<Box<TomlProject>>,
project: Option<Box<TomlProject>>,
profile: Option<TomlProfiles>,
lib: Option<ManyOrOne<TomlLibTarget>>,
bin: Option<Vec<TomlBinTarget>>,
example: Option<Vec<TomlExampleTarget>>,
@ -207,6 +209,21 @@ pub struct TomlManifest {
dev_dependencies: Option<HashMap<String, TomlDependency>>,
}
#[deriving(Decodable, Clone, Default)]
pub struct TomlProfiles {
test: Option<TomlProfile>,
doc: Option<TomlProfile>,
bench: Option<TomlProfile>,
dev: Option<TomlProfile>,
release: Option<TomlProfile>,
}
#[deriving(Decodable, Clone, Default)]
pub struct TomlProfile {
opt_level: Option<uint>,
debug: Option<bool>,
}
#[deriving(Decodable)]
pub enum ManyOrOne<T> {
Many(Vec<T>),
@ -411,12 +428,14 @@ impl TomlManifest {
};
// Get targets
let profiles = self.profile.clone().unwrap_or(Default::default());
let targets = normalize(lib.as_slice(),
bins.as_slice(),
examples.as_slice(),
tests.as_slice(),
benches.as_slice(),
&metadata);
&metadata,
&profiles);
if targets.is_empty() {
debug!("manifest has no build targets");
@ -572,38 +591,61 @@ fn normalize(libs: &[TomlLibTarget],
examples: &[TomlExampleTarget],
tests: &[TomlTestTarget],
benches: &[TomlBenchTarget],
metadata: &Metadata) -> Vec<Target> {
metadata: &Metadata,
profiles: &TomlProfiles) -> Vec<Target> {
log!(4, "normalizing toml targets; lib={}; bin={}; example={}; test={}, benches={}",
libs, bins, examples, tests, benches);
enum TestDep { Needed, NotNeeded }
fn target_profiles(target: &TomlTarget, dep: TestDep) -> Vec<Profile> {
let mut ret = vec![Profile::default_dev(), Profile::default_release()];
fn merge(profile: Profile, toml: &Option<TomlProfile>) -> Profile {
let toml = match *toml {
Some(ref toml) => toml,
None => return profile,
};
let opt_level = toml.opt_level.unwrap_or(profile.get_opt_level());
let debug = toml.debug.unwrap_or(profile.get_debug());
profile.opt_level(opt_level).debug(debug)
}
fn target_profiles(target: &TomlTarget, profiles: &TomlProfiles,
dep: TestDep) -> Vec<Profile> {
let mut ret = vec![
merge(Profile::default_dev(), &profiles.dev),
merge(Profile::default_release(), &profiles.release),
];
match target.test {
Some(true) | None => ret.push(Profile::default_test()),
Some(true) | None => {
ret.push(merge(Profile::default_test(), &profiles.test));
}
Some(false) => {}
}
let doctest = target.doctest.unwrap_or(true);
match target.doc {
Some(true) | None => {
ret.push(Profile::default_doc().doctest(doctest));
ret.push(merge(Profile::default_doc().doctest(doctest),
&profiles.doc));
}
Some(false) => {}
}
match target.bench {
Some(true) | None => ret.push(Profile::default_bench()),
Some(true) | None => {
ret.push(merge(Profile::default_bench(), &profiles.bench));
}
Some(false) => {}
}
match dep {
Needed => {
ret.push(Profile::default_test().test(false));
ret.push(Profile::default_doc().doc(false));
ret.push(Profile::default_bench().test(false));
ret.push(merge(Profile::default_test().test(false),
&profiles.test));
ret.push(merge(Profile::default_doc().doc(false),
&profiles.doc));
ret.push(merge(Profile::default_bench().test(false),
&profiles.bench));
}
_ => {}
}
@ -616,7 +658,7 @@ fn normalize(libs: &[TomlLibTarget],
}
fn lib_targets(dst: &mut Vec<Target>, libs: &[TomlLibTarget],
dep: TestDep, metadata: &Metadata) {
dep: TestDep, metadata: &Metadata, profiles: &TomlProfiles) {
let l = &libs[0];
let path = l.path.clone().unwrap_or_else(|| {
TomlString(format!("src/{}.rs", l.name))
@ -627,7 +669,7 @@ fn normalize(libs: &[TomlLibTarget],
vec![if l.plugin == Some(true) {Dylib} else {Lib}]
});
for profile in target_profiles(l, dep).iter() {
for profile in target_profiles(l, profiles, dep).iter() {
let mut metadata = metadata.clone();
// Libs and their tests are built in parallel, so we need to make
// sure that their metadata is different.
@ -641,14 +683,14 @@ fn normalize(libs: &[TomlLibTarget],
}
fn bin_targets(dst: &mut Vec<Target>, bins: &[TomlBinTarget],
dep: TestDep, metadata: &Metadata,
dep: TestDep, metadata: &Metadata, profiles: &TomlProfiles,
default: |&TomlBinTarget| -> String) {
for bin in bins.iter() {
let path = bin.path.clone().unwrap_or_else(|| {
TomlString(default(bin))
});
for profile in target_profiles(bin, dep).iter() {
for profile in target_profiles(bin, profiles, dep).iter() {
let metadata = if profile.is_test() {
// Make sure that the name of this test executable doesn't
// conflicts with a library that has the same name and is
@ -668,19 +710,21 @@ fn normalize(libs: &[TomlLibTarget],
}
fn example_targets(dst: &mut Vec<Target>, examples: &[TomlExampleTarget],
profiles: &TomlProfiles,
default: |&TomlExampleTarget| -> String) {
for ex in examples.iter() {
let path = ex.path.clone().unwrap_or_else(|| TomlString(default(ex)));
let profile = &Profile::default_test().test(false);
let profile = Profile::default_test().test(false);
let profile = merge(profile, &profiles.test);
dst.push(Target::example_target(ex.name.as_slice(),
&path.to_path(),
profile));
&profile));
}
}
fn test_targets(dst: &mut Vec<Target>, tests: &[TomlTestTarget],
metadata: &Metadata,
metadata: &Metadata, profiles: &TomlProfiles,
default: |&TomlTestTarget| -> String) {
for test in tests.iter() {
let path = test.path.clone().unwrap_or_else(|| {
@ -692,16 +736,17 @@ fn normalize(libs: &[TomlLibTarget],
let mut metadata = metadata.clone();
metadata.mix(&format!("test-{}", test.name));
let profile = &Profile::default_test().harness(harness);
let profile = Profile::default_test().harness(harness);
let profile = merge(profile, &profiles.test);
dst.push(Target::test_target(test.name.as_slice(),
&path.to_path(),
profile,
&profile,
metadata));
}
}
fn bench_targets(dst: &mut Vec<Target>, benches: &[TomlBenchTarget],
metadata: &Metadata,
metadata: &Metadata, profiles: &TomlProfiles,
default: |&TomlBenchTarget| -> String) {
for bench in benches.iter() {
let path = bench.path.clone().unwrap_or_else(|| {
@ -713,11 +758,12 @@ fn normalize(libs: &[TomlLibTarget],
let mut metadata = metadata.clone();
metadata.mix(&format!("bench-{}", bench.name));
let profile = &Profile::default_bench().harness(harness);
let profile = Profile::default_bench().harness(harness);
let profile = merge(profile, &profiles.bench);
dst.push(Target::bench_target(bench.name.as_slice(),
&path.to_path(),
profile,
metadata));
&path.to_path(),
&profile,
metadata));
}
}
@ -731,25 +777,25 @@ fn normalize(libs: &[TomlLibTarget],
match (libs, bins) {
([_, ..], [_, ..]) => {
lib_targets(&mut ret, libs, Needed, metadata);
bin_targets(&mut ret, bins, test_dep, metadata,
lib_targets(&mut ret, libs, Needed, metadata, profiles);
bin_targets(&mut ret, bins, test_dep, metadata, profiles,
|bin| format!("src/bin/{}.rs", bin.name));
},
([_, ..], []) => {
lib_targets(&mut ret, libs, Needed, metadata);
lib_targets(&mut ret, libs, Needed, metadata, profiles);
},
([], [_, ..]) => {
bin_targets(&mut ret, bins, test_dep, metadata,
bin_targets(&mut ret, bins, test_dep, metadata, profiles,
|bin| format!("src/{}.rs", bin.name));
},
([], []) => ()
}
example_targets(&mut ret, examples,
example_targets(&mut ret, examples, profiles,
|ex| format!("examples/{}.rs", ex.name));
test_targets(&mut ret, tests, metadata,
test_targets(&mut ret, tests, metadata, profiles,
|test| {
if test.name.as_slice() == "test" {
"src/test.rs".to_string()
@ -757,7 +803,7 @@ fn normalize(libs: &[TomlLibTarget],
format!("tests/{}.rs", test.name)
}});
bench_targets(&mut ret, benches, metadata,
bench_targets(&mut ret, benches, metadata, profiles,
|bench| {
if bench.name.as_slice() == "bench" {
"src/bench.rs".to_string()

69
src/doc/source/config.md Normal file
View file

@ -0,0 +1,69 @@
---
title: Configuration
---
This document will explain how cargo's configuration system works, as well as
available keys or configuration. For configuration of a project through its
manfest, see the [manifest format](manifest.html).
# Hierarchical structure
Cargo allows to have local configuration for a particular project or global
configuration (like git). Cargo also extends this ability to a hirearchical
strategy. If, for example, cargo were invoked in `/home/foo/bar/baz`, then the
following configuration files would be probed for:
* `/home/foo/bar/baz/.cargo/config`
* `/home/foo/bar/.cargo/config`
* `/home/foo/.cargo/config`
* `/home/.cargo/config`
* `/.cargo/config`
With this structure you can specify local configuration per-project, and even
possibly check it into version control. You can also specify personal default
with a configuration file in your home directory.
# Configuration Format
All configuration is currently in the TOML format (like the manifest), with
simple key-value pairs inside of sections (tables) which all get merged
together.
# Configuration keys
All of the following keys are optional, and their defaults are listed as their
value unless otherwise noted.
```toml
# An array of paths to local repositories which are to be used as overrides for
# dependencies. For more information see the Cargo Guide.
paths = [ "/path/to/override" ]
[cargo-new]
# This is your name/email to place in the `authors` section of a new Cargo.toml
# that is generated. If not present, then `git` will be probed, and if that is
# not present then `$USER` will be used (with no email).
name = "..."
email = "..."
# By default `cargo new` will initialize a new git repository. This key can be
# set to `false` to disable this behavior.
git = true
# For the following sections, $triple refers to any valid target triple, not the
# literal string "$triple", and it will apply whenever that target triple is
# being compiled to.
[target]
# For cargo builds which do not mention --target, these are the ar/linker which
# are passed to rustc to use (via `-C ar=` and `-C linker=`). By default these
# flags are not passed to the compiler.
ar = ".."
linker = ".."
[target.$triple]
# Similar to the above ar/linker configuration, but this only applies to when
# the `$triple` is being compiled for.
ar = ".."
linker = ".."
```

View file

@ -34,7 +34,8 @@ $ cargo new hello_world --bin
```
We're passing `--bin` because we're making a binary program: if we
were making a library, we'd leave it off.
were making a library, we'd leave it off. If you'd like to not initialize a new
git repository as well (the default), you can also pass `--no-git`.
Let's check out what Cargo has generated for us:
@ -359,6 +360,9 @@ This array should be filled with directories that contain a `Cargo.toml`. In
this instance, we're just adding `conduit`, so it will be the only one that's
overridden.
More information about local configuration can be found in the [configuration
documentation](config.html).
# Tests
Cargo can run your tests with the `cargo test` command. Cargo runs tests in two

View file

@ -24,12 +24,11 @@ Alternatively, you can build Cargo from source.
To start a new project with Cargo, use `cargo new`:
```shell
$ cargo new hello_world --bin --git
$ cargo new hello_world --bin
```
We're passing `--bin` because we're making a binary program: if we
were making a library, we'd leave it off. We also pass `--git` to auto-generate
a `.gitignore` and set up the git repository, but nothing will be committed.
were making a library, we'd leave it off.
Let's check out what Cargo has generated for us:

View file

@ -2,17 +2,17 @@
<html>
<head>
<meta charset="utf-8">
<!-- Always force latest IE rendering engine or request Chrome Frame -->
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<!-- Use title if it's in the page YAML frontmatter -->
<title><%= current_page.data.title || "The Middleman" %></title>
<%= stylesheet_link_tag "all" %>
<%= javascript_include_tag "all" %>
</head>
<body class="<%= page_classes %>">
<%= link_to image_tag("forkme.png", class: "fork-me"), "https://github.com/rust-lang/cargo" %>
<%= link_to image_tag("Cargo-Logo-Small.png", class: "logo"), "index.html" %>
@ -26,7 +26,8 @@
<%= link_to "Guide", "guide.html" %> |
<%= link_to "Frequently Asked Questions", "faq.html" %> |
<%= link_to "Manifest Format", "manifest.html" %> |
<%= link_to "Building Non-Rust Code", "native-build.html" %>
<%= link_to "Building Non-Rust Code", "native-build.html" %> |
<%= link_to "Configuration", "config.html" %>
</footer>
</main>

View file

@ -93,6 +93,45 @@ You can specify the source of a dependency in one of two ways at the moment:
Soon, you will be able to load packages from the Cargo registry as well.
# The `[profile.*]` Sections
Cargo supports custom configuration of how rustc is invoked through **profiles**
at the top level. Any manifest may declare a profile, but only the **top level**
project's profiles are actually read. All dependencies' profiles will be
overridden. This is done so the top-level project has control over how its
dependencies are compiled.
There are five currently supported profile names, all of which have the same
configuration available to them. Listed below is the configuration available,
along with the defaults for each profile.
```toml
# The development profile, used for `cargo build`
[profile.dev]
opt-level = 0 # Controls the --opt-level the compiler builds with
debug = true # Controls whether the compiler passes -g or `--cfg ndebug`
# The release profile, used for `cargo build --release`
[profile.release]
opt-level = 3
debug = false
# The testing profile, used for `cargo test`
[profile.test]
opt-level = 0
debug = true
# The benchmarking profile, used for `cargo bench`
[profile.bench]
opt-level = 3
debug = false
# The documentation profile, used for `cargo doc`
[profile.doc]
opt-level = 0
debug = true
```
# The `[dev-dependencies.*]` Sections
The format of this section is equivalent to `[dependencies.*]`. Dev-dependencies

View file

@ -125,6 +125,7 @@ Could not compile `foo`.
To learn more, run the command again with --verbose.\n",
filename = format!("src{}foo.rs", path::SEP)).as_slice()));
assert_that(&p.root().join("Cargo.lock"), existing_file());
})
test!(cargo_compile_with_invalid_code_in_deps {
@ -1152,7 +1153,7 @@ test!(verbose_build {
.file("src/lib.rs", "");
assert_that(p.cargo_process("build").arg("-v"),
execs().with_status(0).with_stdout(format!("\
{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib \
{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib -g \
-C metadata=[..] \
-C extra-filename=-[..] \
--out-dir {dir}{sep}target \
@ -1465,6 +1466,29 @@ test!(simple_staticlib {
assert_that(p.cargo_process("build"), execs().with_status(0));
})
test!(staticlib_rlib_and_bin {
let p = project("foo")
.file("Cargo.toml", r#"
[package]
name = "foo"
authors = []
version = "0.0.1"
[lib]
name = "foo"
crate-type = ["staticlib", "rlib"]
"#)
.file("src/lib.rs", "pub fn foo() {}")
.file("src/main.rs", r#"
extern crate foo;
fn main() {
foo::foo();
}"#);
assert_that(p.cargo_process("build"), execs().with_status(0));
})
test!(opt_out_of_lib {
let p = project("foo")
.file("Cargo.toml", r#"

View file

@ -602,3 +602,47 @@ test!(override_self {
assert_that(p.cargo_process("build"), execs().with_status(0));
})
test!(override_path_dep {
let bar = project("bar")
.file("p1/Cargo.toml", r#"
[package]
name = "p1"
version = "0.5.0"
authors = []
[dependencies.p2]
path = "../p2"
"#)
.file("p1/src/lib.rs", "")
.file("p2/Cargo.toml", r#"
[package]
name = "p2"
version = "0.5.0"
authors = []
"#)
.file("p2/src/lib.rs", "");
let p = project("foo")
.file(".cargo/config", format!(r#"
paths = ['{}', '{}']
"#, bar.root().join("p1").display(),
bar.root().join("p2").display()))
.file("Cargo.toml", format!(r#"
[package]
name = "foo"
version = "0.5.0"
authors = ["wycats@example.com"]
[dependencies.p2]
path = '{}'
"#, bar.root().join("p2").display()))
.file("src/lib.rs", "");
bar.build();
assert_that(p.cargo_process("build").arg("-v"),
execs().with_status(0));
})

View file

@ -295,7 +295,7 @@ test!(linker_and_ar {
.arg("-v"),
execs().with_status(101)
.with_stdout(format!("\
{running} `rustc src/foo.rs --crate-name foo --crate-type bin \
{running} `rustc src/foo.rs --crate-name foo --crate-type bin -g \
--out-dir {dir}{sep}target{sep}{target} \
--dep-info [..] \
--target {target} \

View file

@ -2,7 +2,7 @@ use std::io::{fs, UserRWX, File};
use std::os;
use support::{execs, paths, cargo_dir, ResultTest};
use hamcrest::{assert_that, existing_file, existing_dir};
use hamcrest::{assert_that, existing_file, existing_dir, is_not};
use cargo::util::{process, ProcessBuilder};
@ -23,12 +23,13 @@ fn cargo_process(s: &str) -> ProcessBuilder {
test!(simple_lib {
os::setenv("USER", "foo");
assert_that(cargo_process("new").arg("foo"),
assert_that(cargo_process("new").arg("foo").arg("--no-git"),
execs().with_status(0));
assert_that(&paths::root().join("foo"), existing_dir());
assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
assert_that(&paths::root().join("foo/src/lib.rs"), existing_file());
assert_that(&paths::root().join("foo/.gitignore"), is_not(existing_file()));
assert_that(cargo_process("build").cwd(paths::root().join("foo")),
execs().with_status(0));
@ -52,7 +53,7 @@ test!(simple_bin {
test!(simple_git {
os::setenv("USER", "foo");
assert_that(cargo_process("new").arg("foo").arg("--git"),
assert_that(cargo_process("new").arg("foo"),
execs().with_status(0));
assert_that(&paths::root().join("foo"), existing_dir());
@ -119,3 +120,42 @@ test!(finds_author_git {
let toml = File::open(&toml).read_to_string().assert();
assert!(toml.as_slice().contains(r#"authors = ["bar <baz>"]"#));
})
test!(author_prefers_cargo {
my_process("git").args(["config", "--global", "user.name", "bar"])
.exec().assert();
my_process("git").args(["config", "--global", "user.email", "baz"])
.exec().assert();
let root = paths::root();
fs::mkdir(&root.join(".cargo"), UserRWX).assert();
File::create(&root.join(".cargo/config")).write_str(r#"
[cargo-new]
name = "new-foo"
email = "new-bar"
git = false
"#).assert();
assert_that(cargo_process("new").arg("foo").env("USER", Some("foo")),
execs().with_status(0));
let toml = paths::root().join("foo/Cargo.toml");
let toml = File::open(&toml).read_to_string().assert();
assert!(toml.as_slice().contains(r#"authors = ["new-foo <new-bar>"]"#));
assert!(!root.join("foo/.gitignore").exists());
})
test!(git_prefers_command_line {
let root = paths::root();
fs::mkdir(&root.join(".cargo"), UserRWX).assert();
File::create(&root.join(".cargo/config")).write_str(r#"
[cargo-new]
git = false
name = "foo"
email = "bar"
"#).assert();
assert_that(cargo_process("new").arg("foo").arg("--git")
.env("USER", Some("foo")),
execs().with_status(0));
assert!(root.join("foo/.gitignore").exists());
})

View file

@ -0,0 +1,111 @@
use std::os;
use std::path;
use support::{project, execs};
use support::{COMPILING, RUNNING};
use hamcrest::assert_that;
fn setup() {
}
test!(profile_overrides {
let mut p = project("foo");
p = p
.file("Cargo.toml", r#"
[package]
name = "test"
version = "0.0.0"
authors = []
[profile.dev]
opt-level = 1
debug = false
"#)
.file("src/lib.rs", "");
assert_that(p.cargo_process("build").arg("-v"),
execs().with_status(0).with_stdout(format!("\
{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib \
--opt-level 1 \
--cfg ndebug \
-C metadata=[..] \
-C extra-filename=-[..] \
--out-dir {dir}{sep}target \
--dep-info [..] \
-L {dir}{sep}target \
-L {dir}{sep}target{sep}deps`
{compiling} test v0.0.0 ({url})\n",
running = RUNNING, compiling = COMPILING, sep = path::SEP,
dir = p.root().display(),
url = p.url(),
)));
})
test!(top_level_overrides_deps {
let mut p = project("foo");
p = p
.file("Cargo.toml", r#"
[package]
name = "test"
version = "0.0.0"
authors = []
[profile.release]
opt-level = 1
debug = true
[dependencies.foo]
path = "foo"
"#)
.file("src/lib.rs", "")
.file("foo/Cargo.toml", r#"
[package]
name = "foo"
version = "0.0.0"
authors = []
[profile.release]
opt-level = 0
debug = false
[lib]
name = "foo"
crate_type = ["dylib", "rlib"]
"#)
.file("foo/src/lib.rs", "");
assert_that(p.cargo_process("build").arg("-v").arg("--release"),
execs().with_status(0).with_stdout(format!("\
{running} `rustc {dir}{sep}foo{sep}src{sep}lib.rs --crate-name foo \
--crate-type dylib --crate-type rlib \
--opt-level 1 \
-g \
-C metadata=[..] \
-C extra-filename=-[..] \
--out-dir {dir}{sep}target{sep}release{sep}deps \
--dep-info [..] \
-L {dir}{sep}target{sep}release{sep}deps \
-L {dir}{sep}target{sep}release{sep}deps`
{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type lib \
--opt-level 1 \
-g \
-C metadata=[..] \
-C extra-filename=-[..] \
--out-dir {dir}{sep}target{sep}release \
--dep-info [..] \
-L {dir}{sep}target{sep}release \
-L {dir}{sep}target{sep}release{sep}deps \
--extern foo={dir}{sep}target{sep}release{sep}deps/\
{prefix}foo-[..]{suffix} \
--extern foo={dir}{sep}target{sep}release{sep}deps/libfoo-[..].rlib`
{compiling} foo v0.0.0 ({url})
{compiling} test v0.0.0 ({url})\n",
running = RUNNING,
compiling = COMPILING,
dir = p.root().display(),
url = p.url(),
sep = path::SEP,
prefix = os::consts::DLL_PREFIX,
suffix = os::consts::DLL_SUFFIX).as_slice()));
})

View file

@ -37,4 +37,5 @@ mod test_cargo_compile_plugins;
mod test_cargo_doc;
mod test_cargo_freshness;
mod test_cargo_generate_lockfile;
mod test_cargo_profiles;
mod test_cargo_package;