about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-11-02 18:44:27 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-11-03 08:31:44 -0800
commit6478fcfafe390355c4cc2f7e22cfbf4cd1f5eeee (patch)
tree043fbec89cb67ff0f10a117c326d3d853b6417a0 /src
parent566ee9ecb3f40d8de93a9b4c5c90e1c26b12b5e1 (diff)
parent8e6e846d8a26e5a9d3aafd0bdcc18ed3ddf0cbca (diff)
downloadrust-6478fcfafe390355c4cc2f7e22cfbf4cd1f5eeee.tar.gz
rust-6478fcfafe390355c4cc2f7e22cfbf4cd1f5eeee.zip
rollup merge of #18470 : alexcrichton/dash-l
Diffstat (limited to 'src')
-rw-r--r--src/librustc/driver/config.rs27
-rw-r--r--src/librustc/metadata/creader.rs50
-rw-r--r--src/librustc/metadata/cstore.rs2
-rw-r--r--src/libsyntax/ext/base.rs23
-rw-r--r--src/libsyntax/ext/source_util.rs35
-rw-r--r--src/test/auxiliary/macro-include-items-expr.rs13
-rw-r--r--src/test/auxiliary/macro-include-items-item.rs13
-rw-r--r--src/test/compile-fail/manual-link-bad-form.rs17
-rw-r--r--src/test/compile-fail/manual-link-bad-kind.rs16
-rw-r--r--src/test/compile-fail/manual-link-framework.rs17
-rw-r--r--src/test/run-make/manual-link/Makefile7
-rw-r--r--src/test/run-make/manual-link/bar.c1
-rw-r--r--src/test/run-make/manual-link/foo.c1
-rw-r--r--src/test/run-make/manual-link/foo.rs19
-rw-r--r--src/test/run-make/manual-link/main.rs15
-rw-r--r--src/test/run-pass/macro-include-items.rs18
16 files changed, 234 insertions, 40 deletions
diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs
index ace5ba26fdb..efe7de6b94d 100644
--- a/src/librustc/driver/config.rs
+++ b/src/librustc/driver/config.rs
@@ -20,6 +20,7 @@ use back::write;
 use back::target_strs;
 use back::{arm, x86, x86_64, mips, mipsel};
 use lint;
+use metadata::cstore;
 
 use syntax::abi;
 use syntax::ast;
@@ -78,6 +79,7 @@ pub struct Options {
     // parsed code. It remains mutable in case its replacements wants to use
     // this.
     pub addl_lib_search_paths: RefCell<Vec<Path>>,
+    pub libs: Vec<(String, cstore::NativeLibaryKind)>,
     pub maybe_sysroot: Option<Path>,
     pub target_triple: String,
     // User-specified cfg meta items. The compiler itself will add additional
@@ -130,6 +132,7 @@ pub fn basic_options() -> Options {
         externs: HashMap::new(),
         crate_name: None,
         alt_std_name: None,
+        libs: Vec::new(),
     }
 }
 
@@ -575,6 +578,10 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
         optflag("h", "help", "Display this message"),
         optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
         optmulti("L", "",   "Add a directory to the library search path", "PATH"),
+        optmulti("l", "",   "Link the generated crate(s) to the specified native
+                             library NAME. The optional KIND can be one of,
+                             static, dylib, or framework. If omitted, dylib is
+                             assumed.", "NAME[:KIND]"),
         optmulti("", "crate-type", "Comma separated list of types of crates
                                     for the compiler to emit",
                  "[bin|lib|rlib|dylib|staticlib]"),
@@ -767,6 +774,23 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         Path::new(s.as_slice())
     }).collect();
 
