diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 0358319256760..9c63e8fd72527 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -124,6 +124,7 @@ pub enum NativeLibraryKind { NativeStatic, // native static library (.a archive) NativeStaticNobundle, // native static library, which doesn't get bundled into .rlibs NativeFramework, // macOS-specific + NativeJS, // Emscripten-specific NativeUnknown, // default way to specify a dynamic library } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0bb4cd69e0cd1..e058f785be67e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1564,11 +1564,12 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) // Parse string of the form "[KIND=]lib[:new_name]", // where KIND is one of "dylib", "framework", "static". let mut parts = s.splitn(2, '='); - let kind = parts.next().unwrap(); - let (name, kind) = match (parts.next(), kind) { + let kind_name = parts.next().unwrap(); + let (name, kind) = match (parts.next(), kind_name) { (None, name) => (name, None), (Some(name), "dylib") => (name, Some(cstore::NativeUnknown)), (Some(name), "framework") => (name, Some(cstore::NativeFramework)), + (Some(name), "js") => (name, Some(cstore::NativeJS)), (Some(name), "static") => (name, Some(cstore::NativeStatic)), (Some(name), "static-nobundle") => (name, Some(cstore::NativeStaticNobundle)), (_, s) => { @@ -1577,9 +1578,13 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) s)); } }; - if kind == Some(cstore::NativeStaticNobundle) && !nightly_options::is_nightly_build() { - early_error(error_format, &format!("the library kind 'static-nobundle' is only \ - accepted on the nightly compiler")); + match kind { + Some(cstore::NativeStaticNobundle) | Some(cstore::NativeJS) + if !nightly_options::is_nightly_build() => { + early_error(error_format, &format!("the library kind '{}' is only \ + accepted on the nightly compiler", kind_name)); + } + _ => {} } let mut name_parts = name.splitn(2, ':'); let name = name_parts.next().unwrap(); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 966e814e33790..0d5ac7a36cfe8 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -105,6 +105,22 @@ fn register_native_lib(sess: &Session, None => sess.err(msg), } } + if lib.kind == cstore::NativeJS { + if !sess.target.target.options.is_like_emscripten { + let msg = "JavaScript libraries are only available on Emscripten targets"; + match span { + Some(span) => span_err!(sess, span, E0455, "{}", msg), + None => sess.err(msg), + } + } + if !sess.features.borrow().link_js { + feature_gate::emit_feature_err(&sess.parse_sess, + "link_js", + span.unwrap(), + GateIssue::Language, + "kind=\"js\" is feature gated"); + } + } if lib.cfg.is_some() && !sess.features.borrow().link_cfg { feature_gate::emit_feature_err(&sess.parse_sess, "link_cfg", @@ -1026,6 +1042,7 @@ impl<'a> CrateLoader<'a> { Some("static-nobundle") => cstore::NativeStaticNobundle, Some("dylib") => cstore::NativeUnknown, Some("framework") => cstore::NativeFramework, + Some("js") => cstore::NativeJS, Some(k) => { struct_span_err!(self.sess, m.span, E0458, "unknown kind: `{}`", k) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e42e69d2a76e2..5995e0c43c7f8 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -485,6 +485,7 @@ fn link_rlib<'a>(sess: &'a Session, NativeLibraryKind::NativeStatic => {} NativeLibraryKind::NativeStaticNobundle | NativeLibraryKind::NativeFramework | + NativeLibraryKind::NativeJS | NativeLibraryKind::NativeUnknown => continue, } ab.add_native_library(&lib.name.as_str()); @@ -683,6 +684,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) { let name = match lib.kind { NativeLibraryKind::NativeStaticNobundle | + NativeLibraryKind::NativeJS | NativeLibraryKind::NativeUnknown => "library", NativeLibraryKind::NativeFramework => "framework", // These are included, no need to print them @@ -1035,6 +1037,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { match lib.kind { NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), + NativeLibraryKind::NativeJS => cmd.link_js(&lib.name.as_str()), NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()), NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(&lib.name.as_str(), &search_path) @@ -1329,6 +1332,7 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: c } match lib.kind { NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), + NativeLibraryKind::NativeJS => cmd.link_js(&lib.name.as_str()), NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), NativeLibraryKind::NativeStaticNobundle => { // Link "static-nobundle" native libs only if the crate they originate from diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 61c57f00de70d..bb005df7a9e95 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -94,6 +94,7 @@ pub trait Linker { fn link_dylib(&mut self, lib: &str); fn link_rust_dylib(&mut self, lib: &str, path: &Path); fn link_framework(&mut self, framework: &str); + fn link_js(&mut self, lib: &str); fn link_staticlib(&mut self, lib: &str); fn link_rlib(&mut self, lib: &Path); fn link_whole_rlib(&mut self, lib: &Path); @@ -187,6 +188,10 @@ impl<'a> Linker for GccLinker<'a> { self.cmd.arg("-framework").arg(framework); } + fn link_js(&mut self, _lib: &str) { + bug!("JS libraries are not supported on macOS") + } + // Here we explicitly ask that the entire archive is included into the // result artifact. For more details see #15460, but the gist is that // the linker will strip away any unused objects in the archive if we @@ -455,10 +460,15 @@ impl<'a> Linker for MsvcLinker<'a> { fn framework_path(&mut self, _path: &Path) { bug!("frameworks are not supported on windows") } + fn link_framework(&mut self, _framework: &str) { bug!("frameworks are not supported on windows") } + fn link_js(&mut self, _lib: &str) { + bug!("JS libraries are not supported on windows") + } + fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) { // not supported? self.link_staticlib(lib); @@ -607,6 +617,10 @@ impl<'a> Linker for EmLinker<'a> { bug!("frameworks are not supported on Emscripten") } + fn link_js(&mut self, lib: &str) { + self.cmd.args(&["--js-library", lib]); + } + fn gc_sections(&mut self, _keep_metadata: bool) { // noop } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b6a2c983fd4d7..a49d8a37e23ea 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -321,6 +321,9 @@ declare_features! ( // Allows #[link(kind="static-nobundle"...] (active, static_nobundle, "1.16.0", Some(37403)), + // Allows #[link(kind="js"...)] + (active, link_js, "1.18.0", None), + // `extern "msp430-interrupt" fn()` (active, abi_msp430_interrupt, "1.16.0", Some(38487)), diff --git a/src/test/compile-fail/emscripten-libraries.rs b/src/test/compile-fail/emscripten-libraries.rs new file mode 100644 index 0000000000000..9704efca1f317 --- /dev/null +++ b/src/test/compile-fail/emscripten-libraries.rs @@ -0,0 +1,20 @@ +// Copyright 2013-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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-asmjs +// ignore-wasm32 +// ignore-wasm64 + +#[link(name = "foo", kind = "js")] +extern {} +//~^^ ERROR: JavaScript libraries are only available on Emscripten + +fn main() { +}