about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2016-11-11 10:00:33 +1300
committerNick Cameron <ncameron@mozilla.com>2016-11-23 12:50:39 +1300
commitaf1b19555ce636788c19dba979b57536792d90e9 (patch)
treef9059918dedbaf3e22c775e1ba96c3f8188c9115
parentbaedc3b70ff8ac14a1411b5780112eadd1d63413 (diff)
downloadrust-af1b19555ce636788c19dba979b57536792d90e9.tar.gz
rust-af1b19555ce636788c19dba979b57536792d90e9.zip
Rebasing and review changes
-rw-r--r--src/librustc/middle/cstore.rs12
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc_metadata/creader.rs3
-rw-r--r--src/librustc_metadata/cstore.rs3
-rw-r--r--src/librustc_metadata/decoder.rs3
-rw-r--r--src/librustc_metadata/locator.rs55
-rw-r--r--src/librustc_trans/back/link.rs26
-rw-r--r--src/librustc_trans/back/write.rs8
-rw-r--r--src/test/run-pass/auxiliary/rmeta_rlib.rs18
-rw-r--r--src/test/run-pass/auxiliary/rmeta_rmeta.rs18
-rw-r--r--src/test/run-pass/rmeta.rs22
11 files changed, 126 insertions, 44 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 1468e94459e..653f9852e66 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -65,6 +65,18 @@ pub struct CrateSource {
     pub rmeta: Option<(PathBuf, PathKind)>,
 }
 
+#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
+pub enum DepKind {
+    /// A dependency that is only used for its macros.
+    MacrosOnly,
+    /// A dependency that is always injected into the dependency list and so
+    /// doesn't need to be linked to an rlib, e.g. the injected allocator.
+    Implicit,
+    /// A dependency that is required by an rlib version of this crate.
+    /// Ordinary `extern crate`s result in `Explicit` dependencies.
+    Explicit,
+}
+
 #[derive(PartialEq, Clone, Debug)]
 pub enum LibSource {
     Some(PathBuf),
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 4a073288273..3dc533d61f0 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1634,7 +1634,7 @@ impl fmt::Display for CrateType {
             CrateTypeStaticlib => "staticlib".fmt(f),
             CrateTypeCdylib => "cdylib".fmt(f),
             CrateTypeProcMacro => "proc-macro".fmt(f),
-            CrateTypeMetadata => "rmeta".fmt(f),
+            CrateTypeMetadata => "metadata".fmt(f),
         }
     }
 }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 693b04ae661..12a70da636d 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -67,8 +67,7 @@ fn dump_crates(cstore: &CStore) {
         dylib.map(|dl| info!("  dylib: {}", dl.0.display()));
         rlib.map(|rl|  info!("   rlib: {}", rl.0.display()));
         rmeta.map(|rl| info!("   rmeta: {}", rl.0.display()));
-        });
-    })
+    });
 }
 
 #[derive(Debug)]
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index e5f7964d7eb..c2ed7ca7ce0 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -43,6 +43,7 @@ pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
 pub enum MetadataBlob {
     Inflated(Bytes),
     Archive(locator::ArchiveMetadata),
+    Raw(Vec<u8>),
 }
 
 /// Holds information about a syntax_pos::FileMap imported from another crate.
