Skip to content

Commit 8d6185b

Browse files
committed
rollup merge of rust-lang#18470 : alexcrichton/dash-l
2 parents 74ea432 + 8e6e846 commit 8d6185b

16 files changed

+234
-40
lines changed

src/librustc/driver/config.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use back::write;
2020
use back::target_strs;
2121
use back::{arm, x86, x86_64, mips, mipsel};
2222
use lint;
23+
use metadata::cstore;
2324

2425
use syntax::abi;
2526
use syntax::ast;
@@ -78,6 +79,7 @@ pub struct Options {
7879
// parsed code. It remains mutable in case its replacements wants to use
7980
// this.
8081
pub addl_lib_search_paths: RefCell<Vec<Path>>,
82+
pub libs: Vec<(String, cstore::NativeLibaryKind)>,
8183
pub maybe_sysroot: Option<Path>,
8284
pub target_triple: String,
8385
// User-specified cfg meta items. The compiler itself will add additional
@@ -130,6 +132,7 @@ pub fn basic_options() -> Options {
130132
externs: HashMap::new(),
131133
crate_name: None,
132134
alt_std_name: None,
135+
libs: Vec::new(),
133136
}
134137
}
135138

@@ -575,6 +578,10 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
575578
optflag("h", "help", "Display this message"),
576579
optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
577580
optmulti("L", "", "Add a directory to the library search path", "PATH"),
581+
optmulti("l", "", "Link the generated crate(s) to the specified native
582+
library NAME. The optional KIND can be one of,
583+
static, dylib, or framework. If omitted, dylib is
584+
assumed.", "NAME[:KIND]"),
578585
optmulti("", "crate-type", "Comma separated list of types of crates
579586
for the compiler to emit",
580587
"[bin|lib|rlib|dylib|staticlib]"),
@@ -767,6 +774,23 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
767774
Path::new(s.as_slice())
768775
}).collect();
769776

777+
let libs = matches.opt_strs("l").into_iter().map(|s| {
778+
let mut parts = s.as_slice().rsplitn(1, ':');
779+
let kind = parts.next().unwrap();
780+
let (name, kind) = match (parts.next(), kind) {
781+
(None, name) |
782+
(Some(name), "dylib") => (name, cstore::NativeUnknown),
783+
(Some(name), "framework") => (name, cstore::NativeFramework),
784+
(Some(name), "static") => (name, cstore::NativeStatic),
785+
(_, s) => {
786+
early_error(format!("unknown library kind `{}`, expected \
787+
one of dylib, framework, or static",
788+
s).as_slice());
789+
}
790+
};
791+
(name.to_string(), kind)
792+
}).collect();
793+
770794
let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
771795
let test = matches.opt_present("test");
772796
let write_dependency_info = (matches.opt_present("dep-info"),
@@ -843,7 +867,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
843867
color: color,
844868
externs: externs,
845869
crate_name: crate_name,
846-
alt_std_name: None
870+
alt_std_name: None,
871+
libs: libs,
847872
}
848873
}
849874

src/librustc/metadata/creader.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ pub fn read_crates(sess: &Session,
5252
visit_crate(&e, krate);
5353
visit::walk_crate(&mut e, krate);
5454
dump_crates(&sess.cstore);
55-
warn_if_multiple_versions(sess.diagnostic(), &sess.cstore)
55+
warn_if_multiple_versions(sess.diagnostic(), &sess.cstore);
56+
57+
for &(ref name, kind) in sess.opts.libs.iter() {
58+
register_native_lib(sess, None, name.clone(), kind);
59+
}
5660
}
5761

