2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 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.
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Finds crate binaries and loads their metadata
|
2012-05-15 22:23:06 -05:00
|
|
|
|
2013-12-16 22:58:21 -06:00
|
|
|
use back::archive::{ArchiveRO, METADATA_FILENAME};
|
2014-02-24 21:45:20 -06:00
|
|
|
use back::svh::Svh;
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
use driver::session::Session;
|
|
|
|
use lib::llvm::{False, llvm, ObjectFile, mk_section_iter};
|
2013-12-16 22:58:21 -06:00
|
|
|
use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
|
2012-12-23 16:41:37 -06:00
|
|
|
use metadata::decoder;
|
|
|
|
use metadata::encoder;
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
use metadata::filesearch::{FileMatches, FileDoesntMatch};
|
2013-08-31 11:13:04 -05:00
|
|
|
use syntax::codemap::Span;
|
2013-12-31 08:17:59 -06:00
|
|
|
use syntax::diagnostic::SpanHandler;
|
2014-01-09 07:05:33 -06:00
|
|
|
use syntax::parse::token::IdentInterner;
|
2013-12-28 11:16:48 -06:00
|
|
|
use syntax::crateid::CrateId;
|
2013-07-19 06:51:37 -05:00
|
|
|
use syntax::attr::AttrMetaMethods;
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2013-08-03 19:13:14 -05:00
|
|
|
use std::c_str::ToCStr;
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::cast;
|
2014-02-06 01:34:33 -06:00
|
|
|
use std::cmp;
|
2013-11-11 00:46:32 -06:00
|
|
|
use std::io;
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::os::consts::{macos, freebsd, linux, android, win32};
|
2014-04-03 12:45:36 -05:00
|
|
|
use std::ptr;
|
2014-03-27 12:28:38 -05:00
|
|
|
use std::rc::Rc;
|
2014-03-08 17:11:52 -06:00
|
|
|
use std::slice;
|
2014-04-03 12:45:36 -05:00
|
|
|
use std::str;
|
2014-02-19 21:08:12 -06:00
|
|
|
|
2014-02-19 21:29:58 -06:00
|
|
|
use collections::{HashMap, HashSet};
|
2014-01-24 23:00:31 -06:00
|
|
|
use flate;
|
2014-02-19 21:08:12 -06:00
|
|
|
use time;
|
2012-05-15 22:23:06 -05:00
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
pub enum Os {
|
|
|
|
OsMacos,
|
|
|
|
OsWin32,
|
|
|
|
OsLinux,
|
|
|
|
OsAndroid,
|
|
|
|
OsFreebsd
|
2012-05-22 19:16:26 -05:00
|
|
|
}
|
2012-05-15 22:23:06 -05:00
|
|
|
|
2014-04-04 20:49:03 -05:00
|
|
|
pub struct HashMismatch {
|
2014-04-03 10:43:57 -05:00
|
|
|
path: Path,
|
|
|
|
}
|
|
|
|
|
2014-02-24 20:13:51 -06:00
|
|
|
pub struct Context<'a> {
|
2014-03-28 12:05:27 -05:00
|
|
|
pub sess: &'a Session,
|
|
|
|
pub span: Span,
|
|
|
|
pub ident: &'a str,
|
|
|
|
pub crate_id: &'a CrateId,
|
|
|
|
pub id_hash: &'a str,
|
|
|
|
pub hash: Option<&'a Svh>,
|
|
|
|
pub os: Os,
|
|
|
|
pub intr: Rc<IdentInterner>,
|
2014-04-04 20:49:03 -05:00
|
|
|
pub rejected_via_hash: Vec<HashMismatch>
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
2012-05-22 19:16:26 -05:00
|
|
|
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
pub struct Library {
|
2014-03-28 12:05:27 -05:00
|
|
|
pub dylib: Option<Path>,
|
|
|
|
pub rlib: Option<Path>,
|
|
|
|
pub metadata: MetadataBlob,
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
|
|
|
|
2013-12-16 22:58:21 -06:00
|
|
|
pub struct ArchiveMetadata {
|
2014-03-28 12:05:27 -05:00
|
|
|
archive: ArchiveRO,
|
2013-12-16 22:58:21 -06:00
|
|
|
// See comments in ArchiveMetadata::new for why this is static
|
2014-03-28 12:05:27 -05:00
|
|
|
data: &'static [u8],
|
2013-12-16 22:58:21 -06:00
|
|
|
}
|
|
|
|
|
2014-04-03 10:43:57 -05:00
|
|
|
pub struct CratePaths {
|
|
|
|
pub ident: ~str,
|
|
|
|
pub dylib: Option<Path>,
|
|
|
|
pub rlib: Option<Path>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CratePaths {
|
2014-04-04 20:49:03 -05:00
|
|
|
fn paths(&self) -> Vec<Path> {
|
2014-04-03 10:43:57 -05:00
|
|
|
match (&self.dylib, &self.rlib) {
|
2014-04-04 20:49:03 -05:00
|
|
|
(&None, &None) => vec!(),
|
|
|
|
(&Some(ref p), &None) |
|
|
|
|
(&None, &Some(ref p)) => vec!(p.clone()),
|
|
|
|
(&Some(ref p1), &Some(ref p2)) => vec!(p1.clone(), p2.clone()),
|
2014-04-03 10:43:57 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-22 12:45:44 -06:00
|
|
|
// FIXME(#11857) this should be a "real" realpath
|
|
|
|
fn realpath(p: &Path) -> Path {
|
|
|
|
use std::os;
|
|
|
|
use std::io::fs;
|
|
|
|
|
|
|
|
let path = os::make_absolute(p);
|
|
|
|
match fs::readlink(&path) {
|
|
|
|
Ok(p) => p,
|
|
|
|
Err(..) => path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-24 20:13:51 -06:00
|
|
|
impl<'a> Context<'a> {
|
2014-04-03 10:43:57 -05:00
|
|
|
pub fn load_library_crate(&mut self, root: &Option<CratePaths>) -> Library {
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
match self.find_library_crate() {
|
|
|
|
Some(t) => t,
|
|
|
|
None => {
|
2014-02-10 14:50:53 -06:00
|
|
|
self.sess.abort_if_errors();
|
2014-04-04 20:49:03 -05:00
|
|
|
let message = if self.rejected_via_hash.len() > 0 {
|
2014-02-24 21:45:20 -06:00
|
|
|
format!("found possibly newer version of crate `{}`",
|
|
|
|
self.ident)
|
|
|
|
} else {
|
|
|
|
format!("can't find crate for `{}`", self.ident)
|
|
|
|
};
|
2014-04-03 10:43:57 -05:00
|
|
|
let message = match root {
|
|
|
|
&None => message,
|
|
|
|
&Some(ref r) => format!("{} which `{}` depends on",
|
|
|
|
message, r.ident)
|
2014-02-09 21:29:21 -06:00
|
|
|
};
|
2014-02-24 21:45:20 -06:00
|
|
|
self.sess.span_err(self.span, message);
|
|
|
|
|
2014-04-04 20:49:03 -05:00
|
|
|
if self.rejected_via_hash.len() > 0 {
|
2014-02-24 21:45:20 -06:00
|
|
|
self.sess.span_note(self.span, "perhaps this crate needs \
|
|
|
|
to be recompiled?");
|
2014-04-04 20:49:03 -05:00
|
|
|
let mismatches = self.rejected_via_hash.iter();
|
|
|
|
for (i, &HashMismatch{ ref path }) in mismatches.enumerate() {
|
|
|
|
self.sess.fileline_note(self.span,
|
|
|
|
format!("crate `{}` path \\#{}: {}",
|
|
|
|
self.ident, i+1, path.display()));
|
|
|
|
}
|
|
|
|
match root {
|
|
|
|
&None => {}
|
|
|
|
&Some(ref r) => {
|
|
|
|
for (i, path) in r.paths().iter().enumerate() {
|
|
|
|
self.sess.fileline_note(self.span,
|
|
|
|
format!("crate `{}` path \\#{}: {}",
|
|
|
|
r.ident, i+1, path.display()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-02-24 21:45:20 -06:00
|
|
|
}
|
|
|
|
self.sess.abort_if_errors();
|
|
|
|
unreachable!()
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-15 22:23:06 -05:00
|
|
|
|
2014-02-24 21:45:20 -06:00
|
|
|
fn find_library_crate(&mut self) -> Option<Library> {
|
2014-03-09 07:24:58 -05:00
|
|
|
let filesearch = self.sess.filesearch();
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
let (dyprefix, dysuffix) = self.dylibname();
|
2013-02-19 01:40:42 -06:00
|
|
|
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
|
2014-02-24 20:13:51 -06:00
|
|
|
let dylib_prefix = format!("{}{}-", dyprefix, self.crate_id.name);
|
|
|
|
let rlib_prefix = format!("lib{}-", self.crate_id.name);
|
2012-05-15 22:23:06 -05:00
|
|
|
|
2014-02-10 14:50:53 -06:00
|
|
|
let mut candidates = HashMap::new();
|
2012-05-15 22:23:06 -05:00
|
|
|
|
2014-02-10 14:50:53 -06:00
|
|
|
// First, find all possible candidate rlibs and dylibs purely based on
|
|
|
|
// the name of the files themselves. We're trying to match against an
|
|
|
|
// exact crate_id and a possibly an exact hash.
|
|
|
|
//
|
|
|
|
// During this step, we can filter all found libraries based on the
|
|
|
|
// name and id found in the crate id (we ignore the path portion for
|
|
|
|
// filename matching), as well as the exact hash (if specified). If we
|
|
|
|
// end up having many candidates, we must look at the metadata to
|
|
|
|
// perform exact matches against hashes/crate ids. Note that opening up
|
|
|
|
// the metadata is where we do an exact match against the full contents
|
|
|
|
// of the crate id (path/name/id).
|
|
|
|
//
|
|
|
|
// The goal of this step is to look at as little metadata as possible.
|
|
|
|
filesearch.search(|path| {
|
|
|
|
let file = match path.filename_str() {
|
|
|
|
None => return FileDoesntMatch,
|
|
|
|
Some(file) => file,
|
|
|
|
};
|
|
|
|
if file.starts_with(rlib_prefix) && file.ends_with(".rlib") {
|
|
|
|
info!("rlib candidate: {}", path.display());
|
|
|
|
match self.try_match(file, rlib_prefix, ".rlib") {
|
|
|
|
Some(hash) => {
|
|
|
|
info!("rlib accepted, hash: {}", hash);
|
|
|
|
let slot = candidates.find_or_insert_with(hash, |_| {
|
|
|
|
(HashSet::new(), HashSet::new())
|
|
|
|
});
|
|
|
|
let (ref mut rlibs, _) = *slot;
|
2014-02-22 12:45:44 -06:00
|
|
|
rlibs.insert(realpath(path));
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
FileMatches
|
2014-02-10 14:50:53 -06:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
info!("rlib rejected");
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
FileDoesntMatch
|
|
|
|
}
|
2013-06-24 14:38:14 -05:00
|
|
|
}
|
2014-02-10 14:50:53 -06:00
|
|
|
} else if file.starts_with(dylib_prefix) && file.ends_with(dysuffix){
|
|
|
|
info!("dylib candidate: {}", path.display());
|
|
|
|
match self.try_match(file, dylib_prefix, dysuffix) {
|
|
|
|
Some(hash) => {
|
|
|
|
info!("dylib accepted, hash: {}", hash);
|
|
|
|
let slot = candidates.find_or_insert_with(hash, |_| {
|
|
|
|
(HashSet::new(), HashSet::new())
|
|
|
|
});
|
|
|
|
let (_, ref mut dylibs) = *slot;
|
2014-02-22 12:45:44 -06:00
|
|
|
dylibs.insert(realpath(path));
|
2014-02-10 14:50:53 -06:00
|
|
|
FileMatches
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
info!("dylib rejected");
|
|
|
|
FileDoesntMatch
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FileDoesntMatch
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
2013-11-28 20:03:38 -06:00
|
|
|
});
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
|
2014-02-10 14:50:53 -06:00
|
|
|
// We have now collected all known libraries into a set of candidates
|
|
|
|
// keyed of the filename hash listed. For each filename, we also have a
|
|
|
|
// list of rlibs/dylibs that apply. Here, we map each of these lists
|
|
|
|
// (per hash), to a Library candidate for returning.
|
|
|
|
//
|
|
|
|
// A Library candidate is created if the metadata for the set of
|
|
|
|
// libraries corresponds to the crate id and hash criteria that this
|
2014-04-20 23:49:39 -05:00
|
|
|
// search is being performed for.
|
2014-03-04 12:02:49 -06:00
|
|
|
let mut libraries = Vec::new();
|
2014-02-10 14:50:53 -06:00
|
|
|
for (_hash, (rlibs, dylibs)) in candidates.move_iter() {
|
|
|
|
let mut metadata = None;
|
|
|
|
let rlib = self.extract_one(rlibs, "rlib", &mut metadata);
|
|
|
|
let dylib = self.extract_one(dylibs, "dylib", &mut metadata);
|
|
|
|
match metadata {
|
|
|
|
Some(metadata) => {
|
|
|
|
libraries.push(Library {
|
|
|
|
dylib: dylib,
|
|
|
|
rlib: rlib,
|
|
|
|
metadata: metadata,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Having now translated all relevant found hashes into libraries, see
|
|
|
|
// what we've got and figure out if we found multiple candidates for
|
|
|
|
// libraries or not.
|
|
|
|
match libraries.len() {
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
0 => None,
|
2014-03-08 14:36:22 -06:00
|
|
|
1 => Some(libraries.move_iter().next().unwrap()),
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
_ => {
|
|
|
|
self.sess.span_err(self.span,
|
2014-02-24 20:13:51 -06:00
|
|
|
format!("multiple matching crates for `{}`",
|
|
|
|
self.crate_id.name));
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
self.sess.note("candidates:");
|
2014-02-10 14:50:53 -06:00
|
|
|
for lib in libraries.iter() {
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
match lib.dylib {
|
|
|
|
Some(ref p) => {
|
|
|
|
self.sess.note(format!("path: {}", p.display()));
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
match lib.rlib {
|
|
|
|
Some(ref p) => {
|
|
|
|
self.sess.note(format!("path: {}", p.display()));
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
2013-12-18 16:10:28 -06:00
|
|
|
let data = lib.metadata.as_slice();
|
2014-02-24 21:45:20 -06:00
|
|
|
let crate_id = decoder::get_crate_id(data);
|
|
|
|
note_crateid_attr(self.sess.diagnostic(), &crate_id);
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
2013-06-24 14:38:14 -05:00
|
|
|
None
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-10 14:50:53 -06:00
|
|
|
// Attempts to match the requested version of a library against the file
|
|
|
|
// specified. The prefix/suffix are specified (disambiguates between
|
|
|
|
// rlib/dylib).
|
|
|
|
//
|
|
|
|
// The return value is `None` if `file` doesn't look like a rust-generated
|
2014-04-20 23:49:39 -05:00
|
|
|
// library, or if a specific version was requested and it doesn't match the
|
2014-02-10 14:50:53 -06:00
|
|
|
// apparent file's version.
|
|
|
|
//
|
|
|
|
// If everything checks out, then `Some(hash)` is returned where `hash` is
|
|
|
|
// the listed hash in the filename itself.
|
|
|
|
fn try_match(&self, file: &str, prefix: &str, suffix: &str) -> Option<~str>{
|
|
|
|
let middle = file.slice(prefix.len(), file.len() - suffix.len());
|
|
|
|
debug!("matching -- {}, middle: {}", file, middle);
|
|
|
|
let mut parts = middle.splitn('-', 1);
|
|
|
|
let hash = match parts.next() { Some(h) => h, None => return None };
|
2014-02-24 21:45:20 -06:00
|
|
|
debug!("matching -- {}, hash: {} (want {})", file, hash, self.id_hash);
|
2014-02-10 14:50:53 -06:00
|
|
|
let vers = match parts.next() { Some(v) => v, None => return None };
|
2014-02-24 21:45:20 -06:00
|
|
|
debug!("matching -- {}, vers: {} (want {})", file, vers,
|
|
|
|
self.crate_id.version);
|
2014-02-24 20:13:51 -06:00
|
|
|
match self.crate_id.version {
|
|
|
|
Some(ref version) if version.as_slice() != vers => return None,
|
2014-02-24 21:45:20 -06:00
|
|
|
Some(..) => {} // check the hash
|
|
|
|
|
|
|
|
// hash is irrelevant, no version specified
|
|
|
|
None => return Some(hash.to_owned())
|
2014-02-10 14:50:53 -06:00
|
|
|
}
|
2014-02-24 21:45:20 -06:00
|
|
|
debug!("matching -- {}, vers ok", file);
|
2014-02-10 14:50:53 -06:00
|
|
|
// hashes in filenames are prefixes of the "true hash"
|
2014-02-24 21:45:20 -06:00
|
|
|
if self.id_hash == hash.as_slice() {
|
|
|
|
debug!("matching -- {}, hash ok", file);
|
2014-02-10 14:50:53 -06:00
|
|
|
Some(hash.to_owned())
|
|
|
|
} else {
|
|
|
|
None
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-10 14:50:53 -06:00
|
|
|
// Attempts to extract *one* library from the set `m`. If the set has no
|
|
|
|
// elements, `None` is returned. If the set has more than one element, then
|
|
|
|
// the errors and notes are emitted about the set of libraries.
|
|
|
|
//
|
|
|
|
// With only one library in the set, this function will extract it, and then
|
|
|
|
// read the metadata from it if `*slot` is `None`. If the metadata couldn't
|
|
|
|
// be read, it is assumed that the file isn't a valid rust library (no
|
|
|
|
// errors are emitted).
|
2014-02-24 21:45:20 -06:00
|
|
|
fn extract_one(&mut self, m: HashSet<Path>, flavor: &str,
|
2014-02-10 14:50:53 -06:00
|
|
|
slot: &mut Option<MetadataBlob>) -> Option<Path> {
|
2014-03-19 10:47:59 -05:00
|
|
|
let mut ret = None::<Path>;
|
|
|
|
let mut error = 0;
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
|
2014-04-07 15:13:21 -05:00
|
|
|
if slot.is_some() {
|
|
|
|
// FIXME(#10786): for an optimization, we only read one of the
|
|
|
|
// library's metadata sections. In theory we should
|
|
|
|
// read both, but reading dylib metadata is quite
|
|
|
|
// slow.
|
|
|
|
if m.len() == 0 {
|
|
|
|
return None
|
|
|
|
} else if m.len() == 1 {
|
|
|
|
return Some(m.move_iter().next().unwrap())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-19 10:47:59 -05:00
|
|
|
for lib in m.move_iter() {
|
2014-03-07 16:37:18 -06:00
|
|
|
info!("{} reading metadata from: {}", flavor, lib.display());
|
2014-03-19 10:47:59 -05:00
|
|
|
let metadata = match get_metadata_section(self.os, &lib) {
|
2014-03-07 16:37:18 -06:00
|
|
|
Ok(blob) => {
|
2014-04-03 10:43:57 -05:00
|
|
|
if self.crate_matches(blob.as_slice(), &lib) {
|
2014-03-19 10:47:59 -05:00
|
|
|
blob
|
2014-02-10 14:50:53 -06:00
|
|
|
} else {
|
|
|
|
info!("metadata mismatch");
|
2014-03-19 10:47:59 -05:00
|
|
|
continue
|
2014-02-10 14:50:53 -06:00
|
|
|
}
|
|
|
|
}
|
2014-03-07 16:37:18 -06:00
|
|
|
Err(_) => {
|
2014-02-10 14:50:53 -06:00
|
|
|
info!("no metadata found");
|
2014-03-19 10:47:59 -05:00
|
|
|
continue
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
2014-03-19 10:47:59 -05:00
|
|
|
};
|
|
|
|
if ret.is_some() {
|
|
|
|
self.sess.span_err(self.span,
|
|
|
|
format!("multiple {} candidates for `{}` \
|
|
|
|
found", flavor, self.crate_id.name));
|
|
|
|
self.sess.span_note(self.span,
|
|
|
|
format!(r"candidate \#1: {}",
|
|
|
|
ret.get_ref().display()));
|
|
|
|
error = 1;
|
|
|
|
ret = None;
|
|
|
|
}
|
|
|
|
if error > 0 {
|
|
|
|
error += 1;
|
|
|
|
self.sess.span_note(self.span,
|
|
|
|
format!(r"candidate \#{}: {}", error,
|
|
|
|
lib.display()));
|
|
|
|
continue
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
2014-03-19 10:47:59 -05:00
|
|
|
*slot = Some(metadata);
|
|
|
|
ret = Some(lib);
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
2014-03-19 10:47:59 -05:00
|
|
|
return if error > 0 {None} else {ret}
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
}
|
|
|
|
|
2014-04-03 10:43:57 -05:00
|
|
|
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
|
2014-03-01 13:09:30 -06:00
|
|
|
match decoder::maybe_get_crate_id(crate_data) {
|
|
|
|
Some(ref id) if self.crate_id.matches(id) => {}
|
|
|
|
_ => return false
|
|
|
|
}
|
|
|
|
let hash = match decoder::maybe_get_crate_hash(crate_data) {
|
|
|
|
Some(hash) => hash, None => return false
|
|
|
|
};
|
2014-02-24 21:45:20 -06:00
|
|
|
match self.hash {
|
|
|
|
None => true,
|
2014-03-01 13:09:30 -06:00
|
|
|
Some(myhash) => {
|
|
|
|
if *myhash != hash {
|
2014-04-04 20:49:03 -05:00
|
|
|
self.rejected_via_hash.push(HashMismatch{ path: libpath.clone() });
|
2014-02-24 21:45:20 -06:00
|
|
|
false
|
|
|
|
} else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
// Returns the corresponding (prefix, suffix) that files need to have for
|
|
|
|
// dynamic libraries
|
|
|
|
fn dylibname(&self) -> (&'static str, &'static str) {
|
|
|
|
match self.os {
|
|
|
|
OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
|
|
|
|
OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
|
|
|
|
OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
|
|
|
|
OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
|
|
|
|
OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
2013-07-31 15:47:32 -05:00
|
|
|
}
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
|
|
|
|
2014-03-16 13:56:24 -05:00
|
|
|
pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
|
2013-12-28 11:16:48 -06:00
|
|
|
diag.handler().note(format!("crate_id: {}", crateid.to_str()));
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
|
|
|
|
2013-12-16 22:58:21 -06:00
|
|
|
impl ArchiveMetadata {
|
|
|
|
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
|
|
|
|
let data: &'static [u8] = {
|
|
|
|
let data = match ar.read(METADATA_FILENAME) {
|
|
|
|
Some(data) => data,
|
|
|
|
None => {
|
|
|
|
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// This data is actually a pointer inside of the archive itself, but
|
|
|
|
// we essentially want to cache it because the lookup inside the
|
|
|
|
// archive is a fairly expensive operation (and it's queried for
|
|
|
|
// *very* frequently). For this reason, we transmute it to the
|
|
|
|
// static lifetime to put into the struct. Note that the buffer is
|
|
|
|
// never actually handed out with a static lifetime, but rather the
|
|
|
|
// buffer is loaned with the lifetime of this containing object.
|
|
|
|
// Hence, we're guaranteed that the buffer will never be used after
|
|
|
|
// this object is dead, so this is a safe operation to transmute and
|
|
|
|
// store the data as a static buffer.
|
|
|
|
unsafe { cast::transmute(data) }
|
|
|
|
};
|
|
|
|
Some(ArchiveMetadata {
|
|
|
|
archive: ar,
|
|
|
|
data: data,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_slice<'a>(&'a self) -> &'a [u8] { self.data }
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just a small wrapper to time how long reading metadata takes.
|
2014-03-07 16:37:18 -06:00
|
|
|
fn get_metadata_section(os: Os, filename: &Path) -> Result<MetadataBlob, ~str> {
|
2013-12-16 22:58:21 -06:00
|
|
|
let start = time::precise_time_ns();
|
|
|
|
let ret = get_metadata_section_imp(os, filename);
|
|
|
|
info!("reading {} => {}ms", filename.filename_display(),
|
|
|
|
(time::precise_time_ns() - start) / 1000000);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-03-07 16:37:18 -06:00
|
|
|
fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, ~str> {
|
|
|
|
if !filename.exists() {
|
|
|
|
return Err(format!("no such file: '{}'", filename.display()));
|
|
|
|
}
|
Store metadata separately in rlib files
Right now whenever an rlib file is linked against, all of the metadata from the
rlib is pulled in to the final staticlib or binary. The reason for this is that
the metadata is currently stored in a section of the object file. Note that this
is intentional for dynamic libraries in order to distribute metadata bundled
with static libraries.
This commit alters the situation for rlib libraries to instead store the
metadata in a separate file in the archive. In doing so, when the archive is
passed to the linker, none of the metadata will get pulled into the result
executable. Furthermore, the metadata file is skipped when assembling rlibs into
an archive.
The snag in this implementation comes with multiple output formats. When
generating a dylib, the metadata needs to be in the object file, but when
generating an rlib this needs to be separate. In order to accomplish this, the
metadata variable is inserted into an entirely separate LLVM Module which is
then codegen'd into a different location (foo.metadata.o). This is then linked
into dynamic libraries and silently ignored for rlib files.
While changing how metadata is inserted into archives, I have also stopped
compressing metadata when inserted into rlib files. We have wanted to stop
compressing metadata, but the sections it creates in object file sections are
apparently too large. Thankfully if it's just an arbitrary file it doesn't
matter how large it is.
I have seen massive reductions in executable sizes, as well as staticlib output
sizes (to confirm that this is all working).
2013-12-03 19:41:01 -06:00
|
|
|
if filename.filename_str().unwrap().ends_with(".rlib") {
|
2013-12-16 22:58:21 -06:00
|
|
|
// 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.
|
|
|
|
let archive = match ArchiveRO::open(filename) {
|
|
|
|
Some(ar) => ar,
|
|
|
|
None => {
|
|
|
|
debug!("llvm didn't like `{}`", filename.display());
|
2014-03-07 16:37:18 -06:00
|
|
|
return Err(format!("failed to read rlib metadata: '{}'",
|
|
|
|
filename.display()));
|
2013-12-16 22:58:21 -06:00
|
|
|
}
|
|
|
|
};
|
2014-03-07 16:37:18 -06:00
|
|
|
return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
|
|
|
|
None => return Err(format!("failed to read rlib metadata: '{}'",
|
|
|
|
filename.display())),
|
|
|
|
Some(blob) => return Ok(blob)
|
|
|
|
}
|
Store metadata separately in rlib files
Right now whenever an rlib file is linked against, all of the metadata from the
rlib is pulled in to the final staticlib or binary. The reason for this is that
the metadata is currently stored in a section of the object file. Note that this
is intentional for dynamic libraries in order to distribute metadata bundled
with static libraries.
This commit alters the situation for rlib libraries to instead store the
metadata in a separate file in the archive. In doing so, when the archive is
passed to the linker, none of the metadata will get pulled into the result
executable. Furthermore, the metadata file is skipped when assembling rlibs into
an archive.
The snag in this implementation comes with multiple output formats. When
generating a dylib, the metadata needs to be in the object file, but when
generating an rlib this needs to be separate. In order to accomplish this, the
metadata variable is inserted into an entirely separate LLVM Module which is
then codegen'd into a different location (foo.metadata.o). This is then linked
into dynamic libraries and silently ignored for rlib files.
While changing how metadata is inserted into archives, I have also stopped
compressing metadata when inserted into rlib files. We have wanted to stop
compressing metadata, but the sections it creates in object file sections are
apparently too large. Thankfully if it's just an arbitrary file it doesn't
matter how large it is.
I have seen massive reductions in executable sizes, as well as staticlib output
sizes (to confirm that this is all working).
2013-12-03 19:41:01 -06:00
|
|
|
}
|
2013-01-23 13:43:58 -06:00
|
|
|
unsafe {
|
Store metadata separately in rlib files
Right now whenever an rlib file is linked against, all of the metadata from the
rlib is pulled in to the final staticlib or binary. The reason for this is that
the metadata is currently stored in a section of the object file. Note that this
is intentional for dynamic libraries in order to distribute metadata bundled
with static libraries.
This commit alters the situation for rlib libraries to instead store the
metadata in a separate file in the archive. In doing so, when the archive is
passed to the linker, none of the metadata will get pulled into the result
executable. Furthermore, the metadata file is skipped when assembling rlibs into
an archive.
The snag in this implementation comes with multiple output formats. When
generating a dylib, the metadata needs to be in the object file, but when
generating an rlib this needs to be separate. In order to accomplish this, the
metadata variable is inserted into an entirely separate LLVM Module which is
then codegen'd into a different location (foo.metadata.o). This is then linked
into dynamic libraries and silently ignored for rlib files.
While changing how metadata is inserted into archives, I have also stopped
compressing metadata when inserted into rlib files. We have wanted to stop
compressing metadata, but the sections it creates in object file sections are
apparently too large. Thankfully if it's just an arbitrary file it doesn't
matter how large it is.
I have seen massive reductions in executable sizes, as well as staticlib output
sizes (to confirm that this is all working).
2013-12-03 19:41:01 -06:00
|
|
|
let mb = filename.with_c_str(|buf| {
|
|
|
|
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
|
|
|
|
});
|
2014-03-07 16:37:18 -06:00
|
|
|
if mb as int == 0 {
|
|
|
|
return Err(format!("error reading library: '{}'",filename.display()))
|
|
|
|
}
|
Add generation of static libraries to rustc
This commit implements the support necessary for generating both intermediate
and result static rust libraries. This is an implementation of my thoughts in
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html.
When compiling a library, we still retain the "lib" option, although now there
are "rlib", "staticlib", and "dylib" as options for crate_type (and these are
stackable). The idea of "lib" is to generate the "compiler default" instead of
having too choose (although all are interchangeable). For now I have left the
"complier default" to be a dynamic library for size reasons.
Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an
rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a
dynamic object. I chose this for size reasons, but also because you're probably
not going to be embedding the rustc compiler anywhere any time soon.
Other than the options outlined above, there are a few defaults/preferences that
are now opinionated in the compiler:
* If both a .dylib and .rlib are found for a rust library, the compiler will
prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option
* If generating a "lib", the compiler will generate a dynamic library. This is
overridable by explicitly saying what flavor you'd like (rlib, staticlib,
dylib).
* If no options are passed to the command line, and no crate_type is found in
the destination crate, then an executable is generated
With this change, you can successfully build a rust program with 0 dynamic
dependencies on rust libraries. There is still a dynamic dependency on
librustrt, but I plan on removing that in a subsequent commit.
This change includes no tests just yet. Our current testing
infrastructure/harnesses aren't very amenable to doing flavorful things with
linking, so I'm planning on adding a new mode of testing which I believe belongs
as a separate commit.
Closes #552
2013-11-15 16:03:29 -06:00
|
|
|
let of = match ObjectFile::new(mb) {
|
|
|
|
Some(of) => of,
|
2014-03-07 16:37:18 -06:00
|
|
|
_ => return Err(format!("provided path not an object file: '{}'", filename.display()))
|
2013-01-23 13:43:58 -06:00
|
|
|
};
|
2013-08-25 22:21:13 -05:00
|
|
|
let si = mk_section_iter(of.llof);
|
2013-01-23 13:43:58 -06:00
|
|
|
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
|
2014-04-03 12:45:36 -05:00
|
|
|
let mut name_buf = ptr::null();
|
|
|
|
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
|
|
|
|
let name = str::raw::from_buf_len(name_buf as *u8, name_len as uint);
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("get_metadata_section: name {}", name);
|
2013-08-31 11:13:04 -05:00
|
|
|
if read_meta_section_name(os) == name {
|
2013-01-23 13:43:58 -06:00
|
|
|
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
|
|
|
|
let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
|
2014-03-07 16:37:18 -06:00
|
|
|
let mut found = Err(format!("metadata not found: '{}'", filename.display()));
|
2013-06-20 00:52:02 -05:00
|
|
|
let cvbuf: *u8 = cast::transmute(cbuf);
|
|
|
|
let vlen = encoder::metadata_encoding_version.len();
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("checking {} bytes of metadata-version stamp",
|
2013-06-20 00:52:02 -05:00
|
|
|
vlen);
|
2014-02-06 01:34:33 -06:00
|
|
|
let minsz = cmp::min(vlen, csz);
|
2014-03-08 17:11:52 -06:00
|
|
|
let version_ok = slice::raw::buf_as_slice(cvbuf, minsz,
|
2014-02-18 06:40:25 -06:00
|
|
|
|buf0| buf0 == encoder::metadata_encoding_version);
|
2014-03-07 16:37:18 -06:00
|
|
|
if !version_ok { return Err(format!("incompatible metadata version found: '{}'",
|
2014-04-07 18:08:49 -05:00
|
|
|
filename.display())); }
|
2013-06-20 00:52:02 -05:00
|
|
|
|
2014-02-10 15:50:42 -06:00
|
|
|
let cvbuf1 = cvbuf.offset(vlen as int);
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("inflating {} bytes of compressed metadata",
|
2013-08-25 22:21:13 -05:00
|
|
|
csz - vlen);
|
2014-03-08 17:11:52 -06:00
|
|
|
slice::raw::buf_as_slice(cvbuf1, csz-vlen, |bytes| {
|
2014-04-07 18:08:49 -05:00
|
|
|
match flate::inflate_bytes(bytes) {
|
|
|
|
Some(inflated) => found = Ok(MetadataVec(inflated)),
|
|
|
|
None => found = Err(format!("failed to decompress metadata for: '{}'",
|
|
|
|
filename.display()))
|
|
|
|
}
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2014-03-07 16:37:18 -06:00
|
|
|
if found.is_ok() {
|
2013-08-25 22:21:13 -05:00
|
|
|
return found;
|
|
|
|
}
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
2013-01-23 13:43:58 -06:00
|
|
|
llvm::LLVMMoveToNextSection(si.llsi);
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
2014-03-07 16:37:18 -06:00
|
|
|
return Err(format!("metadata not found: '{}'", filename.display()));
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
pub fn meta_section_name(os: Os) -> &'static str {
|
2012-08-06 14:34:08 -05:00
|
|
|
match os {
|
2013-08-31 11:13:04 -05:00
|
|
|
OsMacos => "__DATA,__note.rustc",
|
|
|
|
OsWin32 => ".note.rustc",
|
|
|
|
OsLinux => ".note.rustc",
|
|
|
|
OsAndroid => ".note.rustc",
|
|
|
|
OsFreebsd => ".note.rustc"
|
2012-05-22 19:16:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
pub fn read_meta_section_name(os: Os) -> &'static str {
|
2013-03-13 03:22:01 -05:00
|
|
|
match os {
|
2013-08-31 11:13:04 -05:00
|
|
|
OsMacos => "__note.rustc",
|
|
|
|
OsWin32 => ".note.rustc",
|
|
|
|
OsLinux => ".note.rustc",
|
|
|
|
OsAndroid => ".note.rustc",
|
|
|
|
OsFreebsd => ".note.rustc"
|
2013-03-13 03:22:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-15 22:23:06 -05:00
|
|
|
// A diagnostic function for dumping crate metadata to an output stream
|
2014-02-13 23:07:09 -06:00
|
|
|
pub fn list_file_metadata(os: Os, path: &Path,
|
2014-01-29 20:42:19 -06:00
|
|
|
out: &mut io::Writer) -> io::IoResult<()> {
|
2013-12-16 22:58:21 -06:00
|
|
|
match get_metadata_section(os, path) {
|
2014-03-07 16:37:18 -06:00
|
|
|
Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),
|
|
|
|
Err(msg) => {
|
|
|
|
write!(out, "{}\n", msg)
|
2014-02-10 14:50:53 -06:00
|
|
|
}
|
2012-05-15 22:23:06 -05:00
|
|
|
}
|
|
|
|
}
|