auto merge of #13905 : alexcrichton/rust/issue-13337, r=thestinger

This has long since not been too relevant since the introduction of many crate
type outputs. This commit removes the flag entirely, adjusting all logic to do
the most reasonable thing when building both a library and an executable.

Closes #13337
This commit is contained in:
bors 2014-05-04 17:11:42 -07:00
commit b0977b1e0f
10 changed files with 73 additions and 68 deletions

View File

@ -210,7 +210,6 @@ pub fn phase_2_configure_and_expand(sess: &Session,
-> (ast::Crate, syntax::ast_map::Map) {
let time_passes = sess.time_passes();
sess.building_library.set(session::building_library(&sess.opts, &krate));
*sess.crate_types.borrow_mut() = session::collect_crate_types(sess, krate.attrs.as_slice());
time(time_passes, "gated feature checking", (), |_|
@ -1046,7 +1045,6 @@ pub fn build_session_(sopts: session::Options,
entry_type: Cell::new(None),
macro_registrar_fn: Cell::new(None),
default_sysroot: default_sysroot,
building_library: Cell::new(false),
local_crate_source_file: local_crate_source_file,
working_dir: os::getcwd(),
lints: RefCell::new(NodeMap::new()),

View File

@ -25,7 +25,6 @@ use syntax::codemap::Span;
use syntax::diagnostic;
use syntax::parse::ParseSess;
use syntax::{abi, ast, codemap};
use syntax;
use std::cell::{Cell, RefCell};
use collections::HashSet;
@ -185,7 +184,6 @@ pub struct Session {
pub entry_type: Cell<Option<EntryFnType>>,
pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
pub default_sysroot: Option<Path>,
pub building_library: Cell<bool>,
// The name of the root source file of the crate, in the local file system. The path is always
// expected to be absolute. `None` means that there is no source file.
pub local_crate_source_file: Option<Path>,
@ -477,26 +475,6 @@ pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> ~str) -> T {
diagnostic::expect(sess.diagnostic(), opt, msg)
}
pub fn building_library(options: &Options, krate: &ast::Crate) -> bool {
if options.test { return false }
for output in options.crate_types.iter() {
match *output {
CrateTypeExecutable => {}
CrateTypeStaticlib | CrateTypeDylib | CrateTypeRlib => return true
}
}
match syntax::attr::first_attr_value_str_by_name(krate.attrs.as_slice(),
"crate_type") {
Some(s) => {
s.equiv(&("lib")) ||
s.equiv(&("rlib")) ||
s.equiv(&("dylib")) ||
s.equiv(&("staticlib"))
}
_ => false
}
}
pub fn default_lib_output() -> CrateType {
CrateTypeRlib
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use driver::session;
use driver::session::Session;
use syntax::ast;
@ -86,7 +86,10 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> {
span: DUMMY_SP
});
if use_start(&krate) && !self.sess.building_library.get() {
let any_exe = self.sess.crate_types.borrow().iter().any(|ty| {
*ty == session::CrateTypeExecutable
});
if use_start(&krate) && any_exe {
vis.push(ast::ViewItem {
node: ast::ViewItemExternCrate(token::str_to_ident("native"),
with_version("native"),

View File

@ -125,27 +125,23 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
// Remove any #[main] from the AST so it doesn't clash with
// the one we're going to add. Only if compiling an executable.
fn nomain(cx: &TestCtxt, item: @ast::Item) -> @ast::Item {
if !cx.sess.building_library.get() {
@ast::Item {
attrs: item.attrs.iter().filter_map(|attr| {
if !attr.name().equiv(&("main")) {
Some(*attr)
} else {
None
}
}).collect(),
.. (*item).clone()
}
} else {
item
fn nomain(item: @ast::Item) -> @ast::Item {
@ast::Item {
attrs: item.attrs.iter().filter_map(|attr| {
if !attr.name().equiv(&("main")) {
Some(*attr)
} else {
None
}
}).collect(),
.. (*item).clone()
}
}
let mod_nomain = ast::Mod {
inner: m.inner,
view_items: m.view_items.clone(),
items: m.items.iter().map(|i| nomain(&self.cx, *i)).collect(),
items: m.items.iter().map(|i| nomain(*i)).collect(),
};
fold::noop_fold_mod(&mod_nomain, self)

View File

@ -48,9 +48,12 @@ impl<'a> Visitor<()> for EntryContext<'a> {
}
pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map) {
if session.building_library.get() {
let any_exe = session.crate_types.borrow().iter().any(|ty| {
*ty == session::CrateTypeExecutable
});
if !any_exe {
// No need to find a main function
return;
return
}
// If the user wants no main function at all, then stop here.
@ -132,18 +135,16 @@ fn configure_main(this: &mut EntryContext) {
*this.session.entry_fn.borrow_mut() = this.main_fn;
this.session.entry_type.set(Some(session::EntryMain));
} else {
if !this.session.building_library.get() {
// No main function
this.session.err("main function not found");
if !this.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
this.session.note("the main function must be defined at the crate level \
but you have one or more functions named 'main' that are not \
defined at the crate level. Either move the definition or \
attach the `#[main]` attribute to override this behavior.");
for &(_, span) in this.non_main_fns.iter() {
this.session.span_note(span, "here is a function named 'main'");
}
// No main function
this.session.err("main function not found");
if !this.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
this.session.note("the main function must be defined at the crate level \
but you have one or more functions named 'main' that are not \
defined at the crate level. Either move the definition or \
attach the `#[main]` attribute to override this behavior.");
for &(_, span) in this.non_main_fns.iter() {
this.session.span_note(span, "here is a function named 'main'");
}
this.session.abort_if_errors();
}

View File

@ -15,6 +15,7 @@
// makes all other generics or inline functions that it references
// reachable as well.
use driver::session;
use middle::ty;
use middle::typeck;
use middle::privacy;
@ -89,6 +90,8 @@ struct ReachableContext<'a> {
// A worklist of item IDs. Each item ID in this worklist will be inlined
// and will be scanned for further references.
worklist: Vec<ast::NodeId>,
// Whether any output of this compilation is a library
any_library: bool,
}
impl<'a> Visitor<()> for ReachableContext<'a> {
@ -157,10 +160,14 @@ impl<'a> Visitor<()> for ReachableContext<'a> {
impl<'a> ReachableContext<'a> {
// Creates a new reachability computation context.
fn new(tcx: &'a ty::ctxt) -> ReachableContext<'a> {
let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
*ty != session::CrateTypeExecutable
});
ReachableContext {
tcx: tcx,
reachable_symbols: NodeSet::new(),
worklist: Vec::new(),
any_library: any_library,
}
}
@ -234,7 +241,7 @@ impl<'a> ReachableContext<'a> {
fn propagate_node(&mut self, node: &ast_map::Node,
search_item: ast::NodeId) {
if !self.tcx.sess.building_library.get() {
if !self.any_library {
// If we are building an executable, then there's no need to flag
// anything as external except for `extern fn` types. These
// functions may still participate in some form of native interface,

View File

@ -1701,7 +1701,7 @@ fn finish_register_fn(ccx: &CrateContext, sp: Span, sym: ~str, node_id: ast::Nod
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
}
if is_entry_fn(ccx.sess(), node_id) && !ccx.sess().building_library.get() {
if is_entry_fn(ccx.sess(), node_id) {
create_entry_wrapper(ccx, sp, llfn);
}
}
@ -2100,7 +2100,10 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeI
pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
use flate;
if !cx.sess().building_library.get() {
let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
*ty != session::CrateTypeExecutable
});
if !any_library {
return Vec::new()
}

View File

@ -409,16 +409,14 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
fn check_for_entry_fn(ccx: &CrateCtxt) {
let tcx = ccx.tcx;
if !tcx.sess.building_library.get() {
match *tcx.sess.entry_fn.borrow() {
Some((id, sp)) => match tcx.sess.entry_type.get() {
Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp),
Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp),
Some(session::EntryNone) => {}
None => tcx.sess.bug("entry function without a type")
},
None => {}
}
match *tcx.sess.entry_fn.borrow() {
Some((id, sp)) => match tcx.sess.entry_type.get() {
Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp),
Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp),
Some(session::EntryNone) => {}
None => tcx.sess.bug("entry function without a type")
},
None => {}
}
}

View File

@ -0,0 +1,7 @@
-include ../tools.mk
all:
$(RUSTC) foo.rs
$(call RUN,foo)
rm $(TMPDIR)/$(call DYLIB_GLOB,foo)

View File

@ -0,0 +1,14 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "dylib"]
#![crate_type = "bin"]
fn main() {}