auto merge of #8362 : sfackler/rust/env, r=alexcrichton

env! aborts compilation of the specified environment variable is not
defined and takes an optional second argument containing a custom
error message. option_env! creates an Option<&'static str> containing
the value of the environment variable.

There are no run-pass tests that check the behavior when the environment
variable is defined since the test framework doesn't support setting
environment variables at compile time as opposed to runtime. However,
both env! and option_env! are used inside of rustc itself, which should
act as a sufficient test.

Fixes #2248.
This commit is contained in:
bors 2013-08-09 05:35:06 -07:00
commit 6928a10e3f
19 changed files with 170 additions and 34 deletions

View File

@ -168,6 +168,7 @@ pub fn get_absolute_rpath(lib: &Path) -> Path {
os::make_absolute(lib).dir_path() os::make_absolute(lib).dir_path()
} }
#[cfg(stage0)]
pub fn get_install_prefix_rpath(target_triple: &str) -> Path { pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
let install_prefix = env!("CFG_PREFIX"); let install_prefix = env!("CFG_PREFIX");
@ -179,6 +180,14 @@ pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
os::make_absolute(&Path(install_prefix).push_rel(&tlib)) os::make_absolute(&Path(install_prefix).push_rel(&tlib))
} }
#[cfg(not(stage0))]
pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
let install_prefix = env!("CFG_PREFIX");
let tlib = filesearch::relative_target_lib_path(target_triple);
os::make_absolute(&Path(install_prefix).push_rel(&tlib))
}
pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] { pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
let mut set = HashSet::new(); let mut set = HashSet::new();
let mut minimized = ~[]; let mut minimized = ~[];

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -578,6 +578,7 @@ pub fn build_target_config(sopts: @session::options,
return target_cfg; return target_cfg;
} }
#[cfg(stage0)]
pub fn host_triple() -> ~str { pub fn host_triple() -> ~str {
// Get the host triple out of the build environment. This ensures that our // 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 // idea of the host triple is the same as for the set of libraries we've
@ -595,6 +596,19 @@ pub fn host_triple() -> ~str {
}; };
} }
#[cfg(not(stage0))]
pub fn host_triple() -> ~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.
(env!("CFG_COMPILER_TRIPLE")).to_owned()
}
pub fn build_session_options(binary: @str, pub fn build_session_options(binary: @str,
matches: &getopts::Matches, matches: &getopts::Matches,
demitter: diagnostic::Emitter) demitter: diagnostic::Emitter)

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -186,6 +186,7 @@ fn get_rustpkg_lib_path_nearest() -> Result<Path, ~str> {
// The name of the directory rustc expects libraries to be located. // The name of the directory rustc expects libraries to be located.
// On Unix should be "lib", on windows "bin" // On Unix should be "lib", on windows "bin"
#[cfg(stage0)]
pub fn libdir() -> ~str { pub fn libdir() -> ~str {
let libdir = env!("CFG_LIBDIR"); let libdir = env!("CFG_LIBDIR");
if libdir.is_empty() { if libdir.is_empty() {
@ -193,3 +194,8 @@ pub fn libdir() -> ~str {
} }
libdir.to_owned() libdir.to_owned()
} }
#[cfg(not(stage0))]
pub fn libdir() -> ~str {
(env!("CFG_LIBDIR")).to_owned()
}

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -4994,7 +4994,9 @@ impl Resolver {
if self.structs.contains(&class_id) => { if self.structs.contains(&class_id) => {
self.record_def(expr.id, definition); self.record_def(expr.id, definition);
} }
_ => { result => {
debug!("(resolving expression) didn't find struct \
def: %?", result);
self.session.span_err( self.session.span_err(
path.span, path.span,
fmt!("`%s` does not name a structure", fmt!("`%s` does not name a structure",

View File

@ -117,6 +117,7 @@ mod std {
} }
*/ */
#[cfg(stage0)]
pub fn version(argv0: &str) { pub fn version(argv0: &str) {
let mut vers = ~"unknown version"; let mut vers = ~"unknown version";
let env_vers = env!("CFG_VERSION"); let env_vers = env!("CFG_VERSION");
@ -125,6 +126,16 @@ pub fn version(argv0: &str) {
printfln!("host: %s", host_triple()); printfln!("host: %s", host_triple());
} }
#[cfg(not(stage0))]
pub fn version(argv0: &str) {
let vers = match option_env!("CFG_VERSION") {
Some(vers) => vers,
None => "unknown version"
};
printfln!("%s %s", argv0, vers);
printfln!("host: %s", host_triple());
}
pub fn usage(argv0: &str) { pub fn usage(argv0: &str) {
let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0); let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0);
printfln!("%s\ printfln!("%s\

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -59,7 +59,7 @@ pub fn expand_asm(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
match state { match state {
Asm => { Asm => {
asm = expr_to_str(cx, p.parse_expr(), asm = expr_to_str(cx, p.parse_expr(),
~"inline assembly must be a string literal."); "inline assembly must be a string literal.");
} }
Outputs => { Outputs => {
while *p.token != token::EOF && while *p.token != token::EOF &&

View File

@ -148,7 +148,9 @@ pub fn syntax_expander_table() -> SyntaxEnv {
intern(&"auto_decode"), intern(&"auto_decode"),
@SE(ItemDecorator(ext::auto_encode::expand_auto_decode))); @SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
syntax_expanders.insert(intern(&"env"), syntax_expanders.insert(intern(&"env"),
builtin_normal_tt(ext::env::expand_syntax_ext)); builtin_normal_tt(ext::env::expand_env));
syntax_expanders.insert(intern(&"option_env"),
builtin_normal_tt(ext::env::expand_option_env));
syntax_expanders.insert(intern("bytes"), syntax_expanders.insert(intern("bytes"),
builtin_normal_tt(ext::bytes::expand_syntax_ext)); builtin_normal_tt(ext::bytes::expand_syntax_ext));
syntax_expanders.insert(intern("concat_idents"), syntax_expanders.insert(intern("concat_idents"),
@ -313,7 +315,7 @@ impl ExtCtxt {
} }
} }
pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: ~str) -> @str { pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: &str) -> @str {
match expr.node { match expr.node {
ast::expr_lit(l) => match l.node { ast::expr_lit(l) => match l.node {
ast::lit_str(s) => s, ast::lit_str(s) => s,
@ -538,8 +540,8 @@ mod test {
a.insert (@"abc",@15); a.insert (@"abc",@15);
let m = MapChain::new(~a); let m = MapChain::new(~a);
m.insert (@"def",@16); m.insert (@"def",@16);
// FIXME: #4492 (ICE) assert_eq!(m.find(&@"abc"),Some(@15)); assert_eq!(m.find(&@"abc"),Some(@15));
// .... assert_eq!(m.find(&@"def"),Some(@16)); assert_eq!(m.find(&@"def"),Some(@16));
assert_eq!(*(m.find(&@"abc").unwrap()),15); assert_eq!(*(m.find(&@"abc").unwrap()),15);
assert_eq!(*(m.find(&@"def").unwrap()),16); assert_eq!(*(m.find(&@"def").unwrap()),16);
let n = m.push_frame(); let n = m.push_frame();
@ -551,8 +553,8 @@ mod test {
assert_eq!(*(n.find(&@"abc").unwrap()),15); assert_eq!(*(n.find(&@"abc").unwrap()),15);
assert_eq!(*(n.find(&@"def").unwrap()),17); assert_eq!(*(n.find(&@"def").unwrap()),17);
// ... but m still has the old ones // ... but m still has the old ones
// FIXME: #4492: assert_eq!(m.find(&@"abc"),Some(@15)); assert_eq!(m.find(&@"abc"),Some(@15));
// FIXME: #4492: assert_eq!(m.find(&@"def"),Some(@16)); assert_eq!(m.find(&@"def"),Some(@16));
assert_eq!(*(m.find(&@"abc").unwrap()),15); assert_eq!(*(m.find(&@"abc").unwrap()),15);
assert_eq!(*(m.find(&@"def").unwrap()),16); assert_eq!(*(m.find(&@"def").unwrap()),16);
} }

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -22,17 +22,35 @@ use ext::build::AstBuilder;
use std::os; use std::os;
pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) pub fn expand_option_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
-> base::MacResult { -> base::MacResult {
let var = get_single_str_from_tts(ext_cx, sp, tts, "option_env!");
let var = get_single_str_from_tts(cx, sp, tts, "env!");
// FIXME (#2248): if this was more thorough it would manufacture an
// Option<str> rather than just an maybe-empty string.
let e = match os::getenv(var) { let e = match os::getenv(var) {
None => cx.expr_str(sp, @""), None => quote_expr!(::std::option::None),
Some(s) => cx.expr_str(sp, s.to_managed()) Some(s) => quote_expr!(::std::option::Some($s))
};
MRExpr(e)
}
pub fn expand_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
-> base::MacResult {
let exprs = get_exprs_from_tts(ext_cx, sp, tts);
if exprs.len() == 0 {
ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments");
}
let var = expr_to_str(ext_cx, exprs[0], "expected string literal");
let msg = match exprs.len() {
1 => fmt!("Environment variable %s not defined", var).to_managed(),
2 => expr_to_str(ext_cx, exprs[1], "expected string literal"),
_ => ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments")
};
let e = match os::getenv(var) {
None => ext_cx.span_fatal(sp, msg),
Some(s) => ext_cx.expr_str(sp, s.to_managed())
}; };
MRExpr(e) MRExpr(e)
} }

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -32,7 +32,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
} }
let fmt = let fmt =
expr_to_str(cx, args[0], expr_to_str(cx, args[0],
~"first argument to fmt! must be a string literal."); "first argument to fmt! must be a string literal.");
let fmtspan = args[0].span; let fmtspan = args[0].span;
debug!("Format string: %s", fmt); debug!("Format string: %s", fmt);
fn parse_fmt_err_(cx: @ExtCtxt, sp: span, msg: &str) -> ! { fn parse_fmt_err_(cx: @ExtCtxt, sp: span, msg: &str) -> ! {

View File

@ -0,0 +1,11 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() { env!("one", 10); } //~ ERROR: expected string literal

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -8,6 +8,4 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// error-pattern: env! takes 1 argument fn main() { env!(); } //~ ERROR: env! takes 1 or 2 arguments
fn main() { env!(); }

View File

@ -0,0 +1,11 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } //~ ERROR: my error message

View File

@ -0,0 +1,11 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() { env!("__HOPEFULLY_NOT_DEFINED__"); } //~ ERROR: Environment variable __HOPEFULLY_NOT_DEFINED__ not defined

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -8,6 +8,4 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// error-pattern:requires a string fn main() { env!(10, "two"); } //~ ERROR: expected string literal
fn main() { env!(10); }

View File

@ -8,6 +8,4 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// error-pattern: env! takes 1 argument fn main() { env!("one", "two", "three"); } //~ ERROR: env! takes 1 or 2 arguments
fn main() { env!("one", "two"); }

View File

@ -0,0 +1,11 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() { option_env!(); } //~ ERROR: option_env! takes 1 argument

View File

@ -0,0 +1,11 @@
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() { option_env!(10); } //~ ERROR: requires a string

View File

@ -0,0 +1,11 @@
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() { option_env!("one", "two"); } //~ ERROR: option_env! takes 1 argument

View File

@ -0,0 +1,14 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let opt: Option<&'static str> = option_env!("__HOPEFULLY_DOESNT_EXIST__");
assert!(opt.is_none());
}