5862
impl<'a, 'v> visit::Visitor<'v> for Env<'a> {
@@ -233,14 +237,7 @@ fn visit_item(e: &Env, i: &ast::Item) {
233237
Some(k) => {
234238
if k.equiv(&("static")) {
235239
cstore::NativeStatic
236-
} else if (e.sess.targ_cfg.os == abi::OsMacos ||
237-
e.sess.targ_cfg.os == abi::OsiOS) &&
238-
k.equiv(&("framework")) {
239-
cstore::NativeFramework
240240
} else if k.equiv(&("framework")) {
241-
e.sess.span_err(m.span,
242-
"native frameworks are only available \
243-
on OSX targets");
244241
cstore::NativeUnknown
245242
} else {
246243
e.sess.span_err(m.span,
@@ -263,15 +260,8 @@ fn visit_item(e: &Env, i: &ast::Item) {
263260
InternedString::new("foo")
264261
}
265262
};
266-
if n.get().is_empty() {
267-
e.sess.span_err(m.span,
268-
"#[link(name = \"\")] given with \
269-
empty name");
270-
} else {
271-
e.sess
272-
.cstore
273-
.add_used_library(n.get().to_string(), kind);
274-
}
263+
register_native_lib(e.sess, Some(m.span),
264+
n.get().to_string(), kind);
275265
}
276266
None => {}
277267
}
@@ -281,6 +271,32 @@ fn visit_item(e: &Env, i: &ast::Item) {
281271
}
282272
}
283273

274+
fn register_native_lib(sess: &Session, span: Option<Span>, name: String,
275+
kind: cstore::NativeLibaryKind) {
276+
if name.as_slice().is_empty() {
277+
match span {
278+
Some(span) => {
279+
sess.span_err(span, "#[link(name = \"\")] given with \
280+
empty name");
281+
}
282+
None => {
283+
sess.err("empty library name given via `-l`");
284+
}
285+
}
286+
return
287+
}
288+
let is_osx = sess.targ_cfg.os == abi::OsMacos ||
289+
sess.targ_cfg.os == abi::OsiOS;
290+
if kind == cstore::NativeFramework && !is_osx {
291+
let msg = "native frameworks are only available on OSX targets";
292+
match span {
293+
Some(span) => sess.span_err(span, msg),
294+
None => sess.err(msg),
295+
}
296+
}
297+
sess.cstore.add_used_library(name, kind);
298+
}
299+
284300
fn existing_match(e: &Env, name: &str,
285301
hash: Option<&Svh>) -> Option<ast::CrateNum> {
286302
let mut ret = None;

src/librustc/metadata/cstore.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub enum LinkagePreference {
5050
RequireStatic,
5151
}
5252

53-
#[deriving(PartialEq, FromPrimitive)]
53+
#[deriving(PartialEq, FromPrimitive, Clone)]
5454
pub enum NativeLibaryKind {
5555
NativeStatic, // native static library (.a archive)
5656
NativeFramework, // OSX-specific

src/libsyntax/ext/base.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -675,26 +675,19 @@ pub fn check_zero_tts(cx: &ExtCtxt,
675675

676676
/// Extract the string literal from the first token of `tts`. If this
677677
/// is not a string literal, emit an error and return None.
678-
pub fn get_single_str_from_tts(cx: &ExtCtxt,
678+
pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
679679
sp: Span,
680680
tts: &[ast::TokenTree],
681681
name: &str)
682682
-> Option<String> {
683-
if tts.len() != 1 {
684-
cx.span_err(sp, format!("{} takes 1 argument.", name).as_slice());
685-
} else {
686-
match tts[0] {
687-
ast::TtToken(_, token::LitStr(ident)) => return Some(parse::str_lit(ident.as_str())),
688-
ast::TtToken(_, token::LitStrRaw(ident, _)) => {
689-
return Some(parse::raw_str_lit(ident.as_str()))
690-
}
691-
_ => {
692-
cx.span_err(sp,
693-
format!("{} requires a string.", name).as_slice())
694-
}
695-
}
683+
let mut p = cx.new_parser_from_tts(tts);
684+
let ret = cx.expander().fold_expr(p.parse_expr());
685+
if p.token != token::Eof {
686+
cx.span_err(sp, format!("{} takes 1 argument", name).as_slice());
696687
}
697-
None
688+
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| {
689+
s.get().to_string()
690+
})
698691
}
699692

700693
/// Extract comma-separated expressions from `tts`. If there is a

src/libsyntax/ext/source_util.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
// except according to those terms.
1010

1111
use ast;
12-
use codemap;
1312
use codemap::{Pos, Span};
13+
use codemap;
1414
use ext::base::*;
1515
use ext::base;
1616
use ext::build::AstBuilder;
17-
use parse;
1817
use parse::token;
18+
use parse;
1919
use print::pprust;
20+
use ptr::P;
21+
use util::small_vector::SmallVector;
2022

2123
use std::io::File;
2224
use std::rc::Rc;
@@ -82,14 +84,14 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
8284
/// include! : parse the given file as an expr
8385
/// This is generally a bad idea because it's going to behave
8486
/// unhygienically.
85-
pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
86-
-> Box<base::MacResult+'static> {
87+
pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
88+
-> Box<base::MacResult+'cx> {
8789
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
8890
Some(f) => f,
8991
None => return DummyResult::expr(sp),
9092
};
9193
// The file will be added to the code map by the parser
92-
let mut p =
94+
let p =
9395
parse::new_sub_parser_from_file(cx.parse_sess(),
9496
cx.cfg(),
9597
&res_rel_file(cx,
@@ -98,7 +100,28 @@ pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
98100
true,
99101
None,
100102
sp);
101-
base::MacExpr::new(p.parse_expr())
103+
104+
struct ExpandResult<'a> {
105+
p: parse::parser::Parser<'a>,
106+
}
107+
impl<'a> base::MacResult for ExpandResult<'a> {
108+
fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
109+
Some(self.p.parse_expr())
110+
}
111+
fn make_items(mut self: Box<ExpandResult<'a>>)
112+
-> Option<SmallVector<P<ast::Item>>> {
113+
let mut ret = SmallVector::zero();
114+
loop {
115+
match self.p.parse_item_with_outer_attributes() {
116+
Some(item) => ret.push(item),
117+
None => break
118+
}
119+
}
120+
Some(ret)
121+
}
122+
}
123+
124+
box ExpandResult { p: p }
102125
}
103126

104127
// include_str! : read the given file, insert it as a literal string expr
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-test: this is not a test
12+
13+
1
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-test: this is not a test
12+
13+
fn foo() { bar() }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags:-l :static
12+
// error-pattern: empty library name given via `-l`
13+
14+
fn main() {
15+
}
16+
17+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags:-l foo:bar
12+
// error-pattern: unknown library kind `bar`, expected one of dylib, framework, or static
13+
14+
fn main() {
15+
}
16+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-macos
12+
// ignore-ios
13+
// compile-flags:-l foo:framework
14+
// error-pattern: native frameworks are only available on OSX targets
15+
16+
fn main() {
17+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-include ../tools.mk
2+
3+
all: $(TMPDIR)/libbar.a
4+
$(RUSTC) foo.rs -lbar:static
5+
$(RUSTC) main.rs
6+
$(call RUN,main)
7+

src/test/run-make/manual-link/bar.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void bar() {}

src/test/run-make/manual-link/foo.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void bar() {}

src/test/run-make/manual-link/foo.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "rlib"]
12+
13+
extern {
14+
fn bar();
15+
}
16+
17+
pub fn foo() {
18+
unsafe { bar(); }
19+
}

src/test/run-make/manual-link/main.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate foo;
12+
13+
fn main() {
14+
foo::foo();
15+
}

0 commit comments

Comments
 (0)