+    let libs = matches.opt_strs("l").into_iter().map(|s| {
+        let mut parts = s.as_slice().rsplitn(1, ':');
+        let kind = parts.next().unwrap();
+        let (name, kind) = match (parts.next(), kind) {
+            (None, name) |
+            (Some(name), "dylib") => (name, cstore::NativeUnknown),
+            (Some(name), "framework") => (name, cstore::NativeFramework),
+            (Some(name), "static") => (name, cstore::NativeStatic),
+            (_, s) => {
+                early_error(format!("unknown library kind `{}`, expected \
+                                     one of dylib, framework, or static",
+                                    s).as_slice());
+            }
+        };
+        (name.to_string(), kind)
+    }).collect();
+
     let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
     let test = matches.opt_present("test");
     let write_dependency_info = (matches.opt_present("dep-info"),
@@ -843,7 +867,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         color: color,
         externs: externs,
         crate_name: crate_name,
-        alt_std_name: None
+        alt_std_name: None,
+        libs: libs,
     }
 }
 
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 92b2382ae64..432ca497cf2 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -52,7 +52,11 @@ pub fn read_crates(sess: &Session,
     visit_crate(&e, krate);
     visit::walk_crate(&mut e, krate);
     dump_crates(&sess.cstore);
-    warn_if_multiple_versions(sess.diagnostic(), &sess.cstore)
+    warn_if_multiple_versions(sess.diagnostic(), &sess.cstore);
+
+    for &(ref name, kind) in sess.opts.libs.iter() {
+        register_native_lib(sess, None, name.clone(), kind);
+    }
 }
 
 impl<'a, 'v> visit::Visitor<'v> for Env<'a> {
@@ -233,14 +237,7 @@ fn visit_item(e: &Env, i: &ast::Item) {
                             Some(k) => {
                                 if k.equiv(&("static")) {
                                     cstore::NativeStatic
-                                } else if (e.sess.targ_cfg.os == abi::OsMacos ||
-                                           e.sess.targ_cfg.os == abi::OsiOS) &&
-                                          k.equiv(&("framework")) {
-                                    cstore::NativeFramework
                                 } else if k.equiv(&("framework")) {
-                                    e.sess.span_err(m.span,
-                                        "native frameworks are only available \
-                                         on OSX targets");
                                     cstore::NativeUnknown
                                 } else {
                                     e.sess.span_err(m.span,
@@ -263,15 +260,8 @@ fn visit_item(e: &Env, i: &ast::Item) {
                                 InternedString::new("foo")
                             }
                         };
-                        if n.get().is_empty() {
-                            e.sess.span_err(m.span,
-                                            "#[link(name = \"\")] given with \
-                                             empty name");
-                        } else {
-                            e.sess
-                             .cstore
-                             .add_used_library(n.get().to_string(), kind);
-                        }
+                        register_native_lib(e.sess, Some(m.span),
+                                            n.get().to_string(), kind);
                     }
                     None => {}
                 }
@@ -281,6 +271,32 @@ fn visit_item(e: &Env, i: &ast::Item) {
     }
 }
 
+fn register_native_lib(sess: &Session, span: Option<Span>, name: String,
+                       kind: cstore::NativeLibaryKind) {
+    if name.as_slice().is_empty() {
+        match span {
+            Some(span) => {
+                sess.span_err(span, "#[link(name = \"\")] given with \
+                                     empty name");
+            }
+            None => {
+                sess.err("empty library name given via `-l`");
+            }
+        }
+        return
+    }
+    let is_osx = sess.targ_cfg.os == abi::OsMacos ||
+                 sess.targ_cfg.os == abi::OsiOS;
+    if kind == cstore::NativeFramework && !is_osx {
+        let msg = "native frameworks are only available on OSX targets";
+        match span {
+            Some(span) => sess.span_err(span, msg),
+            None => sess.err(msg),
+        }
+    }
+    sess.cstore.add_used_library(name, kind);
+}
+
 fn existing_match(e: &Env, name: &str,
                   hash: Option<&Svh>) -> Option<ast::CrateNum> {
     let mut ret = None;
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index 1d1012d9e4f..e8c5f6f4910 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -50,7 +50,7 @@ pub enum LinkagePreference {
     RequireStatic,
 }
 
-#[deriving(PartialEq, FromPrimitive)]
+#[deriving(PartialEq, FromPrimitive, Clone)]
 pub enum NativeLibaryKind {
     NativeStatic,    // native static library (.a archive)
     NativeFramework, // OSX-specific
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index e641abbfeee..bd6df9cb497 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -675,26 +675,19 @@ pub fn check_zero_tts(cx: &ExtCtxt,
 
 /// Extract the string literal from the first token of `tts`. If this
 /// is not a string literal, emit an error and return None.
-pub fn get_single_str_from_tts(cx: &ExtCtxt,
+pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
                                sp: Span,
                                tts: &[ast::TokenTree],
                                name: &str)
                                -> Option<String> {
-    if tts.len() != 1 {
-        cx.span_err(sp, format!("{} takes 1 argument.", name).as_slice());
-    } else {
-        match tts[0] {
-            ast::TtToken(_, token::LitStr(ident)) => return Some(parse::str_lit(ident.as_str())),
-            ast::TtToken(_, token::LitStrRaw(ident, _)) => {
-                return Some(parse::raw_str_lit(ident.as_str()))
-            }
-            _ => {
-                cx.span_err(sp,
-                            format!("{} requires a string.", name).as_slice())
-            }
-        }
+    let mut p = cx.new_parser_from_tts(tts);
+    let ret = cx.expander().fold_expr(p.parse_expr());
+    if p.token != token::Eof {
+        cx.span_err(sp, format!("{} takes 1 argument", name).as_slice());
     }
-    None
+    expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| {
+        s.get().to_string()
+    })
 }
 
 /// Extract comma-separated expressions from `tts`. If there is a
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 41967b0680c..f1923084409 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -9,14 +9,16 @@
 // except according to those terms.
 
 use ast;
-use codemap;
 use codemap::{Pos, Span};
+use codemap;
 use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
-use parse;
 use parse::token;
+use parse;
 use print::pprust;
+use ptr::P;
+use util::small_vector::SmallVector;
 
 use std::io::File;
 use std::rc::Rc;
@@ -82,14 +84,14 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 /// include! : parse the given file as an expr
 /// This is generally a bad idea because it's going to behave
 /// unhygienically.
-pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                      -> Box<base::MacResult+'static> {
+pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+                           -> Box<base::MacResult+'cx> {
     let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
         Some(f) => f,
         None => return DummyResult::expr(sp),
     };
     // The file will be added to the code map by the parser
-    let mut p =
+    let p =
         parse::new_sub_parser_from_file(cx.parse_sess(),
                                         cx.cfg(),
                                         &res_rel_file(cx,
@@ -98,7 +100,28 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                                         true,
                                         None,
                                         sp);
-    base::MacExpr::new(p.parse_expr())
+
+    struct ExpandResult<'a> {
+        p: parse::parser::Parser<'a>,
+    }
+    impl<'a> base::MacResult for ExpandResult<'a> {
+        fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
+            Some(self.p.parse_expr())
+        }
+        fn make_items(mut self: Box<ExpandResult<'a>>)
+                      -> Option<SmallVector<P<ast::Item>>> {
+            let mut ret = SmallVector::zero();
+            loop {
+                match self.p.parse_item_with_outer_attributes() {
+                    Some(item) => ret.push(item),
+                    None => break
+                }
+            }
+            Some(ret)
+        }
+    }
+
+    box ExpandResult { p: p }
 }
 
 // include_str! : read the given file, insert it as a literal string expr
diff --git a/src/test/auxiliary/macro-include-items-expr.rs b/src/test/auxiliary/macro-include-items-expr.rs
new file mode 100644
index 00000000000..aea3c749930
--- /dev/null
+++ b/src/test/auxiliary/macro-include-items-expr.rs
@@ -0,0 +1,13 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// ignore-test: this is not a test
+
+1
diff --git a/src/test/auxiliary/macro-include-items-item.rs b/src/test/auxiliary/macro-include-items-item.rs
new file mode 100644
index 00000000000..da72aaef805
--- /dev/null
+++ b/src/test/auxiliary/macro-include-items-item.rs
@@ -0,0 +1,13 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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.
+
+// ignore-test: this is not a test
+
+fn foo() { bar() }
diff --git a/src/test/compile-fail/manual-link-bad-form.rs b/src/test/compile-fail/manual-link-bad-form.rs
new file mode 100644
index 00000000000..bd2a3eba0b5
--- /dev/null
+++ b/src/test/compile-fail/manual-link-bad-form.rs
@@ -0,0 +1,17 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-l :static
+// error-pattern: empty library name given via `-l`
+
+fn main() {
+}
+
+
diff --git a/src/test/compile-fail/manual-link-bad-kind.rs b/src/test/compile-fail/manual-link-bad-kind.rs
new file mode 100644
index 00000000000..4614440ddaf
--- /dev/null
+++ b/src/test/compile-fail/manual-link-bad-kind.rs
@@ -0,0 +1,16 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-l foo:bar
+// error-pattern: unknown library kind `bar`, expected one of dylib, framework, or static
+
+fn main() {
+}
+
diff --git a/src/test/compile-fail/manual-link-framework.rs b/src/test/compile-fail/manual-link-framework.rs
new file mode 100644
index 00000000000..96cc35049ee
--- /dev/null
+++ b/src/test/compile-fail/manual-link-framework.rs
@@ -0,0 +1,17 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-macos
+// ignore-ios
+// compile-flags:-l foo:framework
+// error-pattern: native frameworks are only available on OSX targets
+
+fn main() {
+}
diff --git a/src/test/run-make/manual-link/Makefile b/src/test/run-make/manual-link/Makefile
new file mode 100644
index 00000000000..d2a02adc9d4
--- /dev/null
+++ b/src/test/run-make/manual-link/Makefile
@@ -0,0 +1,7 @@
+-include ../tools.mk
+
+all: $(TMPDIR)/libbar.a
+	$(RUSTC) foo.rs -lbar:static
+	$(RUSTC) main.rs
+	$(call RUN,main)
+
diff --git a/src/test/run-make/manual-link/bar.c b/src/test/run-make/manual-link/bar.c
new file mode 100644
index 00000000000..e4259998678
--- /dev/null
+++ b/src/test/run-make/manual-link/bar.c
@@ -0,0 +1 @@
+void bar() {}
diff --git a/src/test/run-make/manual-link/foo.c b/src/test/run-make/manual-link/foo.c
new file mode 100644
index 00000000000..e4259998678
--- /dev/null
+++ b/src/test/run-make/manual-link/foo.c
@@ -0,0 +1 @@
+void bar() {}
diff --git a/src/test/run-make/manual-link/foo.rs b/src/test/run-make/manual-link/foo.rs
new file mode 100644
index 00000000000..d67a4057afb
--- /dev/null
+++ b/src/test/run-make/manual-link/foo.rs
@@ -0,0 +1,19 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+
+extern {
+    fn bar();
+}
+
+pub fn foo() {
+    unsafe { bar(); }
+}
diff --git a/src/test/run-make/manual-link/main.rs b/src/test/run-make/manual-link/main.rs
new file mode 100644
index 00000000000..756a47f386a
--- /dev/null
+++ b/src/test/run-make/manual-link/main.rs
@@ -0,0 +1,15 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate foo;
+
+fn main() {
+    foo::foo();
+}
diff --git a/src/test/run-pass/macro-include-items.rs b/src/test/run-pass/macro-include-items.rs
new file mode 100644
index 00000000000..03eec668edd
--- /dev/null
+++ b/src/test/run-pass/macro-include-items.rs
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn bar() {}
+
+include!(concat!("", "", "../auxiliary/", "macro-include-items-item.rs"))
+
+fn main() {
+    foo();
+    assert_eq!(include!(concat!("", "../auxiliary/", "macro-include-items-expr.rs")), 1u);
+}