Skip to content

Commit 6e94e58

Browse files
committed
auto merge of #792 : alexcrichton/cargo/build-cmd, r=brson
This series of commits (based on #763) is an implementation of the recent [Cargo RFC](https://github.com/rust-lang/rfcs/blob/master/text/0403-cargo-build-command.md). This should implement all portions of the RFC, but there's a lot so an extra set of eyes would be nice! I haven't added documentation for it all yet, but I would like to do so before landing (starting with #749). Otherwise I've been migrating all of the existing cargo dependencies away from the build command to a build script, and the progress can be seen with these repositories: * https://github.com/alexcrichton/gcc-rs * https://github.com/alexcrichton/pkg-config-rs * https://github.com/alexcrichton/git2-rs/tree/build-cmd * https://github.com/alexcrichton/openssl-sys * https://github.com/alexcrichton/flate2-rs/tree/build-cmd * https://github.com/alexcrichton/libz-sys * https://github.com/alexcrichton/ssh2-rs/tree/build-cmd I haven't quite gotten around to curl just yet, but it's next on my list!
2 parents 1852281 + 5e29a8b commit 6e94e58

32 files changed

+2665
-816
lines changed

Makefile.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ clean:
102102

103103
# === Documentation
104104

105-
DOCS := index faq config guide manifest native-build pkgid-spec
105+
DOCS := index faq config guide manifest build-script pkgid-spec
106106
DOC_DIR := target/doc
107107
DOC_OPTS := --markdown-no-toc \
108108
--markdown-css stylesheets/normalize.css \

src/cargo/core/dependency.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub struct Dependency {
1010
source_id: SourceId,
1111
req: VersionReq,
1212
specified_req: Option<String>,
13-
transitive: bool,
13+
kind: Kind,
1414
only_match_name: bool,
1515

1616
optional: bool,
@@ -22,6 +22,13 @@ pub struct Dependency {
2222
only_for_platform: Option<String>,
2323
}
2424

25+
#[deriving(PartialEq, Clone, Show)]
26+
pub enum Kind {
27+
Normal,
28+
Development,
29+
Build,
30+
}
31+
2532
impl Dependency {
2633
/// Attempt to create a `Dependency` from an entry in the manifest.
2734
///
@@ -55,7 +62,7 @@ impl Dependency {
5562
name: name.to_string(),
5663
source_id: source_id.clone(),
5764
req: VersionReq::any(),
58-
transitive: true,
65+
kind: Normal,
5966
only_match_name: true,
6067
optional: false,
6168
features: Vec::new(),
@@ -83,8 +90,8 @@ impl Dependency {
8390
&self.source_id
8491
}
8592

86-
pub fn transitive(mut self, transitive: bool) -> Dependency {
87-
self.transitive = transitive;
93+
pub fn kind(mut self, kind: Kind) -> Dependency {
94+
self.kind = kind;
8895
self
8996
}
9097

@@ -132,7 +139,15 @@ impl Dependency {
132139
}
133140

134141
/// Returns false if the dependency is only used to build the local package.
135-
pub fn is_transitive(&self) -> bool { self.transitive }
142+
pub fn is_transitive(&self) -> bool {
143+
match self.kind {
144+
Normal | Build => true,
145+
Development => false,
146+
}
147+
}
148+
pub fn is_build(&self) -> bool {
149+
match self.kind { Build => true, _ => false }
150+
}
136151
pub fn is_optional(&self) -> bool { self.optional }
137152
/// Returns true if the default features of the dependency are requested.
138153
pub fn uses_default_features(&self) -> bool { self.default_features }

src/cargo/core/manifest.rs

+47-12
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ pub struct Manifest {
1616
targets: Vec<Target>,
1717
target_dir: Path,
1818
doc_dir: Path,
19-
build: Vec<String>,
19+
build: Vec<String>, // TODO: deprecated, remove
20+
links: Option<String>,
2021
warnings: Vec<String>,
2122
exclude: Vec<String>,
2223
metadata: ManifestMetadata,
@@ -59,7 +60,7 @@ pub struct SerializedManifest {
5960
targets: Vec<Target>,
6061
target_dir: String,
6162
doc_dir: String,
62-
build: Option<Vec<String>>,
63+
build: Option<Vec<String>>, // TODO: deprecated, remove
6364
}
6465

6566
impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
@@ -73,6 +74,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Manifest {
7374
targets: self.targets.clone(),
7475
target_dir: self.target_dir.display().to_string(),
7576
doc_dir: self.doc_dir.display().to_string(),
77+
// TODO: deprecated, remove
7678
build: if self.build.len() == 0 { None } else { Some(self.build.clone()) },
7779
}.encode(s)
7880
}
@@ -131,8 +133,9 @@ pub struct Profile {
131133
doctest: bool,
132134
doc: bool,
133135
dest: Option<String>,
134-
plugin: bool,
136+
for_host: bool,
135137
harness: bool, // whether to use the test harness (--test)
138+
custom_build: bool,
136139
}
137140

138141
impl Profile {
@@ -146,8 +149,9 @@ impl Profile {
146149
test: false,
147150
doc: false,
148151
dest: None,
149-
plugin: false,
152+
for_host: false,
150153
doctest: false,
154+
custom_build: false,
151155
harness: true,
152156
}
153157
}
@@ -219,8 +223,13 @@ impl Profile {
219223
self.doctest
220224
}
221225

222-
pub fn is_plugin(&self) -> bool {
223-
self.plugin
226+
pub fn is_custom_build(&self) -> bool {
227+
self.custom_build
228+
}
229+
230+
/// Returns true if the target must be built for the host instead of the target.
231+
pub fn is_for_host(&self) -> bool {
232+
self.for_host
224233
}
225234

226235
pub fn get_opt_level(&self) -> uint {
@@ -282,15 +291,22 @@ impl Profile {
282291
self
283292
}
284293

285-
pub fn plugin(mut self, plugin: bool) -> Profile {
286-
self.plugin = plugin;
294+
/// Sets whether the `Target` must be compiled for the host instead of the target platform.
295+
pub fn for_host(mut self, for_host: bool) -> Profile {
296+
self.for_host = for_host;
287297
self
288298
}
289299

290300
pub fn harness(mut self, harness: bool) -> Profile {
291301
self.harness = harness;
292302
self
293303
}
304+
305+
/// Sets whether the `Target` is a custom build script.
306+
pub fn custom_build(mut self, custom_build: bool) -> Profile {
307+
self.custom_build = custom_build;
308+
self
309+
}
294310
}
295311

296312
impl<H: hash::Writer> hash::Hash<H> for Profile {
@@ -302,7 +318,7 @@ impl<H: hash::Writer> hash::Hash<H> for Profile {
302318
codegen_units,
303319
debug,
304320
rpath,
305-
plugin,
321+
for_host,
306322
ref dest,
307323
harness,
308324

@@ -313,8 +329,10 @@ impl<H: hash::Writer> hash::Hash<H> for Profile {
313329
env: _,
314330
test: _,
315331
doctest: _,
332+
333+
custom_build: _,
316334
} = *self;
317-
(opt_level, codegen_units, debug, rpath, plugin, dest, harness).hash(into)
335+
(opt_level, codegen_units, debug, rpath, for_host, dest, harness).hash(into)
318336
}
319337
}
320338

@@ -366,16 +384,17 @@ impl Show for Target {
366384
impl Manifest {
367385
pub fn new(summary: Summary, targets: Vec<Target>,
368386
target_dir: Path, doc_dir: Path,
369-
build: Vec<String>, exclude: Vec<String>,
387+
build: Vec<String>, exclude: Vec<String>, links: Option<String>,
370388
metadata: ManifestMetadata) -> Manifest {
371389
Manifest {
372390
summary: summary,
373391
targets: targets,
374392
target_dir: target_dir,
375393
doc_dir: doc_dir,
376-
build: build,
394+
build: build, // TODO: deprecated, remove
377395
warnings: Vec::new(),
378396
exclude: exclude,
397+
links: links,
379398
metadata: metadata,
380399
}
381400
}
@@ -416,6 +435,10 @@ impl Manifest {
416435
self.build.as_slice()
417436
}
418437

438+
pub fn get_links(&self) -> Option<&str> {
439+
self.links.as_ref().map(|s| s.as_slice())
440+
}
441+
419442
pub fn add_warning(&mut self, s: String) {
420443
self.warnings.push(s)
421444
}
@@ -466,6 +489,18 @@ impl Target {
466489
}
467490
}
468491

492+
/// Builds a `Target` corresponding to the `build = "build.rs"` entry.
493+
pub fn custom_build_target(name: &str, src_path: &Path, profile: &Profile,
494+
metadata: Option<Metadata>) -> Target {
495+
Target {
496+
kind: BinTarget,
497+
name: name.to_string(),
498+
src_path: src_path.clone(),
499+
profile: profile.clone(),
500+
metadata: metadata,
501+
}
502+
}
503+
469504
pub fn example_target(name: &str, src_path: &Path, profile: &Profile) -> Target {
470505
Target {
471506
kind: ExampleTarget,

src/cargo/ops/cargo_clean.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::io::fs::{mod, PathExtensions};
23

34
use core::{MultiShell, PackageSet};
@@ -49,7 +50,7 @@ pub fn clean(manifest_path: &Path, opts: &mut CleanOptions) -> CargoResult<()> {
4950
let pkgs = PackageSet::new([]);
5051
let cx = try!(Context::new("compile", &resolve, &srcs, &pkgs, &mut cfg,
5152
Layout::at(root.get_absolute_target_dir()),
52-
None, &pkg));
53+
None, &pkg, HashMap::new()));
5354

5455
// And finally, clean everything out!
5556
for target in pkg.get_targets().iter() {

src/cargo/ops/cargo_compile.rs

+58-31
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use std::collections::HashMap;
2828
use core::registry::PackageRegistry;
2929
use core::{MultiShell, Source, SourceId, PackageSet, Package, Target, PackageId};
3030
use core::resolver;
31-
use ops;
31+
use ops::{mod, BuildOutput};
3232
use sources::{PathSource};
3333
use util::config::{Config, ConfigValue};
3434
use util::{CargoResult, Wrap, config, internal, human, ChainError, profile};
@@ -129,7 +129,7 @@ pub fn compile_pkg(package: &Package, options: &mut CompileOptions)
129129
};
130130

131131
let targets = to_build.get_targets().iter().filter(|target| {
132-
match env {
132+
target.get_profile().is_custom_build() || match env {
133133
// doc-all == document everything, so look for doc targets
134134
"doc" | "doc-all" => target.get_profile().get_env() == "doc",
135135
env => target.get_profile().get_env() == env,
@@ -138,12 +138,12 @@ pub fn compile_pkg(package: &Package, options: &mut CompileOptions)
138138

139139
let ret = {
140140
let _p = profile::start("compiling");
141-
try!(scrape_target_config(&config, &user_configs));
141+
let lib_overrides = try!(scrape_target_config(&config, &user_configs));
142142

143143
try!(ops::compile_targets(env.as_slice(), targets.as_slice(), to_build,
144144
&PackageSet::new(packages.as_slice()),
145145
&resolve_with_overrides, &sources,
146-
&config))
146+
&config, lib_overrides))
147147
};
148148

149149
return Ok(ret);
@@ -175,41 +175,68 @@ fn source_ids_from_config(configs: &HashMap<String, config::ConfigValue>,
175175

176176
fn scrape_target_config(config: &Config,
177177
configs: &HashMap<String, config::ConfigValue>)
178-
-> CargoResult<()> {
178+
-> CargoResult<HashMap<String, BuildOutput>> {
179179
let target = match configs.find_equiv("target") {
180-
None => return Ok(()),
180+
None => return Ok(HashMap::new()),
181181
Some(target) => try!(target.table().chain_error(|| {
182182
internal("invalid configuration for the key `target`")
183183
})),
184184
};
185-
let target = match config.target() {
186-
None => target,
187-
Some(triple) => match target.find_equiv(triple) {
188-
None => return Ok(()),
189-
Some(target) => try!(target.table().chain_error(|| {
190-
internal(format!("invalid configuration for the key \
191-
`target.{}`", triple))
192-
})),
193-
},
185+
let triple = config.target().unwrap_or(config.rustc_host()).to_string();
186+
let target = match target.find(&triple) {
187+
None => return Ok(HashMap::new()),
188+
Some(target) => try!(target.table().chain_error(|| {
189+
internal(format!("invalid configuration for the key \
190+
`target.{}`", triple))
191+
})),
194192
};
195193

196-
match target.find_equiv("ar") {
197-
None => {}
198-
Some(ar) => {
199-
config.set_ar(try!(ar.string().chain_error(|| {
200-
internal("invalid configuration for key `ar`")
201-
})).ref0().to_string());
202-
}
203-
}
204-
205-
match target.find_equiv("linker") {
206-
None => {}
207-
Some(linker) => {
208-
config.set_linker(try!(linker.string().chain_error(|| {
209-
internal("invalid configuration for key `ar`")
210-
})).ref0().to_string());
194+
let mut ret = HashMap::new();
195+
for (k, v) in target.iter() {
196+
match k.as_slice() {
197+
"ar" | "linker" => {
198+
let v = try!(v.string().chain_error(|| {
199+
internal(format!("invalid configuration for key `{}`", k))
200+
})).ref0().to_string();
201+
if k.as_slice() == "linker" {
202+
config.set_linker(v);
203+
} else {
204+
config.set_ar(v);
205+
}
206+
}
207+
lib_name => {
208+
let table = try!(v.table().chain_error(|| {
209+
internal(format!("invalid configuration for the key \
210+
`target.{}.{}`", triple, lib_name))
211+
}));
212+
let mut output = BuildOutput {
213+
library_paths: Vec::new(),
214+
library_links: Vec::new(),
215+
metadata: Vec::new(),
216+
};
217+
for (k, v) in table.iter() {
218+
let v = try!(v.string().chain_error(|| {
219+
internal(format!("invalid configuration for the key \
220+
`target.{}.{}.{}`", triple, lib_name,
221+
k))
222+
})).val0();
223+
if k.as_slice() == "rustc-flags" {
224+
let whence = format!("in `target.{}.{}.rustc-flags`",
225+
triple, lib_name);
226+
let whence = whence.as_slice();
227+
let (paths, links) = try!(
228+
BuildOutput::parse_rustc_flags(v.as_slice(), whence)
229+
);
230+
output.library_paths.extend(paths.into_iter());
231+
output.library_links.extend(links.into_iter());
232+
} else {
233+
output.metadata.push((k.to_string(), v.to_string()));
234+
}
235+
}
236+
ret.insert(lib_name.to_string(), output);
237+
}
211238
}
212239
}
213240

214-
Ok(())
241+
Ok(ret)
215242
}

src/cargo/ops/cargo_run.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ pub fn run(manifest_path: &Path,
2222
LibTarget(_) => false,
2323
};
2424
let matches_name = name.as_ref().map_or(true, |n| n.as_slice() == a.get_name());
25-
matches_kind && matches_name && a.get_profile().get_env() == env
25+
matches_kind && matches_name && a.get_profile().get_env() == env &&
26+
!a.get_profile().is_custom_build()
2627
});
2728
let bin = try!(bins.next().require(|| {
2829
human("a bin target must be available for `cargo run`")

src/cargo/ops/cargo_rustc/compilation.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub struct Compilation {
2323
///
2424
/// This is currently used to drive some entries which are added to the
2525
/// LD_LIBRARY_PATH as appropriate.
26+
// TODO: deprecated, remove
2627
pub native_dirs: HashMap<PackageId, Path>,
2728

2829
/// Root output directory (for the local package's artifacts)
@@ -43,7 +44,7 @@ impl Compilation {
4344
pub fn new(pkg: &Package) -> Compilation {
4445
Compilation {
4546
libraries: HashMap::new(),
46-
native_dirs: HashMap::new(),
47+
native_dirs: HashMap::new(), // TODO: deprecated, remove
4748
root_output: Path::new("/"),
4849
deps_output: Path::new("/"),
4950
tests: Vec::new(),

0 commit comments

Comments
 (0)