@@ -203,7 +204,7 @@ impl CStore {
                 let path = match path {
                     Some(p) => LibSource::Some(p),
                     None => {
-                        if data.rmeta.is_some() {
+                        if data.source.rmeta.is_some() {
                             LibSource::MetadataOnly
                         } else {
                             LibSource::None
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 3af9d291ae5..3ba899f41d8 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -88,8 +88,9 @@ pub trait Metadata<'a, 'tcx>: Copy {
 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
     fn raw_bytes(self) -> &'a [u8] {
         match *self {
-            MetadataBlob::Inflated(ref vec) => &vec[..],
+            MetadataBlob::Inflated(ref vec) => vec,
             MetadataBlob::Archive(ref ar) => ar.as_slice(),
+            MetadataBlob::Raw(ref vec) => vec,
         }
     }
 }
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 6cdd8b46464..2b06851cb8b 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -53,8 +53,8 @@
 //! is a platform-defined dynamic library. Each library has a metadata somewhere
 //! inside of it.
 //!
-//! A third kind of dependency is an rmeta file. These are rlibs, which contain
-//! metadata, but no code. To a first approximation, these are treated in the
+//! A third kind of dependency is an rmeta file. These are metadata files and do
+//! not contain any code, etc. To a first approximation, these are treated in the
 //! same way as rlibs. Where there is both an rlib and an rmeta file, the rlib
 //! gets priority (even if the rmeta file is newer). An rmeta file is only
 //! useful for checking a downstream crate, attempting to link one will cause an
@@ -239,8 +239,8 @@ use rustc_back::target::Target;
 
 use std::cmp;
 use std::fmt;
-use std::fs;
-use std::io;
+use std::fs::{self, File};
+use std::io::{self, Read};
 use std::path::{Path, PathBuf};
 use std::ptr;
 use std::slice;
@@ -462,22 +462,23 @@ impl<'a> Context<'a> {
                 None => return FileDoesntMatch,
                 Some(file) => file,
             };
-            let (hash, found_kind) = if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
-                (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
-            } else if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rmeta") {
-                (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
-            } else if file.starts_with(&dylib_prefix) &&
-                                         file.ends_with(&dypair.1) {
-                (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib)
-            } else {
-                if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) {
-                    staticlibs.push(CrateMismatch {
-                        path: path.to_path_buf(),
-                        got: "static".to_string(),
-                    });
-                }
-                return FileDoesntMatch;
-            };
+            let (hash, found_kind) =
+                if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
+                    (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
+                } else if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rmeta") {
+                    (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
+                } else if file.starts_with(&dylib_prefix) &&
+                                             file.ends_with(&dypair.1) {
+                    (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib)
+                } else {
+                    if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) {
+                        staticlibs.push(CrateMismatch {
+                            path: path.to_path_buf(),
+                            got: "static".to_string(),
+                        });
+                    }
+                    return FileDoesntMatch;
+                };
             info!("lib candidate: {}", path.display());
 
             let hash_str = hash.to_string();
@@ -731,7 +732,8 @@ impl<'a> Context<'a> {
                         return false;
                     }
                 };
-                if file.starts_with("lib") && file.ends_with(".rlib") {
+                if file.starts_with("lib") &&
+                   (file.ends_with(".rlib") || file.ends_with(".rmeta")) {
                     return true;
                 } else {
                     let (ref prefix, ref suffix) = dylibname;
@@ -846,7 +848,7 @@ fn get_metadata_section_imp(target: &Target,
     if !filename.exists() {
         return Err(format!("no such file: '{}'", filename.display()));
     }
-    if flavor == CrateFlavor::Rlib || flavor == CrateFlavor::Rmeta {
+    if flavor == CrateFlavor::Rlib {
         // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
         // internally to read the file. We also avoid even using a memcpy by
         // just keeping the archive along while the metadata is in use.
@@ -864,6 +866,15 @@ fn get_metadata_section_imp(target: &Target,
                 Ok(blob)
             }
         };
+    } else if flavor == CrateFlavor::Rmeta {
+        let mut file = File::open(filename).map_err(|_|
+            format!("could not open file: '{}'", filename.display()))?;
+        let mut buf = vec![];
+        file.read_to_end(&mut buf).map_err(|_|
+            format!("failed to read rlib metadata: '{}'", filename.display()))?;
+        let blob = MetadataBlob::Raw(buf);
+        verify_decompressed_encoding_version(&blob, filename)?;
+        return Ok(blob);
     }
     unsafe {
         let buf = common::path2cstr(filename);
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 7938ddde4ce..40c2de7b889 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -190,7 +190,6 @@ pub fn link_binary(sess: &Session,
     let mut out_filenames = Vec::new();
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-trans, as they will error.
-        // TODO do we need to check for CrateTypeMetadata here?
         if sess.opts.debugging_opts.no_trans &&
            crate_type == config::CrateTypeExecutable {
             continue;
@@ -312,7 +311,8 @@ pub fn each_linked_rlib(sess: &Session,
         let path = match path {
             LibSource::Some(p) => p,
             LibSource::MetadataOnly => {
-                sess.fatal(&format!("could not find rlib for: `{}`, found rmeta (metadata) file", name));
+                sess.fatal(&format!("could not find rlib for: `{}`, found rmeta (metadata) file",
+                                    name));
             }
             LibSource::None => {
                 sess.fatal(&format!("could not find rlib for: `{}`", name));
@@ -351,13 +351,16 @@ fn link_binary_output(sess: &Session,
     };
 
     match crate_type {
-        config::CrateTypeRlib | config::CrateTypeMetadata => {
+        config::CrateTypeRlib => {
             link_rlib(sess, Some(trans), &objects, &out_filename,
                       tmpdir.path()).build();
         }
         config::CrateTypeStaticlib => {
             link_staticlib(sess, &objects, &out_filename, tmpdir.path());
         }
+        config::CrateTypeMetadata => {
+            emit_metadata(sess, trans, &out_filename);
+        }
         _ => {
             link_natively(sess, crate_type, &objects, &out_filename, trans,
                           outputs, tmpdir.path());
@@ -396,6 +399,13 @@ fn archive_config<'a>(sess: &'a Session,
     }
 }
 
+fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: &Path) {
+    let result = fs::File::create(out_filename).and_then(|mut f| f.write_all(&trans.metadata));
+    if let Err(e) = result {
+        sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+    }
+}
+
 // Create an 'rlib'
 //
 // An rlib in its current incarnation is essentially a renamed .a file. The
@@ -471,15 +481,7 @@ fn link_rlib<'a>(sess: &'a Session,
             // here so concurrent builds in the same directory don't try to use
             // the same filename for metadata (stomping over one another)
             let metadata = tmpdir.join(sess.cstore.metadata_filename());
-            match fs::File::create(&metadata).and_then(|mut f| {
-                f.write_all(&trans.metadata)
-            }) {
-                Ok(..) => {}
-                Err(e) => {
-                    sess.fatal(&format!("failed to write {}: {}",
-                                        metadata.display(), e));
-                }
-            }
+            emit_metadata(sess, trans, &metadata);
             ab.add_file(&metadata);
 
             // For LTO purposes, the bytecode of this library is also inserted
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 29e3efb3b3a..01eea08c50b 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -691,12 +691,10 @@ pub fn run_passes(sess: &Session,
     // Whenever an rlib is created, the bitcode is inserted into the
     // archive in order to allow LTO against it.
     let needs_crate_bitcode =
-            (sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
-             sess.opts.output_types.contains_key(&OutputType::Exe)) ||
-            sess.crate_types.borrow().contains(&config::CrateTypeMetadata);
+            sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
+            sess.opts.output_types.contains_key(&OutputType::Exe);
     let needs_crate_object =
-            sess.opts.output_types.contains_key(&OutputType::Exe) ||
-            sess.crate_types.borrow().contains(&config::CrateTypeMetadata);
+            sess.opts.output_types.contains_key(&OutputType::Exe);
     if needs_crate_bitcode {
         modules_config.emit_bc = true;
     }
diff --git a/src/test/run-pass/auxiliary/rmeta_rlib.rs b/src/test/run-pass/auxiliary/rmeta_rlib.rs
new file mode 100644
index 00000000000..28c11315fa1
--- /dev/null
+++ b/src/test/run-pass/auxiliary/rmeta_rlib.rs
@@ -0,0 +1,18 @@
+// Copyright 2016 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.
+
+// no-prefer-dynamic
+
+#![crate_type="rlib"]
+#![crate_name="rmeta_aux"]
+
+pub struct Foo {
+    pub field: i32,
+}
diff --git a/src/test/run-pass/auxiliary/rmeta_rmeta.rs b/src/test/run-pass/auxiliary/rmeta_rmeta.rs
new file mode 100644
index 00000000000..394845b66f3
--- /dev/null
+++ b/src/test/run-pass/auxiliary/rmeta_rmeta.rs
@@ -0,0 +1,18 @@
+// Copyright 2016 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.
+
+// no-prefer-dynamic
+
+#![crate_type="metadata"]
+#![crate_name="rmeta_aux"]
+
+pub struct Foo {
+    pub field2: i32,
+}
diff --git a/src/test/run-pass/rmeta.rs b/src/test/run-pass/rmeta.rs
new file mode 100644
index 00000000000..11684d8663a
--- /dev/null
+++ b/src/test/run-pass/rmeta.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 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.
+
+// Test that using rlibs and rmeta dep crates work together. Specifically, that
+// there can be both an rmeta and an rlib file and rustc will prefer the rlib.
+
+// aux-build:rmeta_rmeta.rs
+// aux-build:rmeta_rlib.rs
+
+extern crate rmeta_aux;
+use rmeta_aux::Foo;
+
+pub fn main() {
+    let _ = Foo { field: 42 };
+}