Skip to content

Commit

Permalink
rustc/rusti/rustpkg: Infer packages from extern mod directives
Browse files Browse the repository at this point in the history
This commit won't be quite as useful until I implement RUST_PATH and
until we change `extern mod` to take a general string instead of
an identifier (rust-lang#5682 and rust-lang#6407).

With that said, now if you're using rustpkg and a program contains:

extern mod foo;

rustpkg will attempt to search for `foo`, so that you don't have to
provide a -L directory explicitly. In addition, rustpkg will
actually try to build and install `foo`, unless it's already
installed (specifically, I tested that `extern mod extra;` would
not cause it to try to find source for `extra` and compile it
again).

This is as per rust-lang#5681.

Incidentally, I changed some driver code to infer the link name
from the crate link_meta attributes. If that change isn't ok, say
something. Also, I changed the addl_lib_search_paths field in the
session options to be an @mut ~[Path] so that it can be modified
after expansion but before later phases.
  • Loading branch information
catamorphism committed May 30, 2013
1 parent 37388fb commit ed3e7a1
Show file tree
Hide file tree
Showing 17 changed files with 745 additions and 492 deletions.
319 changes: 175 additions & 144 deletions src/librustc/driver/driver.rs

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ pub struct options {
save_temps: bool,
jit: bool,
output_type: back::link::output_type,
addl_lib_search_paths: ~[Path],
addl_lib_search_paths: @mut ~[Path], // This is mutable for rustpkg, which
// updates search paths based on the
// parsed code
linker: Option<~str>,
linker_args: ~[~str],
maybe_sysroot: Option<@Path>,
Expand Down Expand Up @@ -312,7 +314,7 @@ pub fn basic_options() -> @options {
save_temps: false,
jit: false,
output_type: link::output_type_exe,
addl_lib_search_paths: ~[],
addl_lib_search_paths: @mut ~[],
linker: None,
linker_args: ~[],
maybe_sysroot: None,
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/metadata/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,18 @@ pub trait FileSearch {

pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
target_triple: &str,
addl_lib_search_paths: ~[Path])
addl_lib_search_paths: @mut ~[Path])
-> @FileSearch {
struct FileSearchImpl {
sysroot: @Path,
addl_lib_search_paths: ~[Path],
addl_lib_search_paths: @mut ~[Path],
target_triple: ~str
}
impl FileSearch for FileSearchImpl {
fn sysroot(&self) -> @Path { self.sysroot }
fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool {
debug!("filesearch: searching additional lib search paths");
debug!("filesearch: searching additional lib search paths [%?]",
self.addl_lib_search_paths.len());
// a little weird
self.addl_lib_search_paths.each(f);

Expand Down
10 changes: 5 additions & 5 deletions src/librustc/rustc.rc
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,11 @@ pub fn version(argv0: &str) {

pub fn usage(argv0: &str) {
let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0);
io::println(groups::usage(message, optgroups()) +
"Additional help:
-W help Print 'lint' options and default settings
-Z help Print internal options for debugging rustc
");
io::println(fmt!("%s \
Additional help: \
-W help Print 'lint' options and default settings \
-Z help Print internal options for debugging rustc",
groups::usage(message, optgroups())));
}

pub fn describe_warnings() {
Expand Down
8 changes: 4 additions & 4 deletions src/librusti/rusti.rc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ fn run(repl: Repl, input: ~str) -> Repl {
let options = @session::options {
crate_type: session::unknown_crate,
binary: binary,
addl_lib_search_paths: repl.lib_search_paths.map(|p| Path(*p)),
addl_lib_search_paths: @mut repl.lib_search_paths.map(|p| Path(*p)),
jit: true,
.. copy *session::basic_options()
};
Expand All @@ -142,7 +142,7 @@ fn run(repl: Repl, input: ~str) -> Repl {
binary,
&wrapped);

let outputs = driver::build_output_filenames(&wrapped, &None, &None, sess);
let outputs = driver::build_output_filenames(&wrapped, &None, &None, [], sess);
debug!("calling compile_upto");

let crate = driver::parse_input(sess, copy cfg, &wrapped);
Expand Down Expand Up @@ -188,15 +188,15 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
let binary = @copy binary;
let options = @session::options {
binary: binary,
addl_lib_search_paths: ~[os::getcwd()],
addl_lib_search_paths: @mut ~[os::getcwd()],
.. copy *session::basic_options()
};
let input = driver::file_input(copy src_path);
let sess = driver::build_session(options, diagnostic::emit);
*sess.building_library = true;
let cfg = driver::build_configuration(sess, binary, &input);
let outputs = driver::build_output_filenames(
&input, &None, &None, sess);
&input, &None, &None, [], sess);
// If the library already exists and is newer than the source
// file, skip compilation and return None.
let mut should_compile = true;
Expand Down
6 changes: 3 additions & 3 deletions src/librustpkg/conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
// Useful conditions

pub use core::path::Path;
pub use util::PkgId;
pub use package_id::PkgId;

condition! {
bad_path: (super::Path, ~str) -> super::Path;
}

condition! {
nonexistent_package: (super::PkgId, ~str) -> ();
nonexistent_package: (super::PkgId, ~str) -> super::Path;
}

condition! {
Expand All @@ -30,5 +30,5 @@ condition! {
}

condition! {
bad_pkg_id: (super::Path, ~str) -> ::util::PkgId;
bad_pkg_id: (super::Path, ~str) -> super::PkgId;
}
133 changes: 133 additions & 0 deletions src/librustpkg/package_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod std;

pub use package_path::{RemotePath, LocalPath, normalize, hash};
use std::semver;
use core::prelude::*;

/// Placeholder
pub fn default_version() -> Version { ExactRevision(0.1) }

/// Path-fragment identifier of a package such as
/// 'github.com/graydon/test'; path must be a relative
/// path with >=1 component.
pub struct PkgId {
/// Remote path: for example, github.com/mozilla/quux-whatever
remote_path: RemotePath,
/// Local path: for example, /home/quux/github.com/mozilla/quux_whatever
/// Note that '-' normalizes to '_' when mapping a remote path
/// onto a local path
/// Also, this will change when we implement #6407, though we'll still
/// need to keep track of separate local and remote paths
local_path: LocalPath,
/// Short name. This is the local path's filestem, but we store it
/// redundantly so as to not call get() everywhere (filestem() returns an
/// option)
short_name: ~str,
version: Version
}

pub impl PkgId {
fn new(s: &str) -> PkgId {
use conditions::bad_pkg_id::cond;

let p = Path(s);
if p.is_absolute {
return cond.raise((p, ~"absolute pkgid"));
}
if p.components.len() < 1 {
return cond.raise((p, ~"0-length pkgid"));
}
let remote_path = RemotePath(p);
let local_path = normalize(copy remote_path);
let short_name = (copy local_path).filestem().expect(fmt!("Strange path! %s", s));
PkgId {
local_path: local_path,
remote_path: remote_path,
short_name: short_name,
version: default_version()
}
}

fn hash(&self) -> ~str {
fmt!("%s-%s-%s", self.remote_path.to_str(),
hash(self.remote_path.to_str() + self.version.to_str()),
self.version.to_str())
}

fn short_name_with_version(&self) -> ~str {
fmt!("%s-%s", self.short_name, self.version.to_str())
}
}

impl ToStr for PkgId {
fn to_str(&self) -> ~str {
// should probably use the filestem and not the whole path
fmt!("%s-%s", self.local_path.to_str(), self.version.to_str())
}
}

/// A version is either an exact revision,
/// or a semantic version
pub enum Version {
ExactRevision(float),
SemVersion(semver::Version)
}


impl Ord for Version {
fn lt(&self, other: &Version) -> bool {
match (self, other) {
(&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2,
(&SemVersion(ref v1), &SemVersion(ref v2)) => v1 < v2,
_ => false // incomparable, really
}
}
fn le(&self, other: &Version) -> bool {
match (self, other) {
(&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2,
(&SemVersion(ref v1), &SemVersion(ref v2)) => v1 <= v2,
_ => false // incomparable, really
}
}
fn ge(&self, other: &Version) -> bool {
match (self, other) {
(&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2,
(&SemVersion(ref v1), &SemVersion(ref v2)) => v1 > v2,
_ => false // incomparable, really
}
}
fn gt(&self, other: &Version) -> bool {
match (self, other) {
(&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2,
(&SemVersion(ref v1), &SemVersion(ref v2)) => v1 >= v2,
_ => false // incomparable, really
}
}

}

impl ToStr for Version {
fn to_str(&self) -> ~str {
match *self {
ExactRevision(ref n) => n.to_str(),
SemVersion(ref v) => v.to_str()
}
}
}

pub fn parse_vers(vers: ~str) -> result::Result<semver::Version, ~str> {
match semver::parse(vers) {
Some(vers) => result::Ok(vers),
None => result::Err(~"could not parse version: invalid")
}
}
55 changes: 55 additions & 0 deletions src/librustpkg/package_path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// rustpkg utilities having to do with local and remote paths

use core::path::Path;
use core::option::Some;
use core::{hash, str};
use core::rt::io::Writer;
use core::hash::Streaming;

/// Wrappers to prevent local and remote paths from getting confused
/// (These will go away after #6407)
pub struct RemotePath (Path);
pub struct LocalPath (Path);


// normalize should be the only way to construct a LocalPath
// (though this isn't enforced)
/// Replace all occurrences of '-' in the stem part of path with '_'
/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux
/// as the same name
pub fn normalize(p_: RemotePath) -> LocalPath {
let RemotePath(p) = p_;
match p.filestem() {
None => LocalPath(p),
Some(st) => {
let replaced = str::replace(st, "-", "_");
if replaced != st {
LocalPath(p.with_filestem(replaced))
}
else {
LocalPath(p)
}
}
}
}

pub fn write<W: Writer>(writer: &mut W, string: &str) {
let buffer = str::as_bytes_slice(string);
writer.write(buffer);
}

pub fn hash(data: ~str) -> ~str {
let hasher = &mut hash::default_state();
write(hasher, data);
hasher.result_str()
}
Loading

0 comments on commit ed3e7a1

Please sign in to comment.