From 0162f8e6e16152224de4704ecd72d537c27046fe Mon Sep 17 00:00:00 2001 From: JustAPerson Date: Sun, 13 Apr 2014 14:26:02 -0500 Subject: [PATCH] Only check --crate-type flags if present. Before, normal compilation and the --crate-file-name flag would generate output based on both #![crate_type] attributes and --crate-type flags. Now, if one or more flag is specified by command line, only those will be used. Closes #11573. --- src/doc/rust.md | 9 ++- src/librustc/driver/session.rs | 74 ++++++++++--------- .../run-make/obey-crate-type-flag/Makefile | 13 ++++ .../run-make/obey-crate-type-flag/test.rs | 13 ++++ 4 files changed, 74 insertions(+), 35 deletions(-) create mode 100644 src/test/run-make/obey-crate-type-flag/Makefile create mode 100644 src/test/run-make/obey-crate-type-flag/test.rs diff --git a/src/doc/rust.md b/src/doc/rust.md index 5d505e55d2c91..f2df445a5a276 100644 --- a/src/doc/rust.md +++ b/src/doc/rust.md @@ -3920,7 +3920,9 @@ link Rust crates together, and more information about native libraries can be found in the [ffi tutorial][ffi]. In one session of compilation, the compiler can generate multiple artifacts -through the usage of command line flags and the `crate_type` attribute. +through the usage of either command line flags or the `crate_type` attribute. +If one or more command line flag is specified, all `crate_type` attributes will +be ignored in favor of only building the artifacts specified by command line. * `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be produced. This requires that there is a `main` function in the crate which @@ -3963,7 +3965,10 @@ through the usage of command line flags and the `crate_type` attribute. Note that these outputs are stackable in the sense that if multiple are specified, then the compiler will produce each form of output at once without -having to recompile. +having to recompile. However, this only applies for outputs specified by the same +method. If only `crate_type` attributes are specified, then they will all be +built, but if one or more `--crate-type` command line flag is specified, +then only those outputs will be built. With all these different kinds of outputs, if crate A depends on crate B, then the compiler could find B in various different forms throughout the system. The diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index a412742ab3a36..f9a429a2a1687 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -498,43 +498,51 @@ pub fn collect_crate_types(session: &Session, if session.opts.test { return vec!(CrateTypeExecutable) } + + // Only check command line flags if present. If no types are specified by + // command line, then reuse the empty `base` Vec to hold the types that + // will be found in crate attributes. let mut base = session.opts.crate_types.clone(); - let iter = attrs.iter().filter_map(|a| { - if a.name().equiv(&("crate_type")) { - match a.value_str() { - Some(ref n) if n.equiv(&("rlib")) => Some(CrateTypeRlib), - Some(ref n) if n.equiv(&("dylib")) => Some(CrateTypeDylib), - Some(ref n) if n.equiv(&("lib")) => { - Some(default_lib_output()) - } - Some(ref n) if n.equiv(&("staticlib")) => { - Some(CrateTypeStaticlib) - } - Some(ref n) if n.equiv(&("bin")) => Some(CrateTypeExecutable), - Some(_) => { - session.add_lint(lint::UnknownCrateType, - ast::CRATE_NODE_ID, - a.span, - ~"invalid `crate_type` value"); - None - } - _ => { - session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID, - a.span, ~"`crate_type` requires a value"); - None + if base.len() > 0 { + return base + } else { + let iter = attrs.iter().filter_map(|a| { + if a.name().equiv(&("crate_type")) { + match a.value_str() { + Some(ref n) if n.equiv(&("rlib")) => Some(CrateTypeRlib), + Some(ref n) if n.equiv(&("dylib")) => Some(CrateTypeDylib), + Some(ref n) if n.equiv(&("lib")) => { + Some(default_lib_output()) + } + Some(ref n) if n.equiv(&("staticlib")) => { + Some(CrateTypeStaticlib) + } + Some(ref n) if n.equiv(&("bin")) => Some(CrateTypeExecutable), + Some(_) => { + session.add_lint(lint::UnknownCrateType, + ast::CRATE_NODE_ID, + a.span, + ~"invalid `crate_type` value"); + None + } + _ => { + session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID, + a.span, ~"`crate_type` requires a value"); + None + } } + } else { + None } - } else { - None + }); + base.extend(iter); + if base.len() == 0 { + base.push(CrateTypeExecutable); } - }); - base.extend(iter); - if base.len() == 0 { - base.push(CrateTypeExecutable); - } - base.as_mut_slice().sort(); - base.dedup(); - return base; + base.as_mut_slice().sort(); + base.dedup(); + return base; + } } pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os { diff --git a/src/test/run-make/obey-crate-type-flag/Makefile b/src/test/run-make/obey-crate-type-flag/Makefile new file mode 100644 index 0000000000000..c28bc7c7b5e93 --- /dev/null +++ b/src/test/run-make/obey-crate-type-flag/Makefile @@ -0,0 +1,13 @@ +-include ../tools.mk + +# check that rustc builds all crate_type attributes +# delete rlib +# delete whatever dylib is made for this system +# check that rustc only builds --crate-type flags, ignoring attributes +# fail if an rlib was built +all: + $(RUSTC) test.rs + rm $(TMPDIR)/libtest*.rlib + rm $(TMPDIR)/libtest* + $(RUSTC) --crate-type dylib test.rs + rm $(TMPDIR)/libtest*.rlib && exit 1 || exit 0 diff --git a/src/test/run-make/obey-crate-type-flag/test.rs b/src/test/run-make/obey-crate-type-flag/test.rs new file mode 100644 index 0000000000000..8eb82b48eacf7 --- /dev/null +++ b/src/test/run-make/obey-crate-type-flag/test.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] +#![crate_type = "dylib"] +