2013-08-06 23:50:23 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use back::link;
|
2014-08-11 12:33:58 -05:00
|
|
|
use back::write;
|
2014-05-06 06:38:01 -05:00
|
|
|
use driver::session::Session;
|
2014-08-11 05:59:35 -05:00
|
|
|
use driver::config;
|
2014-07-01 11:39:41 -05:00
|
|
|
use lint;
|
2014-07-07 19:58:01 -05:00
|
|
|
use llvm::{ContextRef, ModuleRef};
|
2013-07-27 01:49:38 -05:00
|
|
|
use metadata::common::LinkMeta;
|
2014-05-06 06:38:01 -05:00
|
|
|
use metadata::creader;
|
2014-09-22 14:08:23 -05:00
|
|
|
use middle::{trans, stability, ty, typeck, reachable};
|
2014-05-02 02:59:27 -05:00
|
|
|
use middle::dependency_format;
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle;
|
2014-05-24 18:16:10 -05:00
|
|
|
use plugin::load::Plugins;
|
|
|
|
use plugin::registry::Registry;
|
|
|
|
use plugin;
|
2014-07-01 11:39:41 -05:00
|
|
|
|
2013-03-21 04:50:02 -05:00
|
|
|
use util::common::time;
|
2014-05-06 06:38:01 -05:00
|
|
|
use util::nodemap::{NodeSet};
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2014-02-21 16:18:39 -06:00
|
|
|
use serialize::{json, Encodable};
|
2014-02-19 01:27:49 -06:00
|
|
|
|
2013-11-11 00:46:32 -06:00
|
|
|
use std::io;
|
|
|
|
use std::io::fs;
|
2014-09-03 02:46:23 -05:00
|
|
|
use std::os;
|
2014-04-22 06:33:15 -05:00
|
|
|
use arena::TypedArena;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::ast;
|
2014-09-07 12:09:06 -05:00
|
|
|
use syntax::ast_map;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::attr;
|
2013-07-19 06:51:37 -05:00
|
|
|
use syntax::attr::{AttrMetaMethods};
|
2014-07-01 11:39:41 -05:00
|
|
|
use syntax::diagnostics;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::parse;
|
2013-05-14 19:27:27 -05:00
|
|
|
use syntax::parse::token;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax;
|
2011-12-20 04:17:13 -06:00
|
|
|
|
2014-05-06 06:38:01 -05:00
|
|
|
pub fn host_triple() -> &'static str {
|
|
|
|
// Get the host triple out of the build environment. This ensures that our
|
|
|
|
// idea of the host triple is the same as for the set of libraries we've
|
|
|
|
// actually built. We can't just take LLVM's host triple because they
|
|
|
|
// normalize all ix86 architectures to i386.
|
|
|
|
//
|
|
|
|
// Instead of grabbing the host triple (for the current host), we grab (at
|
|
|
|
// compile time) the target triple that this rustc is built with and
|
|
|
|
// calling that (at runtime) the host triple.
|
|
|
|
(option_env!("CFG_COMPILER_HOST_TRIPLE")).
|
|
|
|
expect("CFG_COMPILER_HOST_TRIPLE")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn compile_input(sess: Session,
|
|
|
|
cfg: ast::CrateConfig,
|
|
|
|
input: &Input,
|
|
|
|
outdir: &Option<Path>,
|
2014-07-19 23:54:37 -05:00
|
|
|
output: &Option<Path>,
|
|
|
|
addl_plugins: Option<Plugins>) {
|
2014-05-06 06:38:01 -05:00
|
|
|
// We need nested scopes here, because the intermediate results can keep
|
|
|
|
// large chunks of memory alive and we want to free them as soon as
|
|
|
|
// possible to keep the peak memory usage low
|
|
|
|
let (outputs, trans, sess) = {
|
2014-09-07 12:09:06 -05:00
|
|
|
let (outputs, expanded_crate, id) = {
|
2014-05-06 06:38:01 -05:00
|
|
|
let krate = phase_1_parse_input(&sess, cfg, input);
|
|
|
|
if stop_after_phase_1(&sess) { return; }
|
|
|
|
let outputs = build_output_filenames(input,
|
|
|
|
outdir,
|
|
|
|
output,
|
|
|
|
krate.attrs.as_slice(),
|
|
|
|
&sess);
|
2014-06-06 15:21:18 -05:00
|
|
|
let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(),
|
2014-07-05 14:37:43 -05:00
|
|
|
input);
|
2014-09-07 12:09:06 -05:00
|
|
|
let expanded_crate
|
2014-07-19 23:54:37 -05:00
|
|
|
= match phase_2_configure_and_expand(&sess, krate, id.as_slice(),
|
|
|
|
addl_plugins) {
|
2014-06-10 16:03:19 -05:00
|
|
|
None => return,
|
2014-09-07 12:09:06 -05:00
|
|
|
Some(k) => k
|
2014-06-10 16:03:19 -05:00
|
|
|
};
|
|
|
|
|
2014-09-07 12:09:06 -05:00
|
|
|
(outputs, expanded_crate, id)
|
2014-05-06 06:38:01 -05:00
|
|
|
};
|
2014-09-07 12:09:06 -05:00
|
|
|
|
|
|
|
let mut forest = ast_map::Forest::new(expanded_crate);
|
|
|
|
let ast_map = assign_node_ids_and_map(&sess, &mut forest);
|
|
|
|
|
2014-06-06 15:21:18 -05:00
|
|
|
write_out_deps(&sess, input, &outputs, id.as_slice());
|
2014-05-06 06:38:01 -05:00
|
|
|
|
|
|
|
if stop_after_phase_2(&sess) { return; }
|
|
|
|
|
2014-04-22 06:33:15 -05:00
|
|
|
let type_arena = TypedArena::new();
|
2014-09-07 12:09:06 -05:00
|
|
|
let analysis = phase_3_run_analysis_passes(sess, ast_map, &type_arena, id);
|
|
|
|
phase_save_analysis(&analysis.ty_cx.sess, analysis.ty_cx.map.krate(), &analysis, outdir);
|
2014-05-06 06:38:01 -05:00
|
|
|
if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
|
2014-09-07 12:09:06 -05:00
|
|
|
let (tcx, trans) = phase_4_translate_to_llvm(analysis);
|
2014-05-06 06:38:01 -05:00
|
|
|
|
|
|
|
// Discard interned strings as they are no longer required.
|
|
|
|
token::get_ident_interner().clear();
|
|
|
|
|
|
|
|
(outputs, trans, tcx.sess)
|
|
|
|
};
|
|
|
|
phase_5_run_llvm_passes(&sess, &trans, &outputs);
|
|
|
|
if stop_after_phase_5(&sess) { return; }
|
|
|
|
phase_6_link_output(&sess, &trans, &outputs);
|
2012-12-23 16:41:37 -06:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* The name used for source code that doesn't originate in a file
|
|
|
|
* (e.g. source from stdin or a string)
|
|
|
|
*/
|
2014-05-22 18:57:53 -05:00
|
|
|
pub fn anon_src() -> String {
|
2014-05-25 05:17:19 -05:00
|
|
|
"<anon>".to_string()
|
2014-01-15 18:42:51 -06:00
|
|
|
}
|
2012-05-09 21:41:24 -05:00
|
|
|
|
2014-05-22 18:57:53 -05:00
|
|
|
pub fn source_name(input: &Input) -> String {
|
2013-04-17 11:15:37 -05:00
|
|
|
match *input {
|
2014-03-16 13:56:24 -05:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-05-25 05:17:19 -05:00
|
|
|
FileInput(ref ifile) => ifile.as_str().unwrap().to_string(),
|
2014-03-16 13:56:24 -05:00
|
|
|
StrInput(_) => anon_src()
|
2012-05-09 21:41:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-13 10:31:05 -06:00
|
|
|
pub enum Input {
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Load source from file
|
2014-01-13 10:31:05 -06:00
|
|
|
FileInput(Path),
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The string is the source
|
2014-05-22 18:57:53 -05:00
|
|
|
StrInput(String)
|
2012-05-09 21:41:24 -05:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
|
log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
2014-03-09 00:11:44 -06:00
|
|
|
impl Input {
|
2014-05-22 18:57:53 -05:00
|
|
|
fn filestem(&self) -> String {
|
log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
2014-03-09 00:11:44 -06:00
|
|
|
match *self {
|
2014-05-25 05:17:19 -05:00
|
|
|
FileInput(ref ifile) => ifile.filestem_str().unwrap().to_string(),
|
|
|
|
StrInput(_) => "rust_out".to_string(),
|
log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
2014-03-09 00:11:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-18 12:58:26 -05:00
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
|
2013-09-27 21:46:09 -05:00
|
|
|
-> ast::Crate {
|
2014-02-19 01:27:49 -06:00
|
|
|
let krate = time(sess.time_passes(), "parsing", (), |_| {
|
2013-07-27 01:49:38 -05:00
|
|
|
match *input {
|
2014-01-13 10:31:05 -06:00
|
|
|
FileInput(ref file) => {
|
2014-03-09 09:54:34 -05:00
|
|
|
parse::parse_crate_from_file(&(*file), cfg.clone(), &sess.parse_sess)
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
2014-01-15 18:26:20 -06:00
|
|
|
StrInput(ref src) => {
|
2014-05-25 05:17:19 -05:00
|
|
|
parse::parse_crate_from_source_str(anon_src().to_string(),
|
|
|
|
src.to_string(),
|
2014-01-15 18:26:20 -06:00
|
|
|
cfg.clone(),
|
2014-03-09 09:54:34 -05:00
|
|
|
&sess.parse_sess)
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
|
|
|
}
|
2014-02-19 01:27:49 -06:00
|
|
|
});
|
|
|
|
|
2014-05-06 06:38:01 -05:00
|
|
|
if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 {
|
2014-03-18 07:40:07 -05:00
|
|
|
let mut stdout = io::BufferedWriter::new(io::stdout());
|
2014-02-19 01:27:49 -06:00
|
|
|
let mut json = json::PrettyEncoder::new(&mut stdout);
|
2014-03-18 12:58:26 -05:00
|
|
|
// unwrapping so IoError isn't ignored
|
2014-03-28 19:05:46 -05:00
|
|
|
krate.encode(&mut json).unwrap();
|
2014-02-19 01:27:49 -06:00
|
|
|
}
|
|
|
|
|
log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
2014-03-09 00:11:44 -06:00
|
|
|
if sess.show_span() {
|
2014-07-24 21:44:24 -05:00
|
|
|
syntax::show_span::run(sess.diagnostic(), &krate);
|
log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
2014-03-09 00:11:44 -06:00
|
|
|
}
|
|
|
|
|
2014-02-19 01:27:49 -06:00
|
|
|
krate
|
2012-01-17 09:42:45 -06:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
|
2013-01-22 19:19:13 -06:00
|
|
|
// For continuing compilation after a parsed crate has been
|
|
|
|
// modified
|
2013-05-28 17:31:32 -05:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
/// Run the "early phases" of the compiler: initial `cfg` processing,
|
2014-07-20 18:32:46 -05:00
|
|
|
/// loading compiler plugins (including those from `addl_plugins`),
|
2013-07-27 01:49:38 -05:00
|
|
|
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
|
|
|
|
/// harness if one is to be provided and injection of a dependency on the
|
|
|
|
/// standard library and prelude.
|
2014-06-10 16:03:19 -05:00
|
|
|
///
|
|
|
|
/// Returns `None` if we're aborting after handling -W help.
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn phase_2_configure_and_expand(sess: &Session,
|
log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
2014-03-09 00:11:44 -06:00
|
|
|
mut krate: ast::Crate,
|
2014-07-19 23:54:37 -05:00
|
|
|
crate_name: &str,
|
|
|
|
addl_plugins: Option<Plugins>)
|
2014-09-07 12:09:06 -05:00
|
|
|
-> Option<ast::Crate> {
|
2012-05-17 23:53:49 -05:00
|
|
|
let time_passes = sess.time_passes();
|
2011-12-20 04:17:13 -06:00
|
|
|
|
2014-06-06 15:21:18 -05:00
|
|
|
*sess.crate_types.borrow_mut() =
|
|
|
|
collect_crate_types(sess, krate.attrs.as_slice());
|
2014-07-01 00:52:48 -05:00
|
|
|
*sess.crate_metadata.borrow_mut() =
|
|
|
|
collect_crate_metadata(sess, krate.attrs.as_slice());
|
2013-05-09 00:15:54 -05:00
|
|
|
|
2014-09-10 19:55:42 -05:00
|
|
|
time(time_passes, "gated feature checking", (), |_| {
|
|
|
|
let (features, unknown_features) =
|
|
|
|
syntax::feature_gate::check_crate(&sess.parse_sess.span_diagnostic, &krate);
|
|
|
|
|
|
|
|
for uf in unknown_features.iter() {
|
|
|
|
sess.add_lint(lint::builtin::UNKNOWN_FEATURES,
|
|
|
|
ast::CRATE_NODE_ID,
|
|
|
|
*uf,
|
|
|
|
"unknown feature".to_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
sess.abort_if_errors();
|
|
|
|
*sess.features.borrow_mut() = features;
|
|
|
|
});
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2014-09-10 17:35:21 -05:00
|
|
|
let any_exe = sess.crate_types.borrow().iter().any(|ty| {
|
|
|
|
*ty == config::CrateTypeExecutable
|
|
|
|
});
|
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
krate = time(time_passes, "crate injection", krate, |krate|
|
2014-09-10 17:35:21 -05:00
|
|
|
syntax::std_inject::maybe_inject_crates_ref(krate,
|
|
|
|
sess.opts.alt_std_name.clone(),
|
|
|
|
any_exe));
|
2014-01-24 01:40:54 -06:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
// strip before expansion to allow macros to depend on
|
|
|
|
// configuration variables e.g/ in
|
|
|
|
//
|
|
|
|
// #[macro_escape] #[cfg(foo)]
|
|
|
|
// mod bar { macro_rules! baz!(() => {{}}) }
|
|
|
|
//
|
|
|
|
// baz! should not use this definition unless foo is enabled.
|
2013-07-16 00:05:50 -05:00
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
krate = time(time_passes, "configuration 1", krate, |krate|
|
2014-09-24 22:22:57 -05:00
|
|
|
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
|
2013-06-21 22:20:00 -05:00
|
|
|
|
2014-07-19 23:54:37 -05:00
|
|
|
let mut addl_plugins = Some(addl_plugins);
|
2014-05-24 18:16:10 -05:00
|
|
|
let Plugins { macros, registrars }
|
|
|
|
= time(time_passes, "plugin loading", (), |_|
|
2014-08-18 19:52:38 -05:00
|
|
|
plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()));
|
2014-05-24 18:16:10 -05:00
|
|
|
|
|
|
|
let mut registry = Registry::new(&krate);
|
|
|
|
|
|
|
|
time(time_passes, "plugin registration", (), |_| {
|
2014-09-10 19:55:42 -05:00
|
|
|
if sess.features.borrow().rustc_diagnostic_macros {
|
2014-07-01 11:39:41 -05:00
|
|
|
registry.register_macro("__diagnostic_used",
|
|
|
|
diagnostics::plugin::expand_diagnostic_used);
|
|
|
|
registry.register_macro("__register_diagnostic",
|
|
|
|
diagnostics::plugin::expand_register_diagnostic);
|
|
|
|
registry.register_macro("__build_diagnostic_array",
|
|
|
|
diagnostics::plugin::expand_build_diagnostic_array);
|
|
|
|
}
|
|
|
|
|
2014-05-24 18:16:10 -05:00
|
|
|
for ®istrar in registrars.iter() {
|
|
|
|
registrar(&mut registry);
|
2014-04-29 13:38:51 -05:00
|
|
|
}
|
2013-12-25 12:10:33 -06:00
|
|
|
});
|
2013-05-27 19:45:16 -05:00
|
|
|
|
2014-07-20 22:27:59 -05:00
|
|
|
let Registry { syntax_exts, lint_passes, lint_groups, .. } = registry;
|
2014-05-24 18:16:10 -05:00
|
|
|
|
2014-06-18 19:26:14 -05:00
|
|
|
{
|
|
|
|
let mut ls = sess.lint_store.borrow_mut();
|
2014-09-14 22:27:36 -05:00
|
|
|
for pass in lint_passes.into_iter() {
|
2014-06-18 19:26:14 -05:00
|
|
|
ls.register_pass(Some(sess), true, pass);
|
|
|
|
}
|
2014-07-20 22:27:59 -05:00
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
for (name, to) in lint_groups.into_iter() {
|
2014-07-20 22:27:59 -05:00
|
|
|
ls.register_group(Some(sess), true, name, to);
|
|
|
|
}
|
2014-06-18 19:26:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Lint plugins are registered; now we can process command line flags.
|
2014-06-10 16:03:19 -05:00
|
|
|
if sess.opts.describe_lints {
|
2014-06-18 19:26:14 -05:00
|
|
|
super::describe_lints(&*sess.lint_store.borrow(), true);
|
2014-06-10 16:03:19 -05:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
sess.lint_store.borrow_mut().process_command_line(sess);
|
|
|
|
|
|
|
|
// Abort if there are errors from lint processing or a plugin registrar.
|
|
|
|
sess.abort_if_errors();
|
|
|
|
|
2014-05-24 18:16:10 -05:00
|
|
|
krate = time(time_passes, "expansion", (krate, macros, syntax_exts),
|
|
|
|
|(krate, macros, syntax_exts)| {
|
|
|
|
// Windows dlls do not have rpaths, so they don't know how to find their
|
|
|
|
// dependencies. It's up to us to tell the system where to find all the
|
|
|
|
// dependent dlls. Note that this uses cfg!(windows) as opposed to
|
|
|
|
// targ_cfg because syntax extensions are always loaded for the host
|
|
|
|
// compiler, not for the target.
|
2014-09-03 02:46:23 -05:00
|
|
|
let mut _old_path = String::new();
|
2014-05-24 18:16:10 -05:00
|
|
|
if cfg!(windows) {
|
2014-09-03 02:46:23 -05:00
|
|
|
_old_path = os::getenv("PATH").unwrap_or(_old_path);
|
|
|
|
let mut new_path = sess.host_filesearch().get_dylib_search_paths();
|
|
|
|
new_path.push_all_move(os::split_paths(_old_path.as_slice()));
|
|
|
|
os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap());
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
|
|
|
let cfg = syntax::ext::expand::ExpansionConfig {
|
2014-06-06 15:21:18 -05:00
|
|
|
crate_name: crate_name.to_string(),
|
2014-09-26 19:14:23 -05:00
|
|
|
deriving_hash_type_parameter: sess.features.borrow().default_type_params,
|
|
|
|
enable_quotes: sess.features.borrow().quote,
|
2014-10-01 04:38:54 -05:00
|
|
|
recursion_limit: sess.recursion_limit.get(),
|
2014-05-24 18:16:10 -05:00
|
|
|
};
|
2014-09-03 02:46:23 -05:00
|
|
|
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
|
2014-05-24 18:16:10 -05:00
|
|
|
cfg,
|
|
|
|
macros,
|
|
|
|
syntax_exts,
|
2014-09-03 02:46:23 -05:00
|
|
|
krate);
|
|
|
|
if cfg!(windows) {
|
|
|
|
os::setenv("PATH", _old_path);
|
|
|
|
}
|
|
|
|
ret
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2014-07-09 18:41:13 -05:00
|
|
|
// JBC: make CFG processing part of expansion to avoid this problem:
|
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
// strip again, in case expansion added anything with a #[cfg].
|
2014-02-05 15:15:24 -06:00
|
|
|
krate = time(time_passes, "configuration 2", krate, |krate|
|
2014-09-24 22:22:57 -05:00
|
|
|
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
|
2013-05-27 19:45:16 -05:00
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
krate = time(time_passes, "maybe building test harness", krate, |krate|
|
2014-07-24 21:44:24 -05:00
|
|
|
syntax::test::modify_for_testing(&sess.parse_sess,
|
|
|
|
&sess.opts.cfg,
|
|
|
|
krate,
|
|
|
|
sess.diagnostic()));
|
2013-07-19 06:51:37 -05:00
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
krate = time(time_passes, "prelude injection", krate, |krate|
|
2014-09-10 17:35:21 -05:00
|
|
|
syntax::std_inject::maybe_inject_prelude(krate));
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2014-09-07 12:09:06 -05:00
|
|
|
time(time_passes, "checking that all macro invocations are gone", &krate, |krate|
|
|
|
|
syntax::ext::expand::check_for_macros(&sess.parse_sess, krate));
|
|
|
|
|
|
|
|
Some(krate)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn assign_node_ids_and_map<'ast>(sess: &Session,
|
|
|
|
forest: &'ast mut ast_map::Forest)
|
|
|
|
-> ast_map::Map<'ast> {
|
|
|
|
struct NodeIdAssigner<'a> {
|
|
|
|
sess: &'a Session
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ast_map::FoldOps for NodeIdAssigner<'a> {
|
|
|
|
fn new_id(&self, old_id: ast::NodeId) -> ast::NodeId {
|
|
|
|
assert_eq!(old_id, ast::DUMMY_NODE_ID);
|
|
|
|
self.sess.next_node_id()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let map = time(sess.time_passes(), "assigning node ids and indexing ast", forest, |forest|
|
|
|
|
ast_map::map_crate(forest, NodeIdAssigner { sess: sess }));
|
2014-02-19 01:27:49 -06:00
|
|
|
|
2014-05-06 06:38:01 -05:00
|
|
|
if sess.opts.debugging_opts & config::AST_JSON != 0 {
|
2014-03-18 07:40:07 -05:00
|
|
|
let mut stdout = io::BufferedWriter::new(io::stdout());
|
2014-02-19 01:27:49 -06:00
|
|
|
let mut json = json::PrettyEncoder::new(&mut stdout);
|
2014-03-18 12:58:26 -05:00
|
|
|
// unwrapping so IoError isn't ignored
|
2014-09-07 12:09:06 -05:00
|
|
|
map.krate().encode(&mut json).unwrap();
|
2014-02-19 01:27:49 -06:00
|
|
|
}
|
|
|
|
|
2014-09-07 12:09:06 -05:00
|
|
|
map
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
2012-01-26 17:20:29 -06:00
|
|
|
|
2014-04-22 06:33:15 -05:00
|
|
|
pub struct CrateAnalysis<'tcx> {
|
2014-03-28 12:05:27 -05:00
|
|
|
pub exp_map2: middle::resolve::ExportMap2,
|
|
|
|
pub exported_items: middle::privacy::ExportedItems,
|
|
|
|
pub public_items: middle::privacy::PublicItems,
|
2014-04-22 06:33:15 -05:00
|
|
|
pub ty_cx: ty::ctxt<'tcx>,
|
2014-03-28 12:05:27 -05:00
|
|
|
pub reachable: NodeSet,
|
2014-06-06 15:21:18 -05:00
|
|
|
pub name: String,
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-07-09 18:41:13 -05:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
/// Run the resolution, typechecking, region checking and other
|
|
|
|
/// miscellaneous analysis passes on the crate. Return various
|
|
|
|
/// structures carrying the results of the analysis.
|
2014-04-22 06:33:15 -05:00
|
|
|
pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
2014-09-07 12:09:06 -05:00
|
|
|
ast_map: ast_map::Map<'tcx>,
|
2014-04-22 06:33:15 -05:00
|
|
|
type_arena: &'tcx TypedArena<ty::t_box_>,
|
|
|
|
name: String) -> CrateAnalysis<'tcx> {
|
2013-07-27 01:49:38 -05:00
|
|
|
let time_passes = sess.time_passes();
|
2014-09-07 12:09:06 -05:00
|
|
|
let krate = ast_map.krate();
|
2013-09-06 21:11:55 -05:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "external crate/lib resolution", (), |_|
|
2014-04-17 10:52:25 -05:00
|
|
|
creader::read_crates(&sess, krate));
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
let lang_items = time(time_passes, "language item collection", (), |_|
|
2014-03-05 08:36:01 -06:00
|
|
|
middle::lang_items::collect_language_items(krate, &sess));
|
2013-04-29 16:56:05 -05:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
let middle::resolve::CrateMap {
|
2014-09-17 21:45:21 -05:00
|
|
|
def_map,
|
|
|
|
freevars,
|
|
|
|
capture_mode_map,
|
|
|
|
exp_map2,
|
|
|
|
trait_map,
|
|
|
|
external_exports,
|
|
|
|
last_private_map
|
2013-07-27 01:49:38 -05:00
|
|
|
} =
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "resolution", (), |_|
|
2014-04-10 08:58:20 -05:00
|
|
|
middle::resolve::resolve_crate(&sess, &lang_items, krate));
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2014-03-08 16:18:58 -06:00
|
|
|
// Discard MTWT tables that aren't required past resolution.
|
|
|
|
syntax::ext::mtwt::clear_tables();
|
|
|
|
|
2013-10-28 16:37:10 -05:00
|
|
|
let named_region_map = time(time_passes, "lifetime resolution", (),
|
2014-03-05 08:36:01 -06:00
|
|
|
|_| middle::resolve_lifetime::krate(&sess, krate));
|
2013-10-28 16:37:10 -05:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "looking for entry point", (),
|
2014-09-07 12:09:06 -05:00
|
|
|
|_| middle::entry::find_entry_point(&sess, &ast_map));
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2014-05-24 18:16:10 -05:00
|
|
|
sess.plugin_registrar_fn.set(
|
|
|
|
time(time_passes, "looking for plugin registrar", (), |_|
|
|
|
|
plugin::build::find_plugin_registrar(
|
2014-04-13 13:26:43 -05:00
|
|
|
sess.diagnostic(), krate)));
|
2013-12-25 12:10:33 -06:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
let region_map = time(time_passes, "region resolution", (), |_|
|
2014-03-05 08:36:01 -06:00
|
|
|
middle::region::resolve_crate(&sess, krate));
|
2012-01-17 09:42:45 -06:00
|
|
|
|
2014-04-04 18:05:31 -05:00
|
|
|
time(time_passes, "loop checking", (), |_|
|
|
|
|
middle::check_loop::check_crate(&sess, krate));
|
|
|
|
|
Add stability inheritance
This commit makes several changes to the stability index infrastructure:
* Stability levels are now inherited lexically, i.e., each item's
stability level becomes the default for any nested items.
* The computed stability level for an item is stored as part of the
metadata. When using an item from an external crate, this data is
looked up and cached.
* The stability lint works from the computed stability level, rather
than manual stability attribute annotations. However, the lint still
checks only a limited set of item uses (e.g., it does not check every
component of a path on import). This will be addressed in a later PR,
as part of issue #8962.
* The stability lint only applies to items originating from external
crates, since the stability index is intended as a promise to
downstream crates.
* The "experimental" lint is now _allow_ by default. This is because
almost all existing crates have been marked "experimental", pending
library stabilization. With inheritance in place, this would generate
a massive explosion of warnings for every Rust program.
The lint should be changed back to deny-by-default after library
stabilization is complete.
* The "deprecated" lint still warns by default.
The net result: we can begin tracking stability index for the standard
libraries as we stabilize, without impacting most clients.
Closes #13540.
2014-06-11 19:23:11 -05:00
|
|
|
let stability_index = time(time_passes, "stability index", (), |_|
|
|
|
|
stability::Index::build(krate));
|
|
|
|
|
2014-09-14 19:21:25 -05:00
|
|
|
time(time_passes, "static item recursion checking", (), |_|
|
|
|
|
middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
|
|
|
|
|
2014-07-23 14:43:29 -05:00
|
|
|
let ty_cx = ty::mk_ctxt(sess,
|
2014-04-22 06:33:15 -05:00
|
|
|
type_arena,
|
2014-07-23 14:43:29 -05:00
|
|
|
def_map,
|
|
|
|
named_region_map,
|
|
|
|
ast_map,
|
|
|
|
freevars,
|
2014-09-17 21:45:21 -05:00
|
|
|
capture_mode_map,
|
2014-07-23 14:43:29 -05:00
|
|
|
region_map,
|
|
|
|
lang_items,
|
|
|
|
stability_index);
|
2012-09-04 16:48:32 -05:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
// passes are timed inside typeck
|
2014-09-07 12:09:06 -05:00
|
|
|
typeck::check_crate(&ty_cx, trait_map);
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2014-02-26 12:22:41 -06:00
|
|
|
time(time_passes, "check static items", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::check_static::check_crate(&ty_cx));
|
2014-02-26 12:22:41 -06:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
// These next two const passes can probably be merged
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "const marking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::const_eval::process_crate(&ty_cx));
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "const checking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::check_const::check_crate(&ty_cx));
|
2012-06-30 18:19:07 -05:00
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let maps = (external_exports, last_private_map);
|
2014-01-07 20:46:16 -06:00
|
|
|
let (exported_items, public_items) =
|
|
|
|
time(time_passes, "privacy checking", maps, |(a, b)|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::privacy::check_crate(&ty_cx, &exp_map2, a, b));
|
2012-06-30 18:19:07 -05:00
|
|
|
|
2014-06-12 16:08:44 -05:00
|
|
|
time(time_passes, "intrinsic checking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::intrinsicck::check_crate(&ty_cx));
|
2014-06-12 16:08:44 -05:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "effect checking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::effect::check_crate(&ty_cx));
|
2013-05-23 21:12:16 -05:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "match checking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::check_match::check_crate(&ty_cx));
|
2012-12-07 21:34:57 -06:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "liveness checking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::liveness::check_crate(&ty_cx));
|
2012-11-14 20:05:07 -06:00
|
|
|
|
2014-04-15 15:43:24 -05:00
|
|
|
time(time_passes, "borrow checking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
middle::borrowck::check_crate(&ty_cx));
|
2012-11-14 20:05:07 -06:00
|
|
|
|
2014-09-01 22:55:07 -05:00
|
|
|
time(time_passes, "rvalue checking", (), |_|
|
|
|
|
middle::check_rvalues::check_crate(&ty_cx, krate));
|
|
|
|
|
2014-09-22 14:08:23 -05:00
|
|
|
// Avoid overwhelming user with errors if type checking failed.
|
|
|
|
// I'm not sure how helpful this is, to be honest, but it avoids a
|
|
|
|
// lot of annoying errors in the compile-fail tests (basically,
|
|
|
|
// lint warnings and so on -- kindck used to do this abort, but
|
|
|
|
// kindck is gone now). -nmatsakis
|
|
|
|
ty_cx.sess.abort_if_errors();
|
2013-06-14 00:38:17 -05:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
let reachable_map =
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "reachability checking", (), |_|
|
2014-04-09 10:18:40 -05:00
|
|
|
reachable::find_reachable(&ty_cx, &exported_items));
|
2013-06-14 00:38:17 -05:00
|
|
|
|
2014-03-09 06:42:22 -05:00
|
|
|
time(time_passes, "death checking", (), |_| {
|
|
|
|
middle::dead::check_crate(&ty_cx,
|
|
|
|
&exported_items,
|
2014-09-07 12:09:06 -05:00
|
|
|
&reachable_map)
|
2014-03-09 06:42:22 -05:00
|
|
|
});
|
2013-12-08 01:55:27 -06:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(time_passes, "lint checking", (), |_|
|
2014-09-07 12:09:06 -05:00
|
|
|
lint::check_crate(&ty_cx, &exported_items));
|
2013-06-14 20:21:47 -05:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
CrateAnalysis {
|
|
|
|
exp_map2: exp_map2,
|
|
|
|
ty_cx: ty_cx,
|
2013-10-12 16:40:41 -05:00
|
|
|
exported_items: exported_items,
|
2014-01-07 20:46:16 -06:00
|
|
|
public_items: public_items,
|
2014-05-02 02:59:27 -05:00
|
|
|
reachable: reachable_map,
|
2014-06-06 15:21:18 -05:00
|
|
|
name: name,
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
|
|
|
}
|
2013-06-14 00:38:17 -05:00
|
|
|
|
2014-02-04 22:31:33 -06:00
|
|
|
pub fn phase_save_analysis(sess: &Session,
|
|
|
|
krate: &ast::Crate,
|
|
|
|
analysis: &CrateAnalysis,
|
|
|
|
odir: &Option<Path>) {
|
|
|
|
if (sess.opts.debugging_opts & config::SAVE_ANALYSIS) == 0 {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
time(sess.time_passes(), "save analysis", krate, |krate|
|
|
|
|
middle::save::process_crate(sess, krate, analysis, odir));
|
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 12:52:52 -05:00
|
|
|
pub struct ModuleTranslation {
|
|
|
|
pub llcx: ContextRef,
|
|
|
|
pub llmod: ModuleRef,
|
|
|
|
}
|
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
pub struct CrateTranslation {
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 12:52:52 -05:00
|
|
|
pub modules: Vec<ModuleTranslation>,
|
|
|
|
pub metadata_module: ModuleTranslation,
|
2014-03-28 12:05:27 -05:00
|
|
|
pub link: LinkMeta,
|
|
|
|
pub metadata: Vec<u8>,
|
2014-05-22 18:57:53 -05:00
|
|
|
pub reachable: Vec<String>,
|
2014-05-02 02:59:27 -05:00
|
|
|
pub crate_formats: dependency_format::Dependencies,
|
2014-05-14 13:24:12 -05:00
|
|
|
pub no_builtins: bool,
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
2012-02-14 17:21:53 -06:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
/// Run the translation phase to LLVM, after which the AST and analysis can
|
|
|
|
/// be discarded.
|
2014-09-07 12:09:06 -05:00
|
|
|
pub fn phase_4_translate_to_llvm<'tcx>(analysis: CrateAnalysis<'tcx>)
|
|
|
|
-> (ty::ctxt<'tcx>, CrateTranslation) {
|
2014-03-15 15:29:34 -05:00
|
|
|
let time_passes = analysis.ty_cx.sess.time_passes();
|
2014-05-02 02:59:27 -05:00
|
|
|
|
|
|
|
time(time_passes, "resolving dependency formats", (), |_|
|
|
|
|
dependency_format::calculate(&analysis.ty_cx));
|
|
|
|
|
|
|
|
// Option dance to work around the lack of stack once closures.
|
2014-09-07 12:09:06 -05:00
|
|
|
time(time_passes, "translation", analysis, |analysis|
|
|
|
|
trans::base::trans_crate(analysis))
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Run LLVM itself, producing a bitcode file, assembly file or object file
|
|
|
|
/// as a side effect.
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn phase_5_run_llvm_passes(sess: &Session,
|
2013-07-27 01:49:38 -05:00
|
|
|
trans: &CrateTranslation,
|
|
|
|
outputs: &OutputFilenames) {
|
2014-02-06 21:57:09 -06:00
|
|
|
if sess.opts.cg.no_integrated_as {
|
2014-08-11 12:33:58 -05:00
|
|
|
let output_type = write::OutputTypeAssembly;
|
2013-03-15 03:32:39 -05:00
|
|
|
|
2013-10-04 12:46:53 -05:00
|
|
|
time(sess.time_passes(), "LLVM passes", (), |_|
|
2014-08-11 12:33:58 -05:00
|
|
|
write::run_passes(sess, trans, [output_type], outputs));
|
2013-03-15 03:32:39 -05:00
|
|
|
|
2014-08-11 12:33:58 -05:00
|
|
|
write::run_assembler(sess, outputs);
|
2013-08-19 17:21:30 -05:00
|
|
|
|
2013-12-08 22:13:10 -06:00
|
|
|
// Remove assembly source, unless --save-temps was specified
|
2014-02-06 21:57:09 -06:00
|
|
|
if !sess.opts.cg.save_temps {
|
2014-08-11 12:33:58 -05:00
|
|
|
fs::unlink(&outputs.temp_path(write::OutputTypeAssembly)).unwrap();
|
2013-08-19 17:21:30 -05:00
|
|
|
}
|
2013-03-15 03:32:39 -05:00
|
|
|
} else {
|
2013-10-04 12:46:53 -05:00
|
|
|
time(sess.time_passes(), "LLVM passes", (), |_|
|
2014-08-11 12:33:58 -05:00
|
|
|
write::run_passes(sess,
|
|
|
|
trans,
|
|
|
|
sess.opts.output_types.as_slice(),
|
|
|
|
outputs));
|
2013-03-15 03:32:39 -05:00
|
|
|
}
|
2014-09-27 03:33:36 -05:00
|
|
|
|
|
|
|
sess.abort_if_errors();
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
|
2013-07-27 01:49:38 -05:00
|
|
|
/// Run the linker on any artifacts that resulted from the LLVM run.
|
|
|
|
/// This should produce either a finished executable or library.
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn phase_6_link_output(sess: &Session,
|
2013-07-27 01:49:38 -05:00
|
|
|
trans: &CrateTranslation,
|
|
|
|
outputs: &OutputFilenames) {
|
2014-09-03 02:46:23 -05:00
|
|
|
let old_path = os::getenv("PATH").unwrap_or_else(||String::new());
|
2014-09-22 12:14:05 -05:00
|
|
|
let mut new_path = os::split_paths(old_path.as_slice());
|
|
|
|
new_path.push_all_move(sess.host_filesearch().get_tools_search_paths());
|
2014-09-03 02:46:23 -05:00
|
|
|
os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap());
|
|
|
|
|
2013-12-26 13:55:10 -06:00
|
|
|
time(sess.time_passes(), "linking", (), |_|
|
2012-09-18 13:46:39 -05:00
|
|
|
link::link_binary(sess,
|
Store metadata separately in rlib files
Right now whenever an rlib file is linked against, all of the metadata from the
rlib is pulled in to the final staticlib or binary. The reason for this is that
the metadata is currently stored in a section of the object file. Note that this
is intentional for dynamic libraries in order to distribute metadata bundled
with static libraries.
This commit alters the situation for rlib libraries to instead store the
metadata in a separate file in the archive. In doing so, when the archive is
passed to the linker, none of the metadata will get pulled into the result
executable. Furthermore, the metadata file is skipped when assembling rlibs into
an archive.
The snag in this implementation comes with multiple output formats. When
generating a dylib, the metadata needs to be in the object file, but when
generating an rlib this needs to be separate. In order to accomplish this, the
metadata variable is inserted into an entirely separate LLVM Module which is
then codegen'd into a different location (foo.metadata.o). This is then linked
into dynamic libraries and silently ignored for rlib files.
While changing how metadata is inserted into archives, I have also stopped
compressing metadata when inserted into rlib files. We have wanted to stop
compressing metadata, but the sections it creates in object file sections are
apparently too large. Thankfully if it's just an arbitrary file it doesn't
matter how large it is.
I have seen massive reductions in executable sizes, as well as staticlib output
sizes (to confirm that this is all working).
2013-12-03 19:41:01 -06:00
|
|
|
trans,
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
outputs,
|
2014-06-06 15:21:18 -05:00
|
|
|
trans.link.crate_name.as_slice()));
|
2014-09-03 02:46:23 -05:00
|
|
|
|
|
|
|
os::setenv("PATH", old_path);
|
2013-12-26 13:55:10 -06:00
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn stop_after_phase_3(sess: &Session) -> bool {
|
2013-12-26 13:55:10 -06:00
|
|
|
if sess.opts.no_trans {
|
|
|
|
debug!("invoked with --no-trans, returning early from compile_input");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn stop_after_phase_1(sess: &Session) -> bool {
|
2013-12-26 13:55:10 -06:00
|
|
|
if sess.opts.parse_only {
|
|
|
|
debug!("invoked with --parse-only, returning early from compile_input");
|
|
|
|
return true;
|
|
|
|
}
|
log: Introduce liblog, the old std::logging
This commit moves all logging out of the standard library into an external
crate. This crate is the new crate which is responsible for all logging macros
and logging implementation. A few reasons for this change are:
* The crate map has always been a bit of a code smell among rust programs. It
has difficulty being loaded on almost all platforms, and it's used almost
exclusively for logging and only logging. Removing the crate map is one of the
end goals of this movement.
* The compiler has a fair bit of special support for logging. It has the
__log_level() expression as well as generating a global word per module
specifying the log level. This is unfairly favoring the built-in logging
system, and is much better done purely in libraries instead of the compiler
itself.
* Initialization of logging is much easier to do if there is no reliance on a
magical crate map being available to set module log levels.
* If the logging library can be written outside of the standard library, there's
no reason that it shouldn't be. It's likely that we're not going to build the
highest quality logging library of all time, so third-party libraries should
be able to provide just as high-quality logging systems as the default one
provided in the rust distribution.
With a migration such as this, the change does not come for free. There are some
subtle changes in the behavior of liblog vs the previous logging macros:
* The core change of this migration is that there is no longer a physical
log-level per module. This concept is still emulated (it is quite useful), but
there is now only a global log level, not a local one. This global log level
is a reflection of the maximum of all log levels specified. The previously
generated logging code looked like:
if specified_level <= __module_log_level() {
println!(...)
}
The newly generated code looks like:
if specified_level <= ::log::LOG_LEVEL {
if ::log::module_enabled(module_path!()) {
println!(...)
}
}
Notably, the first layer of checking is still intended to be "super fast" in
that it's just a load of a global word and a compare. The second layer of
checking is executed to determine if the current module does indeed have
logging turned on.
This means that if any module has a debug log level turned on, all modules
with debug log levels get a little bit slower (they all do more expensive
dynamic checks to determine if they're turned on or not).
Semantically, this migration brings no change in this respect, but
runtime-wise, this will have a perf impact on some code.
* A `RUST_LOG=::help` directive will no longer print out a list of all modules
that can be logged. This is because the crate map will no longer specify the
log levels of all modules, so the list of modules is not known. Additionally,
warnings can no longer be provided if a malformed logging directive was
supplied.
The new "hello world" for logging looks like:
#[phase(syntax, link)]
extern crate log;
fn main() {
debug!("Hello, world!");
}
2014-03-09 00:11:44 -06:00
|
|
|
if sess.show_span() {
|
|
|
|
return true;
|
|
|
|
}
|
2014-05-06 06:38:01 -05:00
|
|
|
return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0;
|
2013-12-26 13:55:10 -06:00
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn stop_after_phase_2(sess: &Session) -> bool {
|
2013-12-26 16:39:36 -06:00
|
|
|
if sess.opts.no_analysis {
|
|
|
|
debug!("invoked with --no-analysis, returning early from compile_input");
|
|
|
|
return true;
|
|
|
|
}
|
2014-05-06 06:38:01 -05:00
|
|
|
return sess.opts.debugging_opts & config::AST_JSON != 0;
|
2013-12-26 16:39:36 -06:00
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn stop_after_phase_5(sess: &Session) -> bool {
|
2014-08-11 12:33:58 -05:00
|
|
|
if !sess.opts.output_types.iter().any(|&i| i == write::OutputTypeExe) {
|
2013-12-26 13:55:10 -06:00
|
|
|
debug!("not building executable, returning early from compile_input");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-10-01 06:47:38 -05:00
|
|
|
fn escape_dep_filename(filename: &str) -> String {
|
|
|
|
// Apparently clang and gcc *only* escape spaces:
|
|
|
|
// http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
|
|
|
|
filename.replace(" ", "\\ ")
|
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
fn write_out_deps(sess: &Session,
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
input: &Input,
|
|
|
|
outputs: &OutputFilenames,
|
2014-06-06 15:21:18 -05:00
|
|
|
id: &str) {
|
2013-12-26 13:55:10 -06:00
|
|
|
|
2014-03-04 12:02:49 -06:00
|
|
|
let mut out_filenames = Vec::new();
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
for output_type in sess.opts.output_types.iter() {
|
|
|
|
let file = outputs.path(*output_type);
|
|
|
|
match *output_type {
|
2014-08-11 12:33:58 -05:00
|
|
|
write::OutputTypeExe => {
|
2014-03-20 21:49:20 -05:00
|
|
|
for output in sess.crate_types.borrow().iter() {
|
2014-06-06 15:21:18 -05:00
|
|
|
let p = link::filename_for_input(sess, *output,
|
|
|
|
id, &file);
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
out_filenames.push(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => { out_filenames.push(file); }
|
|
|
|
}
|
|
|
|
}
|
2013-11-27 21:06:35 -06:00
|
|
|
|
2014-01-29 20:42:19 -06:00
|
|
|
// Write out dependency rules to the dep-info file if requested with
|
|
|
|
// --dep-info
|
2013-12-22 14:38:55 -06:00
|
|
|
let deps_filename = match sess.opts.write_dependency_info {
|
|
|
|
// Use filename from --dep-file argument if given
|
|
|
|
(true, Some(ref filename)) => filename.clone(),
|
2014-01-29 20:42:19 -06:00
|
|
|
// Use default filename: crate source filename with extension replaced
|
|
|
|
// by ".d"
|
2013-12-22 14:38:55 -06:00
|
|
|
(true, None) => match *input {
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
FileInput(..) => outputs.with_extension("d"),
|
2014-01-13 10:31:05 -06:00
|
|
|
StrInput(..) => {
|
2014-01-29 20:42:19 -06:00
|
|
|
sess.warn("can not write --dep-info without a filename \
|
|
|
|
when compiling stdin.");
|
2014-04-15 09:35:17 -05:00
|
|
|
return
|
2013-12-22 14:38:55 -06:00
|
|
|
},
|
|
|
|
},
|
2014-04-15 09:35:17 -05:00
|
|
|
_ => return,
|
2013-12-22 14:38:55 -06:00
|
|
|
};
|
2013-12-26 13:55:10 -06:00
|
|
|
|
2014-04-15 09:35:17 -05:00
|
|
|
let result = (|| {
|
|
|
|
// Build a list of files used to compile the output and
|
|
|
|
// write Makefile-compatible dependency rules
|
2014-05-22 18:57:53 -05:00
|
|
|
let files: Vec<String> = sess.codemap().files.borrow()
|
2014-04-15 09:35:17 -05:00
|
|
|
.iter().filter(|fmap| fmap.is_real_file())
|
2014-10-01 06:47:38 -05:00
|
|
|
.map(|fmap| escape_dep_filename(fmap.name.as_slice()))
|
2014-04-15 09:35:17 -05:00
|
|
|
.collect();
|
|
|
|
let mut file = try!(io::File::create(&deps_filename));
|
|
|
|
for path in out_filenames.iter() {
|
|
|
|
try!(write!(&mut file as &mut Writer,
|
|
|
|
"{}: {}\n\n", path.display(), files.connect(" ")));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})();
|
|
|
|
|
|
|
|
match result {
|
|
|
|
Ok(()) => {}
|
|
|
|
Err(e) => {
|
|
|
|
sess.fatal(format!("error writing dependencies to `{}`: {}",
|
2014-05-16 12:45:16 -05:00
|
|
|
deps_filename.display(), e).as_slice());
|
2014-04-15 09:35:17 -05:00
|
|
|
}
|
2013-07-27 01:49:38 -05:00
|
|
|
}
|
2013-01-22 19:19:13 -06:00
|
|
|
}
|
|
|
|
|
2014-05-06 06:38:01 -05:00
|
|
|
pub fn collect_crate_types(session: &Session,
|
|
|
|
attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
|
2014-05-23 00:29:13 -05:00
|
|
|
// Unconditionally collect crate types from attributes to make them used
|
|
|
|
let attr_types: Vec<config::CrateType> = attrs.iter().filter_map(|a| {
|
|
|
|
if a.check_name("crate_type") {
|
|
|
|
match a.value_str() {
|
|
|
|
Some(ref n) if n.equiv(&("rlib")) => {
|
|
|
|
Some(config::CrateTypeRlib)
|
|
|
|
}
|
|
|
|
Some(ref n) if n.equiv(&("dylib")) => {
|
|
|
|
Some(config::CrateTypeDylib)
|
|
|
|
}
|
|
|
|
Some(ref n) if n.equiv(&("lib")) => {
|
|
|
|
Some(config::default_lib_output())
|
|
|
|
}
|
|
|
|
Some(ref n) if n.equiv(&("staticlib")) => {
|
|
|
|
Some(config::CrateTypeStaticlib)
|
|
|
|
}
|
|
|
|
Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable),
|
|
|
|
Some(_) => {
|
2014-10-14 13:37:16 -05:00
|
|
|
session.add_lint(lint::builtin::UNKNOWN_CRATE_TYPES,
|
2014-05-23 00:29:13 -05:00
|
|
|
ast::CRATE_NODE_ID,
|
|
|
|
a.span,
|
|
|
|
"invalid `crate_type` \
|
2014-05-25 05:17:19 -05:00
|
|
|
value".to_string());
|
2014-05-23 00:29:13 -05:00
|
|
|
None
|
|
|
|
}
|
|
|
|
_ => {
|
2014-10-14 13:37:16 -05:00
|
|
|
session.add_lint(lint::builtin::UNKNOWN_CRATE_TYPES,
|
2014-05-23 00:29:13 -05:00
|
|
|
ast::CRATE_NODE_ID,
|
|
|
|
a.span,
|
|
|
|
"`crate_type` requires a \
|
2014-05-25 05:17:19 -05:00
|
|
|
value".to_string());
|
2014-05-23 00:29:13 -05:00
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}).collect();
|
|
|
|
|
2014-05-06 06:38:01 -05:00
|
|
|
// If we're generating a test executable, then ignore all other output
|
|
|
|
// styles at all other locations
|
|
|
|
if session.opts.test {
|
|
|
|
return vec!(config::CrateTypeExecutable)
|
2013-06-15 02:43:19 -05:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
|
2014-05-06 06:38:01 -05:00
|
|
|
// 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();
|
2014-06-11 02:48:17 -05:00
|
|
|
if base.len() == 0 {
|
2014-09-14 22:27:36 -05:00
|
|
|
base.extend(attr_types.into_iter());
|
2014-05-06 06:38:01 -05:00
|
|
|
if base.len() == 0 {
|
2014-06-11 02:48:17 -05:00
|
|
|
base.push(link::default_output_for_target(session));
|
2014-04-30 18:49:12 -05:00
|
|
|
}
|
2014-05-06 06:38:01 -05:00
|
|
|
base.as_mut_slice().sort();
|
|
|
|
base.dedup();
|
2012-03-12 12:19:35 -05:00
|
|
|
}
|
2014-06-11 02:48:17 -05:00
|
|
|
|
2014-09-14 22:27:36 -05:00
|
|
|
base.into_iter().filter(|crate_type| {
|
2014-06-11 02:48:17 -05:00
|
|
|
let res = !link::invalid_output_for_target(session, *crate_type);
|
|
|
|
|
|
|
|
if !res {
|
|
|
|
session.warn(format!("dropping unsupported crate type `{}` \
|
|
|
|
for target os `{}`",
|
|
|
|
*crate_type, session.targ_cfg.os).as_slice());
|
|
|
|
}
|
|
|
|
|
|
|
|
res
|
|
|
|
}).collect()
|
2011-12-20 04:17:13 -06:00
|
|
|
}
|
|
|
|
|
2014-07-01 00:52:48 -05:00
|
|
|
pub fn collect_crate_metadata(session: &Session,
|
|
|
|
_attrs: &[ast::Attribute]) -> Vec<String> {
|
|
|
|
session.opts.cg.metadata.clone()
|
|
|
|
}
|
|
|
|
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 12:52:52 -05:00
|
|
|
#[deriving(Clone)]
|
2013-02-19 01:40:42 -06:00
|
|
|
pub struct OutputFilenames {
|
2014-03-28 12:05:27 -05:00
|
|
|
pub out_directory: Path,
|
2014-05-22 18:57:53 -05:00
|
|
|
pub out_filestem: String,
|
2014-03-28 12:05:27 -05:00
|
|
|
pub single_output_file: Option<Path>,
|
2014-07-15 11:13:58 -05:00
|
|
|
extra: String,
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl OutputFilenames {
|
2014-08-11 12:33:58 -05:00
|
|
|
pub fn path(&self, flavor: write::OutputType) -> Path {
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
match self.single_output_file {
|
|
|
|
Some(ref path) => return path.clone(),
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
self.temp_path(flavor)
|
|
|
|
}
|
|
|
|
|
2014-08-11 12:33:58 -05:00
|
|
|
pub fn temp_path(&self, flavor: write::OutputType) -> Path {
|
2014-07-15 11:13:58 -05:00
|
|
|
let base = self.out_directory.join(self.filestem());
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
match flavor {
|
2014-08-11 12:33:58 -05:00
|
|
|
write::OutputTypeBitcode => base.with_extension("bc"),
|
|
|
|
write::OutputTypeAssembly => base.with_extension("s"),
|
|
|
|
write::OutputTypeLlvmAssembly => base.with_extension("ll"),
|
|
|
|
write::OutputTypeObject => base.with_extension("o"),
|
|
|
|
write::OutputTypeExe => base,
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_extension(&self, extension: &str) -> Path {
|
2014-07-15 11:13:58 -05:00
|
|
|
self.out_directory.join(self.filestem()).with_extension(extension)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn filestem(&self) -> String {
|
|
|
|
format!("{}{}", self.out_filestem, self.extra)
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
}
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
2012-01-17 09:42:45 -06:00
|
|
|
|
2014-01-13 10:31:05 -06:00
|
|
|
pub fn build_output_filenames(input: &Input,
|
2013-01-29 17:16:07 -06:00
|
|
|
odir: &Option<Path>,
|
|
|
|
ofile: &Option<Path>,
|
2013-07-19 06:51:37 -05:00
|
|
|
attrs: &[ast::Attribute],
|
2014-03-05 08:36:01 -06:00
|
|
|
sess: &Session)
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
-> OutputFilenames {
|
2012-08-24 17:28:43 -05:00
|
|
|
match *ofile {
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
None => {
|
|
|
|
// "-" as input file will cause the parser to read from stdin so we
|
|
|
|
// have to make up a name
|
|
|
|
// We want to toss everything after the final '.'
|
|
|
|
let dirpath = match *odir {
|
|
|
|
Some(ref d) => d.clone(),
|
2014-02-10 23:06:01 -06:00
|
|
|
None => Path::new(".")
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
};
|
|
|
|
|
2014-06-06 15:21:18 -05:00
|
|
|
// If a crate name is present, we use it as the link name
|
2014-07-07 21:04:34 -05:00
|
|
|
let stem = sess.opts.crate_name.clone().or_else(|| {
|
|
|
|
attr::find_crate_name(attrs).map(|n| n.get().to_string())
|
|
|
|
}).or_else(|| {
|
|
|
|
// NB: this clause can be removed once #[crate_id] is no longer
|
|
|
|
// deprecated.
|
|
|
|
//
|
|
|
|
// Also note that this will be warned about later so we don't
|
|
|
|
// warn about it here.
|
|
|
|
use syntax::crateid::CrateId;
|
|
|
|
attrs.iter().find(|at| at.check_name("crate_id"))
|
|
|
|
.and_then(|at| at.value_str())
|
|
|
|
.and_then(|s| from_str::<CrateId>(s.get()))
|
|
|
|
.map(|id| id.name)
|
|
|
|
}).unwrap_or(input.filestem());
|
|
|
|
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
OutputFilenames {
|
|
|
|
out_directory: dirpath,
|
|
|
|
out_filestem: stem,
|
|
|
|
single_output_file: None,
|
2014-07-15 11:13:58 -05:00
|
|
|
extra: sess.opts.cg.extra_filename.clone(),
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
}
|
|
|
|
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
Some(ref out_file) => {
|
|
|
|
let ofile = if sess.opts.output_types.len() > 1 {
|
|
|
|
sess.warn("ignoring specified output filename because multiple \
|
|
|
|
outputs were requested");
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(out_file.clone())
|
|
|
|
};
|
|
|
|
if *odir != None {
|
|
|
|
sess.warn("ignoring --out-dir flag due to -o flag.");
|
|
|
|
}
|
|
|
|
OutputFilenames {
|
|
|
|
out_directory: out_file.dir_path(),
|
2014-05-25 05:17:19 -05:00
|
|
|
out_filestem: out_file.filestem_str().unwrap().to_string(),
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
single_output_file: ofile,
|
2014-07-15 11:13:58 -05:00
|
|
|
extra: sess.opts.cg.extra_filename.clone(),
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 17:27:54 -06:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
}
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
2011-12-20 04:17:13 -06:00
|
|
|
}
|