diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-11-30 11:39:55 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-11-30 15:47:43 -0800 |
| commit | f9d6fd20a515d677e923686f2fbf4e9f2307aab1 (patch) | |
| tree | a72a14d12c945d655d45da715cf172fb0439f62d | |
| parent | 4252a24ae1236207a99c1d313d4b1b1eda3ebb58 (diff) | |
| download | rust-f9d6fd20a515d677e923686f2fbf4e9f2307aab1.tar.gz rust-f9d6fd20a515d677e923686f2fbf4e9f2307aab1.zip | |
Support OSX frameworks
This adds support to link to OSX frameworks via the new link attribute when using `kind = "framework"`. It is a compiler error to request linkage to a framework when the target is not macos because other platforms don't support frameworks. Closes #2023
| -rw-r--r-- | src/librustc/back/link.rs | 36 | ||||
| -rw-r--r-- | src/librustc/metadata/common.rs | 2 | ||||
| -rw-r--r-- | src/librustc/metadata/creader.rs | 22 | ||||
| -rw-r--r-- | src/librustc/metadata/csearch.rs | 3 | ||||
| -rw-r--r-- | src/librustc/metadata/cstore.rs | 7 | ||||
| -rw-r--r-- | src/librustc/metadata/decoder.rs | 9 | ||||
| -rw-r--r-- | src/librustc/metadata/encoder.rs | 10 | ||||
| -rw-r--r-- | src/test/compile-fail/bad-extern-link-attrs.rs | 16 | ||||
| -rw-r--r-- | src/test/compile-fail/osx-frameworks.rs | 18 | ||||
| -rw-r--r-- | src/test/run-pass/osx-frameworks.rs | 25 |
10 files changed, 130 insertions, 18 deletions
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 8119618da57..5cf912a929f 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -1015,7 +1015,7 @@ fn link_rlib(sess: Session, obj_filename: &Path, cstore::NativeStatic => { a.add_native_library(l.as_slice()); } - cstore::NativeUnknown => {} + cstore::NativeFramework | cstore::NativeUnknown => {} } } return a; @@ -1044,8 +1044,13 @@ fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) { }; a.add_rlib(&p); let native_libs = csearch::get_native_libraries(sess.cstore, cnum); - for lib in native_libs.iter() { - sess.warn(format!("unlinked native library: {}", *lib)); + for &(kind, ref lib) in native_libs.iter() { + let name = match kind { + cstore::NativeStatic => "static library", + cstore::NativeUnknown => "library", + cstore::NativeFramework => "framework", + }; + sess.warn(format!("unlinked native {}: {}", name, *lib)); } } } @@ -1204,8 +1209,17 @@ fn add_upstream_rust_crates(args: &mut ~[~str], sess: Session, args.push(cratepath.as_str().unwrap().to_owned()); let libs = csearch::get_native_libraries(sess.cstore, cnum); - for lib in libs.iter() { - args.push("-l" + *lib); + for &(kind, ref lib) in libs.iter() { + match kind { + cstore::NativeUnknown => args.push("-l" + *lib), + cstore::NativeFramework => { + args.push(~"-framework"); + args.push(lib.to_owned()); + } + cstore::NativeStatic => { + sess.bug("statics shouldn't be propagated"); + } + } } } return; @@ -1262,7 +1276,15 @@ fn add_local_native_libraries(args: &mut ~[~str], sess: Session) { args.push("-L" + path.as_str().unwrap().to_owned()); } - for &(ref l, _) in cstore::get_used_libraries(sess.cstore).iter() { - args.push(~"-l" + *l); + for &(ref l, kind) in cstore::get_used_libraries(sess.cstore).iter() { + match kind { + cstore::NativeUnknown | cstore::NativeStatic => { + args.push("-l" + *l); + } + cstore::NativeFramework => { + args.push(~"-framework"); + args.push(l.to_owned()); + } + } } } diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 5ed1eac746c..f6eadfcc916 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -199,6 +199,8 @@ pub static tag_region_param_def_def_id: uint = 0x102; pub static tag_native_libraries: uint = 0x103; pub static tag_native_libraries_lib: uint = 0x104; +pub static tag_native_libraries_name: uint = 0x105; +pub static tag_native_libraries_kind: uint = 0x106; pub struct LinkMeta { name: @str, diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 9d28a5abed2..b425f1449f5 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -18,6 +18,7 @@ use metadata::loader; use std::hashmap::HashMap; use syntax::ast; use std::vec; +use syntax::abi; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::codemap::{Span, dummy_sp}; @@ -191,10 +192,22 @@ fn visit_item(e: &Env, i: @ast::item) { "kind" == k.name() }).and_then(|a| a.value_str()); let kind = match kind { - Some(k) if "static" == k => cstore::NativeStatic, Some(k) => { - e.sess.span_fatal(i.span, - format!("unknown kind: `{}`", k)); + if "static" == k { + cstore::NativeStatic + } else if e.sess.targ_cfg.os == abi::OsMacos && + "framework" == k { + cstore::NativeFramework + } else if "framework" == k { + e.sess.span_err(m.span, + "native frameworks are only available \ + on OSX targets"); + cstore::NativeUnknown + } else { + e.sess.span_err(m.span, + format!("unknown kind: `{}`", k)); + cstore::NativeUnknown + } } None => cstore::NativeUnknown }; @@ -204,9 +217,10 @@ fn visit_item(e: &Env, i: @ast::item) { let n = match n { Some(n) => n, None => { - e.sess.span_fatal(i.span, + e.sess.span_err(m.span, "#[link(...)] specified without \ `name = \"foo\"`"); + @"foo" } }; cstore::add_used_library(cstore, n.to_owned(), kind); diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 96250fd5ec8..c1c56e94f27 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -263,7 +263,8 @@ pub fn get_item_visibility(cstore: @mut cstore::CStore, } pub fn get_native_libraries(cstore: @mut cstore::CStore, - crate_num: ast::CrateNum) -> ~[~str] { + crate_num: ast::CrateNum) + -> ~[(cstore::NativeLibaryKind, ~str)] { let cdata = cstore::get_crate_data(cstore, crate_num); decoder::get_native_libraries(cdata) } diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 50da84d3895..c2f6443ed54 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -40,10 +40,11 @@ pub enum LinkagePreference { RequireStatic, } -#[deriving(Eq)] +#[deriving(Eq, FromPrimitive)] pub enum NativeLibaryKind { - NativeStatic, - NativeUnknown, + NativeStatic, // native static library (.a archive) + NativeFramework, // OSX-specific + NativeUnknown, // default way to specify a dynamic library } // Where a crate came from on the local filesystem. One of these two options diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 441f1620e4d..b5746cec58d 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1530,11 +1530,16 @@ pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: ty::ctxt) } -pub fn get_native_libraries(cdata: Cmd) -> ~[~str] { +pub fn get_native_libraries(cdata: Cmd) -> ~[(cstore::NativeLibaryKind, ~str)] { let libraries = reader::get_doc(reader::Doc(cdata.data), tag_native_libraries); let mut result = ~[]; reader::tagged_docs(libraries, tag_native_libraries_lib, |lib_doc| { - result.push(lib_doc.as_str()); + let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind); + let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name); + let kind: cstore::NativeLibaryKind = + FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); + let name = name_doc.as_str(); + result.push((kind, name)); true }); return result; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 269054c6fd2..ea4f4b0f3cf 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1640,10 +1640,18 @@ fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { for &(ref lib, kind) in cstore::get_used_libraries(ecx.cstore).iter() { match kind { cstore::NativeStatic => {} // these libraries are not propagated - cstore::NativeUnknown => { + cstore::NativeFramework | cstore::NativeUnknown => { ebml_w.start_tag(tag_native_libraries_lib); + + ebml_w.start_tag(tag_native_libraries_kind); + ebml_w.writer.write_be_u32(kind as u32); + ebml_w.end_tag(); + + ebml_w.start_tag(tag_native_libraries_name); ebml_w.writer.write(lib.as_bytes()); ebml_w.end_tag(); + + ebml_w.end_tag(); } } } diff --git a/src/test/compile-fail/bad-extern-link-attrs.rs b/src/test/compile-fail/bad-extern-link-attrs.rs new file mode 100644 index 00000000000..0616da26602 --- /dev/null +++ b/src/test/compile-fail/bad-extern-link-attrs.rs @@ -0,0 +1,16 @@ +// 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. + +#[link()] //~ ERROR: specified without `name = +#[link(name = "foo")] +#[link(name = "foo", kind = "bar")] //~ ERROR: unknown kind +extern {} + +fn main() {} diff --git a/src/test/compile-fail/osx-frameworks.rs b/src/test/compile-fail/osx-frameworks.rs new file mode 100644 index 00000000000..61593629656 --- /dev/null +++ b/src/test/compile-fail/osx-frameworks.rs @@ -0,0 +1,18 @@ +// 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. + +// xfail-macos this is supposed to succeed on osx + +#[link(name = "foo", kind = "framework")] +extern {} +//~^^ ERROR: native frameworks are only available on OSX + +fn main() { +} diff --git a/src/test/run-pass/osx-frameworks.rs b/src/test/run-pass/osx-frameworks.rs new file mode 100644 index 00000000000..cfb7a8e43be --- /dev/null +++ b/src/test/run-pass/osx-frameworks.rs @@ -0,0 +1,25 @@ +// 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. + +use std::libc; + +#[cfg(target_os = "macos")] +#[link(name = "CoreFoundation", kind = "framework")] +extern { + fn CFRunLoopGetTypeID() -> libc::c_ulong; +} + +#[cfg(target_os = "macos")] +fn main() { + unsafe { CFRunLoopGetTypeID(); } +} + +#[cfg(not(target_os = "macos"))] +pub fn main() {} |
