rustc/rusti/rustpkg: Infer packages from extern mod
directives
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 (#5682 and #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 #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.
This commit is contained in:
parent
341678b815
commit
c120464be0
17 changed files with 729 additions and 472 deletions
|
@ -161,8 +161,15 @@ pub fn parse_input(sess: Session, cfg: ast::crate_cfg, input: &input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// First phase to do, last phase to do
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub enum compile_upto {
|
pub struct compile_upto {
|
||||||
|
from: compile_phase,
|
||||||
|
to: compile_phase
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
pub enum compile_phase {
|
||||||
cu_parse,
|
cu_parse,
|
||||||
cu_expand,
|
cu_expand,
|
||||||
cu_typeck,
|
cu_typeck,
|
||||||
|
@ -177,32 +184,38 @@ pub enum compile_upto {
|
||||||
#[fixed_stack_segment]
|
#[fixed_stack_segment]
|
||||||
pub fn compile_rest(sess: Session,
|
pub fn compile_rest(sess: Session,
|
||||||
cfg: ast::crate_cfg,
|
cfg: ast::crate_cfg,
|
||||||
upto: compile_upto,
|
phases: compile_upto,
|
||||||
outputs: Option<@OutputFilenames>,
|
outputs: Option<@OutputFilenames>,
|
||||||
curr: Option<@ast::crate>)
|
curr: Option<@ast::crate>)
|
||||||
-> (Option<@ast::crate>, Option<ty::ctxt>) {
|
-> (Option<@ast::crate>, Option<ty::ctxt>) {
|
||||||
|
|
||||||
let time_passes = sess.time_passes();
|
let time_passes = sess.time_passes();
|
||||||
|
|
||||||
let (llmod, link_meta) = {
|
let mut crate_opt = curr;
|
||||||
|
|
||||||
let mut crate = curr.unwrap();
|
if phases.from == cu_parse || phases.from == cu_everything {
|
||||||
|
|
||||||
*sess.building_library = session::building_library(
|
*sess.building_library = session::building_library(
|
||||||
sess.opts.crate_type, crate, sess.opts.test);
|
sess.opts.crate_type, crate_opt.unwrap(), sess.opts.test);
|
||||||
|
|
||||||
crate = time(time_passes, ~"expansion", ||
|
crate_opt = Some(time(time_passes, ~"expansion", ||
|
||||||
syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg,
|
syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg,
|
||||||
crate));
|
crate_opt.unwrap())));
|
||||||
|
|
||||||
crate = time(time_passes, ~"configuration", ||
|
crate_opt = Some(time(time_passes, ~"configuration", ||
|
||||||
front::config::strip_unconfigured_items(crate));
|
front::config::strip_unconfigured_items(crate_opt.unwrap())));
|
||||||
|
|
||||||
crate = time(time_passes, ~"maybe building test harness", ||
|
crate_opt = Some(time(time_passes, ~"maybe building test harness", ||
|
||||||
front::test::modify_for_testing(sess, crate));
|
front::test::modify_for_testing(sess, crate_opt.unwrap())));
|
||||||
|
}
|
||||||
|
|
||||||
if upto == cu_expand { return (Some(crate), None); }
|
if phases.to == cu_expand { return (crate_opt, None); }
|
||||||
|
|
||||||
|
assert!(phases.from != cu_no_trans);
|
||||||
|
|
||||||
|
let mut crate = crate_opt.unwrap();
|
||||||
|
|
||||||
|
let (llmod, link_meta) = {
|
||||||
crate = time(time_passes, ~"intrinsic injection", ||
|
crate = time(time_passes, ~"intrinsic injection", ||
|
||||||
front::intrinsic_inject::inject_intrinsic(sess, crate));
|
front::intrinsic_inject::inject_intrinsic(sess, crate));
|
||||||
|
|
||||||
|
@ -236,6 +249,9 @@ pub fn compile_rest(sess: Session,
|
||||||
let freevars = time(time_passes, ~"freevar finding", ||
|
let freevars = time(time_passes, ~"freevar finding", ||
|
||||||
freevars::annotate_freevars(def_map, crate));
|
freevars::annotate_freevars(def_map, crate));
|
||||||
|
|
||||||
|
let freevars = time(time_passes, ~"freevar finding", ||
|
||||||
|
freevars::annotate_freevars(def_map, crate));
|
||||||
|
|
||||||
let region_map = time(time_passes, ~"region resolution", ||
|
let region_map = time(time_passes, ~"region resolution", ||
|
||||||
middle::region::resolve_crate(sess, def_map, crate));
|
middle::region::resolve_crate(sess, def_map, crate));
|
||||||
|
|
||||||
|
@ -257,7 +273,7 @@ pub fn compile_rest(sess: Session,
|
||||||
middle::check_const::check_crate(sess, crate, ast_map, def_map,
|
middle::check_const::check_crate(sess, crate, ast_map, def_map,
|
||||||
method_map, ty_cx));
|
method_map, ty_cx));
|
||||||
|
|
||||||
if upto == cu_typeck { return (Some(crate), Some(ty_cx)); }
|
if phases.to == cu_typeck { return (Some(crate), Some(ty_cx)); }
|
||||||
|
|
||||||
time(time_passes, ~"privacy checking", ||
|
time(time_passes, ~"privacy checking", ||
|
||||||
middle::privacy::check_crate(ty_cx, &method_map, crate));
|
middle::privacy::check_crate(ty_cx, &method_map, crate));
|
||||||
|
@ -293,7 +309,7 @@ pub fn compile_rest(sess: Session,
|
||||||
time(time_passes, ~"lint checking", ||
|
time(time_passes, ~"lint checking", ||
|
||||||
lint::check_crate(ty_cx, crate));
|
lint::check_crate(ty_cx, crate));
|
||||||
|
|
||||||
if upto == cu_no_trans { return (Some(crate), Some(ty_cx)); }
|
if phases.to == cu_no_trans { return (Some(crate), Some(ty_cx)); }
|
||||||
|
|
||||||
let maps = astencode::Maps {
|
let maps = astencode::Maps {
|
||||||
root_map: root_map,
|
root_map: root_map,
|
||||||
|
@ -351,7 +367,7 @@ pub fn compile_rest(sess: Session,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_upto(sess: Session, cfg: ast::crate_cfg,
|
pub fn compile_upto(sess: Session, cfg: ast::crate_cfg,
|
||||||
input: &input, upto: compile_upto,
|
input: &input, upto: compile_phase,
|
||||||
outputs: Option<@OutputFilenames>)
|
outputs: Option<@OutputFilenames>)
|
||||||
-> (Option<@ast::crate>, Option<ty::ctxt>) {
|
-> (Option<@ast::crate>, Option<ty::ctxt>) {
|
||||||
let time_passes = sess.time_passes();
|
let time_passes = sess.time_passes();
|
||||||
|
@ -359,7 +375,8 @@ pub fn compile_upto(sess: Session, cfg: ast::crate_cfg,
|
||||||
|| parse_input(sess, copy cfg, input) );
|
|| parse_input(sess, copy cfg, input) );
|
||||||
if upto == cu_parse { return (Some(crate), None); }
|
if upto == cu_parse { return (Some(crate), None); }
|
||||||
|
|
||||||
compile_rest(sess, cfg, upto, outputs, Some(crate))
|
compile_rest(sess, cfg, compile_upto { from: cu_parse, to: upto },
|
||||||
|
outputs, Some(crate))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input,
|
pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input,
|
||||||
|
@ -367,7 +384,7 @@ pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input,
|
||||||
let upto = if sess.opts.parse_only { cu_parse }
|
let upto = if sess.opts.parse_only { cu_parse }
|
||||||
else if sess.opts.no_trans { cu_no_trans }
|
else if sess.opts.no_trans { cu_no_trans }
|
||||||
else { cu_everything };
|
else { cu_everything };
|
||||||
let outputs = build_output_filenames(input, outdir, output, sess);
|
let outputs = build_output_filenames(input, outdir, output, [], sess); // ???
|
||||||
compile_upto(sess, cfg, input, upto, Some(outputs));
|
compile_upto(sess, cfg, input, upto, Some(outputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,8 +662,7 @@ pub fn build_session_options(binary: @~str,
|
||||||
~"2" => Default,
|
~"2" => Default,
|
||||||
~"3" => Aggressive,
|
~"3" => Aggressive,
|
||||||
_ => {
|
_ => {
|
||||||
early_error(demitter, ~"optimization level needs " +
|
early_error(demitter, ~"optimization level needs to be between 0-3")
|
||||||
"to be between 0-3")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { No }
|
} else { No }
|
||||||
|
@ -706,7 +722,7 @@ pub fn build_session_options(binary: @~str,
|
||||||
save_temps: save_temps,
|
save_temps: save_temps,
|
||||||
jit: jit,
|
jit: jit,
|
||||||
output_type: output_type,
|
output_type: output_type,
|
||||||
addl_lib_search_paths: addl_lib_search_paths,
|
addl_lib_search_paths: @mut addl_lib_search_paths,
|
||||||
linker: linker,
|
linker: linker,
|
||||||
linker_args: linker_args,
|
linker_args: linker_args,
|
||||||
maybe_sysroot: sysroot_opt,
|
maybe_sysroot: sysroot_opt,
|
||||||
|
@ -745,7 +761,7 @@ pub fn build_session_(sopts: @session::options,
|
||||||
let filesearch = filesearch::mk_filesearch(
|
let filesearch = filesearch::mk_filesearch(
|
||||||
&sopts.maybe_sysroot,
|
&sopts.maybe_sysroot,
|
||||||
sopts.target_triple,
|
sopts.target_triple,
|
||||||
/*bad*/copy sopts.addl_lib_search_paths);
|
sopts.addl_lib_search_paths);
|
||||||
@Session_ {
|
@Session_ {
|
||||||
targ_cfg: target_cfg,
|
targ_cfg: target_cfg,
|
||||||
opts: sopts,
|
opts: sopts,
|
||||||
|
@ -854,6 +870,7 @@ pub struct OutputFilenames {
|
||||||
pub fn build_output_filenames(input: &input,
|
pub fn build_output_filenames(input: &input,
|
||||||
odir: &Option<Path>,
|
odir: &Option<Path>,
|
||||||
ofile: &Option<Path>,
|
ofile: &Option<Path>,
|
||||||
|
attrs: &[ast::attribute],
|
||||||
sess: Session)
|
sess: Session)
|
||||||
-> @OutputFilenames {
|
-> @OutputFilenames {
|
||||||
let obj_path;
|
let obj_path;
|
||||||
|
@ -863,7 +880,6 @@ pub fn build_output_filenames(input: &input,
|
||||||
sopts.output_type != link::output_type_exe ||
|
sopts.output_type != link::output_type_exe ||
|
||||||
sopts.is_static && *sess.building_library;
|
sopts.is_static && *sess.building_library;
|
||||||
|
|
||||||
|
|
||||||
let obj_suffix =
|
let obj_suffix =
|
||||||
match sopts.output_type {
|
match sopts.output_type {
|
||||||
link::output_type_none => ~"none",
|
link::output_type_none => ~"none",
|
||||||
|
@ -887,11 +903,26 @@ pub fn build_output_filenames(input: &input,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let stem = match *input {
|
let mut stem = match *input {
|
||||||
file_input(ref ifile) => (*ifile).filestem().get(),
|
file_input(ref ifile) => (*ifile).filestem().get(),
|
||||||
str_input(_) => ~"rust_out"
|
str_input(_) => ~"rust_out"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If a linkage name meta is present, we use it as the link name
|
||||||
|
let linkage_metas = attr::find_linkage_metas(attrs);
|
||||||
|
if !linkage_metas.is_empty() {
|
||||||
|
// But if a linkage meta is present, that overrides
|
||||||
|
let maybe_matches = attr::find_meta_items_by_name(linkage_metas, "name");
|
||||||
|
if !maybe_matches.is_empty() {
|
||||||
|
match attr::get_meta_item_value_str(maybe_matches[0]) {
|
||||||
|
Some(s) => stem = copy *s,
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the name is missing, we just default to the filename
|
||||||
|
// version
|
||||||
|
}
|
||||||
|
|
||||||
if *sess.building_library {
|
if *sess.building_library {
|
||||||
out_path = dirpath.push(os::dll_filename(stem));
|
out_path = dirpath.push(os::dll_filename(stem));
|
||||||
obj_path = dirpath.push(stem).with_filetype(obj_suffix);
|
obj_path = dirpath.push(stem).with_filetype(obj_suffix);
|
||||||
|
|
|
@ -136,7 +136,9 @@ pub struct options {
|
||||||
save_temps: bool,
|
save_temps: bool,
|
||||||
jit: bool,
|
jit: bool,
|
||||||
output_type: back::link::output_type,
|
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: Option<~str>,
|
||||||
linker_args: ~[~str],
|
linker_args: ~[~str],
|
||||||
maybe_sysroot: Option<@Path>,
|
maybe_sysroot: Option<@Path>,
|
||||||
|
@ -316,7 +318,7 @@ pub fn basic_options() -> @options {
|
||||||
save_temps: false,
|
save_temps: false,
|
||||||
jit: false,
|
jit: false,
|
||||||
output_type: link::output_type_exe,
|
output_type: link::output_type_exe,
|
||||||
addl_lib_search_paths: ~[],
|
addl_lib_search_paths: @mut ~[],
|
||||||
linker: None,
|
linker: None,
|
||||||
linker_args: ~[],
|
linker_args: ~[],
|
||||||
maybe_sysroot: None,
|
maybe_sysroot: None,
|
||||||
|
|
|
@ -35,17 +35,18 @@ pub trait FileSearch {
|
||||||
|
|
||||||
pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
|
pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
|
||||||
target_triple: &str,
|
target_triple: &str,
|
||||||
addl_lib_search_paths: ~[Path])
|
addl_lib_search_paths: @mut ~[Path])
|
||||||
-> @FileSearch {
|
-> @FileSearch {
|
||||||
struct FileSearchImpl {
|
struct FileSearchImpl {
|
||||||
sysroot: @Path,
|
sysroot: @Path,
|
||||||
addl_lib_search_paths: ~[Path],
|
addl_lib_search_paths: @mut ~[Path],
|
||||||
target_triple: ~str
|
target_triple: ~str
|
||||||
}
|
}
|
||||||
impl FileSearch for FileSearchImpl {
|
impl FileSearch for FileSearchImpl {
|
||||||
fn sysroot(&self) -> @Path { self.sysroot }
|
fn sysroot(&self) -> @Path { self.sysroot }
|
||||||
fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool {
|
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
|
// a little weird
|
||||||
self.addl_lib_search_paths.each(f);
|
self.addl_lib_search_paths.each(f);
|
||||||
|
|
||||||
|
|
|
@ -183,11 +183,11 @@ pub fn version(argv0: &str) {
|
||||||
|
|
||||||
pub fn usage(argv0: &str) {
|
pub fn usage(argv0: &str) {
|
||||||
let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0);
|
let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0);
|
||||||
io::println(groups::usage(message, optgroups()) +
|
io::println(fmt!("%s \
|
||||||
"Additional help:
|
Additional help: \
|
||||||
-W help Print 'lint' options and default settings
|
-W help Print 'lint' options and default settings \
|
||||||
-Z help Print internal options for debugging rustc
|
-Z help Print internal options for debugging rustc",
|
||||||
");
|
groups::usage(message, optgroups())));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn describe_warnings() {
|
pub fn describe_warnings() {
|
||||||
|
|
|
@ -121,7 +121,7 @@ fn run(repl: Repl, input: ~str) -> Repl {
|
||||||
let options = @session::options {
|
let options = @session::options {
|
||||||
crate_type: session::unknown_crate,
|
crate_type: session::unknown_crate,
|
||||||
binary: binary,
|
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,
|
jit: true,
|
||||||
.. copy *session::basic_options()
|
.. copy *session::basic_options()
|
||||||
};
|
};
|
||||||
|
@ -142,11 +142,12 @@ fn run(repl: Repl, input: ~str) -> Repl {
|
||||||
binary,
|
binary,
|
||||||
&wrapped);
|
&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");
|
debug!("calling compile_upto");
|
||||||
|
|
||||||
let crate = driver::parse_input(sess, copy cfg, &wrapped);
|
let crate = driver::parse_input(sess, copy cfg, &wrapped);
|
||||||
driver::compile_rest(sess, cfg, driver::cu_everything,
|
driver::compile_rest(sess, cfg, driver::compile_upto { from: driver::cu_parse,
|
||||||
|
to: driver::cu_everything },
|
||||||
Some(outputs), Some(crate));
|
Some(outputs), Some(crate));
|
||||||
|
|
||||||
let mut opt = None;
|
let mut opt = None;
|
||||||
|
@ -188,7 +189,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
|
||||||
let binary = @copy binary;
|
let binary = @copy binary;
|
||||||
let options = @session::options {
|
let options = @session::options {
|
||||||
binary: binary,
|
binary: binary,
|
||||||
addl_lib_search_paths: ~[os::getcwd()],
|
addl_lib_search_paths: @mut ~[os::getcwd()],
|
||||||
.. copy *session::basic_options()
|
.. copy *session::basic_options()
|
||||||
};
|
};
|
||||||
let input = driver::file_input(copy src_path);
|
let input = driver::file_input(copy src_path);
|
||||||
|
@ -196,7 +197,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
|
||||||
*sess.building_library = true;
|
*sess.building_library = true;
|
||||||
let cfg = driver::build_configuration(sess, binary, &input);
|
let cfg = driver::build_configuration(sess, binary, &input);
|
||||||
let outputs = driver::build_output_filenames(
|
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
|
// If the library already exists and is newer than the source
|
||||||
// file, skip compilation and return None.
|
// file, skip compilation and return None.
|
||||||
let mut should_compile = true;
|
let mut should_compile = true;
|
||||||
|
|
|
@ -11,14 +11,14 @@
|
||||||
// Useful conditions
|
// Useful conditions
|
||||||
|
|
||||||
pub use core::path::Path;
|
pub use core::path::Path;
|
||||||
pub use util::PkgId;
|
pub use package_id::PkgId;
|
||||||
|
|
||||||
condition! {
|
condition! {
|
||||||
bad_path: (super::Path, ~str) -> super::Path;
|
bad_path: (super::Path, ~str) -> super::Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
condition! {
|
condition! {
|
||||||
nonexistent_package: (super::PkgId, ~str) -> ();
|
nonexistent_package: (super::PkgId, ~str) -> super::Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
condition! {
|
condition! {
|
||||||
|
@ -30,5 +30,5 @@ condition! {
|
||||||
}
|
}
|
||||||
|
|
||||||
condition! {
|
condition! {
|
||||||
bad_pkg_id: (super::Path, ~str) -> ::util::PkgId;
|
bad_pkg_id: (super::Path, ~str) -> super::PkgId;
|
||||||
}
|
}
|
||||||
|
|
132
src/librustpkg/package_id.rs
Normal file
132
src/librustpkg/package_id.rs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
pub use package_path::{RemotePath, LocalPath, normalize, hash};
|
||||||
|
use extra::semver;
|
||||||
|
use core::prelude::*;
|
||||||
|
use core::result;
|
||||||
|
|
||||||
|
/// 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
src/librustpkg/package_path.rs
Normal file
55
src/librustpkg/package_path.rs
Normal file
|
@ -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()
|
||||||
|
}
|
|
@ -11,9 +11,9 @@
|
||||||
// rustpkg utilities having to do with paths and directories
|
// rustpkg utilities having to do with paths and directories
|
||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
pub use package_path::{RemotePath, LocalPath};
|
||||||
pub use util::{PkgId, RemotePath, LocalPath};
|
pub use package_id::{PkgId, Version};
|
||||||
pub use util::{normalize, OutputType, Main, Lib, Bench, Test};
|
pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install};
|
||||||
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
||||||
use core::os::mkdir_recursive;
|
use core::os::mkdir_recursive;
|
||||||
use core::os;
|
use core::os;
|
||||||
|
@ -32,22 +32,38 @@ pub static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
|
||||||
/// succeeded.
|
/// succeeded.
|
||||||
pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, u_rwx) }
|
pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, u_rwx) }
|
||||||
|
|
||||||
// n.b. So far this only handles local workspaces
|
|
||||||
// n.b. The next three functions ignore the package version right
|
// n.b. The next three functions ignore the package version right
|
||||||
// now. Should fix that.
|
// now. Should fix that.
|
||||||
|
|
||||||
/// True if there's a directory in <workspace> with
|
/// True if there's a directory in <workspace> with
|
||||||
/// pkgid's short name
|
/// pkgid's short name
|
||||||
pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
|
pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
|
||||||
let pkgpath = workspace.push("src").push(pkgid.local_path.to_str());
|
let pkgpath = workspace.push("src").push(pkgid.remote_path.to_str());
|
||||||
os::path_is_dir(&pkgpath)
|
os::path_is_dir(&pkgpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the directory for <pkgid>'s source files in <workspace>.
|
/// Returns a list of possible directories
|
||||||
/// Doesn't check that it exists.
|
/// for <pkgid>'s source files in <workspace>.
|
||||||
pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
/// Doesn't check that any of them exist.
|
||||||
let result = workspace.push("src");
|
/// (for example, try both with and without the version)
|
||||||
result.push(pkgid.local_path.to_str())
|
pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> ~[Path] {
|
||||||
|
let mut results = ~[];
|
||||||
|
let result = workspace.push("src").push(fmt!("%s-%s",
|
||||||
|
pkgid.local_path.to_str(), pkgid.version.to_str()));
|
||||||
|
results.push(result);
|
||||||
|
results.push(workspace.push("src").push_rel(&*pkgid.remote_path));
|
||||||
|
results
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a src for pkgid that does exist -- None if none of them do
|
||||||
|
pub fn first_pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
|
||||||
|
let rs = pkgid_src_in_workspace(pkgid, workspace);
|
||||||
|
for rs.each |p| {
|
||||||
|
if os::path_exists(p) {
|
||||||
|
return Some(copy *p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Figure out what the executable name for <pkgid> in <workspace>'s build
|
/// Figure out what the executable name for <pkgid> in <workspace>'s build
|
||||||
|
@ -55,7 +71,7 @@ pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
||||||
pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
|
pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
|
||||||
let mut result = workspace.push("build");
|
let mut result = workspace.push("build");
|
||||||
// should use a target-specific subdirectory
|
// should use a target-specific subdirectory
|
||||||
result = mk_output_path(Main, pkgid, &result);
|
result = mk_output_path(Main, Build, pkgid, &result);
|
||||||
debug!("built_executable_in_workspace: checking whether %s exists",
|
debug!("built_executable_in_workspace: checking whether %s exists",
|
||||||
result.to_str());
|
result.to_str());
|
||||||
if os::path_exists(&result) {
|
if os::path_exists(&result) {
|
||||||
|
@ -83,7 +99,7 @@ pub fn built_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path>
|
||||||
fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Option<Path> {
|
fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Option<Path> {
|
||||||
let mut result = workspace.push("build");
|
let mut result = workspace.push("build");
|
||||||
// should use a target-specific subdirectory
|
// should use a target-specific subdirectory
|
||||||
result = mk_output_path(what, pkgid, &result);
|
result = mk_output_path(what, Build, pkgid, &result);
|
||||||
debug!("output_in_workspace: checking whether %s exists",
|
debug!("output_in_workspace: checking whether %s exists",
|
||||||
result.to_str());
|
result.to_str());
|
||||||
if os::path_exists(&result) {
|
if os::path_exists(&result) {
|
||||||
|
@ -98,17 +114,39 @@ fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Opt
|
||||||
/// Figure out what the library name for <pkgid> in <workspace>'s build
|
/// Figure out what the library name for <pkgid> in <workspace>'s build
|
||||||
/// directory is, and if the file exists, return it.
|
/// directory is, and if the file exists, return it.
|
||||||
pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
|
pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Path> {
|
||||||
let result = mk_output_path(Lib, pkgid, &workspace.push("build"));
|
// passing in local_path here sounds fishy
|
||||||
debug!("built_library_in_workspace: checking whether %s exists",
|
library_in_workspace(pkgid.local_path.to_str(), pkgid.short_name, Build,
|
||||||
result.to_str());
|
workspace, "build")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does the actual searching stuff
|
||||||
|
pub fn installed_library_in_workspace(short_name: &str, workspace: &Path) -> Option<Path> {
|
||||||
|
library_in_workspace(short_name, short_name, Install, workspace, "lib")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// This doesn't take a PkgId, so we can use it for `extern mod` inference, where we
|
||||||
|
/// don't know the entire package ID.
|
||||||
|
/// `full_name` is used to figure out the directory to search.
|
||||||
|
/// `short_name` is taken as the link name of the library.
|
||||||
|
fn library_in_workspace(full_name: &str, short_name: &str, where: Target,
|
||||||
|
workspace: &Path, prefix: &str) -> Option<Path> {
|
||||||
|
debug!("library_in_workspace: checking whether a library named %s exists",
|
||||||
|
short_name);
|
||||||
|
|
||||||
// We don't know what the hash is, so we have to search through the directory
|
// We don't know what the hash is, so we have to search through the directory
|
||||||
// contents
|
// contents
|
||||||
let dir_contents = os::list_dir(&result.pop());
|
|
||||||
|
let dir_to_search = match where {
|
||||||
|
Build => workspace.push(prefix).push(full_name),
|
||||||
|
Install => workspace.push(prefix)
|
||||||
|
};
|
||||||
|
debug!("Listing directory %s", dir_to_search.to_str());
|
||||||
|
let dir_contents = os::list_dir(&dir_to_search);
|
||||||
debug!("dir has %? entries", dir_contents.len());
|
debug!("dir has %? entries", dir_contents.len());
|
||||||
|
|
||||||
let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, pkgid.short_name);
|
let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, short_name);
|
||||||
let lib_filetype = fmt!("%s%s", pkgid.version.to_str(), os::consts::DLL_SUFFIX);
|
let lib_filetype = os::consts::DLL_SUFFIX;
|
||||||
|
|
||||||
debug!("lib_prefix = %s and lib_filetype = %s", lib_prefix, lib_filetype);
|
debug!("lib_prefix = %s and lib_filetype = %s", lib_prefix, lib_filetype);
|
||||||
|
|
||||||
|
@ -116,9 +154,19 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Pat
|
||||||
for dir_contents.each |&p| {
|
for dir_contents.each |&p| {
|
||||||
let mut which = 0;
|
let mut which = 0;
|
||||||
let mut hash = None;
|
let mut hash = None;
|
||||||
|
let p_path = Path(p);
|
||||||
|
let extension = p_path.filetype();
|
||||||
|
debug!("p = %s, p's extension is %?", p.to_str(), extension);
|
||||||
|
match extension {
|
||||||
|
Some(ref s) if lib_filetype == *s => (),
|
||||||
|
_ => loop
|
||||||
|
}
|
||||||
// Find a filename that matches the pattern: (lib_prefix)-hash-(version)(lib_suffix)
|
// Find a filename that matches the pattern: (lib_prefix)-hash-(version)(lib_suffix)
|
||||||
// and remember what the hash was
|
// and remember what the hash was
|
||||||
for p.each_split_char('-') |piece| {
|
let f_name = match p_path.filename() {
|
||||||
|
Some(s) => s, None => loop
|
||||||
|
};
|
||||||
|
for f_name.each_split_char('-') |piece| {
|
||||||
debug!("a piece = %s", piece);
|
debug!("a piece = %s", piece);
|
||||||
if which == 0 && piece != lib_prefix {
|
if which == 0 && piece != lib_prefix {
|
||||||
break;
|
break;
|
||||||
|
@ -128,13 +176,6 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Pat
|
||||||
}
|
}
|
||||||
else if which == 1 {
|
else if which == 1 {
|
||||||
hash = Some(piece.to_owned());
|
hash = Some(piece.to_owned());
|
||||||
which += 1;
|
|
||||||
}
|
|
||||||
else if which == 2 && piece != lib_filetype {
|
|
||||||
hash = None;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if which == 2 {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -144,20 +185,19 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Pat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if hash.is_some() {
|
if hash.is_some() {
|
||||||
result_filename = Some(p);
|
result_filename = Some(p_path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the filename that matches, which we now know exists
|
// Return the filename that matches, which we now know exists
|
||||||
// (if result_filename != None)
|
// (if result_filename != None)
|
||||||
debug!("result_filename = %?", result_filename);
|
|
||||||
match result_filename {
|
match result_filename {
|
||||||
None => None,
|
None => None,
|
||||||
Some(result_filename) => {
|
Some(result_filename) => {
|
||||||
let result_filename = result.with_filename(result_filename);
|
let absolute_path = dir_to_search.push_rel(&result_filename);
|
||||||
debug!("result_filename = %s", result_filename.to_str());
|
debug!("result_filename = %s", absolute_path.to_str());
|
||||||
Some(result_filename)
|
Some(absolute_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,33 +206,36 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Pat
|
||||||
/// in <workspace>
|
/// in <workspace>
|
||||||
/// As a side effect, creates the bin-dir if it doesn't exist
|
/// As a side effect, creates the bin-dir if it doesn't exist
|
||||||
pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
||||||
target_file_in_workspace(pkgid, workspace, Main)
|
target_file_in_workspace(pkgid, workspace, Main, Install)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Returns the executable that would be installed for <pkgid>
|
/// Returns the executable that would be installed for <pkgid>
|
||||||
/// in <workspace>
|
/// in <workspace>
|
||||||
/// As a side effect, creates the bin-dir if it doesn't exist
|
/// As a side effect, creates the lib-dir if it doesn't exist
|
||||||
pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
||||||
target_file_in_workspace(pkgid, workspace, Lib)
|
target_file_in_workspace(pkgid, workspace, Lib, Install)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the test executable that would be installed for <pkgid>
|
/// Returns the test executable that would be installed for <pkgid>
|
||||||
/// in <workspace>
|
/// in <workspace>
|
||||||
/// note that we *don't* install test executables, so this is just for unit testing
|
/// note that we *don't* install test executables, so this is just for unit testing
|
||||||
pub fn target_test_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
pub fn target_test_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
||||||
target_file_in_workspace(pkgid, workspace, Test)
|
target_file_in_workspace(pkgid, workspace, Test, Install)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the bench executable that would be installed for <pkgid>
|
/// Returns the bench executable that would be installed for <pkgid>
|
||||||
/// in <workspace>
|
/// in <workspace>
|
||||||
/// note that we *don't* install bench executables, so this is just for unit testing
|
/// note that we *don't* install bench executables, so this is just for unit testing
|
||||||
pub fn target_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
pub fn target_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
||||||
target_file_in_workspace(pkgid, workspace, Bench)
|
target_file_in_workspace(pkgid, workspace, Bench, Install)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns the path that pkgid `pkgid` would have if placed `where`
|
||||||
|
/// in `workspace`
|
||||||
fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
|
fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
|
||||||
what: OutputType) -> Path {
|
what: OutputType, where: Target) -> Path {
|
||||||
use conditions::bad_path::cond;
|
use conditions::bad_path::cond;
|
||||||
|
|
||||||
let subdir = match what {
|
let subdir = match what {
|
||||||
|
@ -202,7 +245,7 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
|
||||||
if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) {
|
if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) {
|
||||||
cond.raise((copy result, fmt!("I couldn't create the %s dir", subdir)));
|
cond.raise((copy result, fmt!("I couldn't create the %s dir", subdir)));
|
||||||
}
|
}
|
||||||
mk_output_path(what, pkgid, &result)
|
mk_output_path(what, where, pkgid, &result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the directory for <pkgid>'s build artifacts in <workspace>.
|
/// Return the directory for <pkgid>'s build artifacts in <workspace>.
|
||||||
|
@ -224,15 +267,21 @@ pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
|
||||||
|
|
||||||
/// Return the output file for a given directory name,
|
/// Return the output file for a given directory name,
|
||||||
/// given whether we're building a library and whether we're building tests
|
/// given whether we're building a library and whether we're building tests
|
||||||
pub fn mk_output_path(what: OutputType, pkg_id: &PkgId, workspace: &Path) -> Path {
|
pub fn mk_output_path(what: OutputType, where: Target,
|
||||||
|
pkg_id: &PkgId, workspace: &Path) -> Path {
|
||||||
let short_name_with_version = pkg_id.short_name_with_version();
|
let short_name_with_version = pkg_id.short_name_with_version();
|
||||||
// Not local_path.dir_path()! For package foo/bar/blat/, we want
|
// Not local_path.dir_path()! For package foo/bar/blat/, we want
|
||||||
// the executable blat-0.5 to live under blat/
|
// the executable blat-0.5 to live under blat/
|
||||||
let dir = workspace.push_rel(&*pkg_id.local_path);
|
let dir = match where {
|
||||||
debug!("mk_output_path: short_name = %s, path = %s",
|
// If we're installing, it just goes under <workspace>...
|
||||||
|
Install => copy *workspace, // bad copy, but I just couldn't make the borrow checker happy
|
||||||
|
// and if we're just building, it goes in a package-specific subdir
|
||||||
|
Build => workspace.push_rel(&*pkg_id.local_path)
|
||||||
|
};
|
||||||
|
debug!("[%?:%?] mk_output_path: short_name = %s, path = %s", what, where,
|
||||||
if what == Lib { copy short_name_with_version } else { copy pkg_id.short_name },
|
if what == Lib { copy short_name_with_version } else { copy pkg_id.short_name },
|
||||||
dir.to_str());
|
dir.to_str());
|
||||||
let output_path = match what {
|
let mut output_path = match what {
|
||||||
// this code is duplicated from elsewhere; fix this
|
// this code is duplicated from elsewhere; fix this
|
||||||
Lib => dir.push(os::dll_filename(short_name_with_version)),
|
Lib => dir.push(os::dll_filename(short_name_with_version)),
|
||||||
// executable names *aren't* versioned
|
// executable names *aren't* versioned
|
||||||
|
@ -244,6 +293,9 @@ pub fn mk_output_path(what: OutputType, pkg_id: &PkgId, workspace: &Path) -> Pat
|
||||||
}
|
}
|
||||||
os::EXE_SUFFIX))
|
os::EXE_SUFFIX))
|
||||||
};
|
};
|
||||||
|
if !output_path.is_absolute() {
|
||||||
|
output_path = os::getcwd().push_rel(&output_path).normalize();
|
||||||
|
}
|
||||||
debug!("mk_output_path: returning %s", output_path.to_str());
|
debug!("mk_output_path: returning %s", output_path.to_str());
|
||||||
output_path
|
output_path
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,15 +35,21 @@ use rustc::metadata::filesearch;
|
||||||
use extra::{getopts};
|
use extra::{getopts};
|
||||||
use syntax::{ast, diagnostic};
|
use syntax::{ast, diagnostic};
|
||||||
use util::*;
|
use util::*;
|
||||||
use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, u_rwx};
|
use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, first_pkgid_src_in_workspace};
|
||||||
|
use path_util::u_rwx;
|
||||||
use path_util::{built_executable_in_workspace, built_library_in_workspace};
|
use path_util::{built_executable_in_workspace, built_library_in_workspace};
|
||||||
use path_util::{target_executable_in_workspace, target_library_in_workspace};
|
use path_util::{target_executable_in_workspace, target_library_in_workspace};
|
||||||
use workspace::pkg_parent_workspaces;
|
use workspace::pkg_parent_workspaces;
|
||||||
use context::Ctx;
|
use context::Ctx;
|
||||||
|
use package_id::PkgId;
|
||||||
|
|
||||||
mod conditions;
|
mod conditions;
|
||||||
mod context;
|
mod context;
|
||||||
|
mod package_id;
|
||||||
|
mod package_path;
|
||||||
mod path_util;
|
mod path_util;
|
||||||
|
mod search;
|
||||||
|
mod target;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
mod util;
|
mod util;
|
||||||
|
@ -99,8 +105,7 @@ impl<'self> PkgScript<'self> {
|
||||||
let input = driver::file_input(script);
|
let input = driver::file_input(script);
|
||||||
let sess = driver::build_session(options, diagnostic::emit);
|
let sess = driver::build_session(options, diagnostic::emit);
|
||||||
let cfg = driver::build_configuration(sess, binary, &input);
|
let cfg = driver::build_configuration(sess, binary, &input);
|
||||||
let (crate, _) = driver::compile_upto(sess, copy cfg, &input,
|
let (crate, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_parse, None);
|
||||||
driver::cu_parse, None);
|
|
||||||
let work_dir = build_pkg_id_in_workspace(id, workspace);
|
let work_dir = build_pkg_id_in_workspace(id, workspace);
|
||||||
|
|
||||||
debug!("Returning package script with id %?", id);
|
debug!("Returning package script with id %?", id);
|
||||||
|
@ -134,11 +139,13 @@ impl<'self> PkgScript<'self> {
|
||||||
let root = r.pop().pop().pop().pop(); // :-\
|
let root = r.pop().pop().pop().pop(); // :-\
|
||||||
debug!("Root is %s, calling compile_rest", root.to_str());
|
debug!("Root is %s, calling compile_rest", root.to_str());
|
||||||
let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
|
let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
|
||||||
util::compile_crate_from_input(&self.input, self.id,
|
let binary = @copy os::args()[0];
|
||||||
Some(copy self.build_dir),
|
util::compile_crate_from_input(&self.input,
|
||||||
sess, Some(crate),
|
&self.build_dir,
|
||||||
&exe, @copy os::args()[0],
|
sess,
|
||||||
driver::cu_everything);
|
crate,
|
||||||
|
driver::build_configuration(sess,
|
||||||
|
binary, &self.input));
|
||||||
debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what);
|
debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what);
|
||||||
let status = run::process_status(exe.to_str(), [root.to_str(), what]);
|
let status = run::process_status(exe.to_str(), [root.to_str(), what]);
|
||||||
if status != 0 {
|
if status != 0 {
|
||||||
|
@ -170,9 +177,9 @@ impl<'self> PkgScript<'self> {
|
||||||
|
|
||||||
impl Ctx {
|
impl Ctx {
|
||||||
|
|
||||||
fn run(&self, cmd: ~str, args: ~[~str]) {
|
fn run(&self, cmd: &str, args: ~[~str]) {
|
||||||
match cmd {
|
match cmd {
|
||||||
~"build" => {
|
"build" => {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return usage::build();
|
return usage::build();
|
||||||
}
|
}
|
||||||
|
@ -183,7 +190,7 @@ impl Ctx {
|
||||||
self.build(workspace, &pkgid);
|
self.build(workspace, &pkgid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~"clean" => {
|
"clean" => {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return usage::build();
|
return usage::build();
|
||||||
}
|
}
|
||||||
|
@ -193,17 +200,17 @@ impl Ctx {
|
||||||
let cwd = os::getcwd();
|
let cwd = os::getcwd();
|
||||||
self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd
|
self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd
|
||||||
}
|
}
|
||||||
~"do" => {
|
"do" => {
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
return usage::do_cmd();
|
return usage::do_cmd();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.do_cmd(copy args[0], copy args[1]);
|
self.do_cmd(copy args[0], copy args[1]);
|
||||||
}
|
}
|
||||||
~"info" => {
|
"info" => {
|
||||||
self.info();
|
self.info();
|
||||||
}
|
}
|
||||||
~"install" => {
|
"install" => {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return usage::install();
|
return usage::install();
|
||||||
}
|
}
|
||||||
|
@ -215,24 +222,24 @@ impl Ctx {
|
||||||
self.install(workspace, &pkgid);
|
self.install(workspace, &pkgid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~"prefer" => {
|
"prefer" => {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return usage::uninstall();
|
return usage::uninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.prefer(args[0], None);
|
self.prefer(args[0], None);
|
||||||
}
|
}
|
||||||
~"test" => {
|
"test" => {
|
||||||
self.test();
|
self.test();
|
||||||
}
|
}
|
||||||
~"uninstall" => {
|
"uninstall" => {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return usage::uninstall();
|
return usage::uninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.uninstall(args[0], None);
|
self.uninstall(args[0], None);
|
||||||
}
|
}
|
||||||
~"unprefer" => {
|
"unprefer" => {
|
||||||
if args.len() < 1 {
|
if args.len() < 1 {
|
||||||
return usage::uninstall();
|
return usage::uninstall();
|
||||||
}
|
}
|
||||||
|
@ -249,7 +256,7 @@ impl Ctx {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(&self, workspace: &Path, pkgid: &PkgId) {
|
fn build(&self, workspace: &Path, pkgid: &PkgId) {
|
||||||
let src_dir = pkgid_src_in_workspace(pkgid, workspace);
|
let src_dir = first_pkgid_src_in_workspace(pkgid, workspace);
|
||||||
let build_dir = build_pkg_id_in_workspace(pkgid, workspace);
|
let build_dir = build_pkg_id_in_workspace(pkgid, workspace);
|
||||||
debug!("Destination dir = %s", build_dir.to_str());
|
debug!("Destination dir = %s", build_dir.to_str());
|
||||||
|
|
||||||
|
@ -260,8 +267,8 @@ impl Ctx {
|
||||||
// Is there custom build logic? If so, use it
|
// Is there custom build logic? If so, use it
|
||||||
let pkg_src_dir = src_dir;
|
let pkg_src_dir = src_dir;
|
||||||
let mut custom = false;
|
let mut custom = false;
|
||||||
debug!("Package source directory = %s", pkg_src_dir.to_str());
|
debug!("Package source directory = %?", pkg_src_dir);
|
||||||
let cfgs = match src.package_script_option(&pkg_src_dir) {
|
let cfgs = match pkg_src_dir.chain_ref(|p| src.package_script_option(p)) {
|
||||||
Some(package_script_path) => {
|
Some(package_script_path) => {
|
||||||
let pscript = PkgScript::parse(package_script_path,
|
let pscript = PkgScript::parse(package_script_path,
|
||||||
workspace,
|
workspace,
|
||||||
|
@ -290,7 +297,7 @@ impl Ctx {
|
||||||
// Find crates inside the workspace
|
// Find crates inside the workspace
|
||||||
src.find_crates();
|
src.find_crates();
|
||||||
// Build it!
|
// Build it!
|
||||||
src.build(&build_dir, cfgs, self.sysroot_opt);
|
src.build(self, build_dir, cfgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +359,7 @@ impl Ctx {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefer(&self, _id: &str, _vers: Option<~str>) {
|
fn prefer(&self, _id: &str, _vers: Option<~str>) {
|
||||||
fail!(~"prefer not yet implemented");
|
fail!("prefer not yet implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test(&self) {
|
fn test(&self) {
|
||||||
|
@ -522,21 +529,20 @@ impl PkgSrc {
|
||||||
fn check_dir(&self) -> Path {
|
fn check_dir(&self) -> Path {
|
||||||
use conditions::nonexistent_package::cond;
|
use conditions::nonexistent_package::cond;
|
||||||
|
|
||||||
debug!("Pushing onto root: %s | %s", self.id.to_str(),
|
debug!("Pushing onto root: %s | %s", self.id.remote_path.to_str(),
|
||||||
self.root.to_str());
|
self.root.to_str());
|
||||||
|
let dir;
|
||||||
let mut dir = self.root.push("src");
|
let dirs = pkgid_src_in_workspace(&self.id, &self.root);
|
||||||
dir = dir.push(self.id.to_str()); // ?? Should this use the version number?
|
debug!("Checking dirs: %?", dirs);
|
||||||
|
let path = dirs.find(|d| os::path_exists(d));
|
||||||
debug!("Checking dir: %s", dir.to_str());
|
match path {
|
||||||
|
Some(d) => dir = d,
|
||||||
if !os::path_exists(&dir) {
|
None => dir = match self.fetch_git() {
|
||||||
if !self.fetch_git() {
|
None => cond.raise((copy self.id, ~"supplied path for package dir does not \
|
||||||
cond.raise((copy self.id, ~"supplied path for package dir does not \
|
exist, and couldn't interpret it as a URL fragment")),
|
||||||
exist, and couldn't interpret it as a URL fragment"));
|
Some(d) => d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !os::path_is_dir(&dir) {
|
if !os::path_is_dir(&dir) {
|
||||||
cond.raise((copy self.id, ~"supplied path for package dir is a \
|
cond.raise((copy self.id, ~"supplied path for package dir is a \
|
||||||
non-directory"));
|
non-directory"));
|
||||||
|
@ -546,10 +552,10 @@ impl PkgSrc {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try interpreting self's package id as a remote package, and try
|
/// Try interpreting self's package id as a remote package, and try
|
||||||
/// fetching it and caching it in a local directory. If that didn't
|
/// fetching it and caching it in a local directory. Return the cached directory
|
||||||
/// work, return false.
|
/// if this was successful, None otherwise
|
||||||
/// (right now we only support git)
|
/// (right now we only support git)
|
||||||
fn fetch_git(&self) -> bool {
|
fn fetch_git(&self) -> Option<Path> {
|
||||||
|
|
||||||
let mut local = self.root.push("src");
|
let mut local = self.root.push("src");
|
||||||
local = local.push(self.id.to_str());
|
local = local.push(self.id.to_str());
|
||||||
|
@ -561,9 +567,11 @@ impl PkgSrc {
|
||||||
|
|
||||||
if run::process_output("git", [~"clone", copy url, local.to_str()]).status != 0 {
|
if run::process_output("git", [~"clone", copy url, local.to_str()]).status != 0 {
|
||||||
util::note(fmt!("fetching %s failed: can't clone repository", url));
|
util::note(fmt!("fetching %s failed: can't clone repository", url));
|
||||||
return false;
|
None
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Some(local)
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -655,7 +663,7 @@ impl PkgSrc {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_crates(&self,
|
fn build_crates(&self,
|
||||||
maybe_sysroot: Option<@Path>,
|
ctx: &Ctx,
|
||||||
dst_dir: &Path,
|
dst_dir: &Path,
|
||||||
src_dir: &Path,
|
src_dir: &Path,
|
||||||
crates: &[Crate],
|
crates: &[Crate],
|
||||||
|
@ -666,11 +674,14 @@ impl PkgSrc {
|
||||||
util::note(fmt!("build_crates: compiling %s", path.to_str()));
|
util::note(fmt!("build_crates: compiling %s", path.to_str()));
|
||||||
util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str()));
|
util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str()));
|
||||||
|
|
||||||
let result = util::compile_crate(maybe_sysroot, &self.id, path,
|
let result = util::compile_crate(ctx,
|
||||||
|
&self.id,
|
||||||
|
path,
|
||||||
dst_dir,
|
dst_dir,
|
||||||
crate.flags,
|
crate.flags,
|
||||||
crate.cfgs + cfgs,
|
crate.cfgs + cfgs,
|
||||||
false, what);
|
false,
|
||||||
|
what);
|
||||||
if !result {
|
if !result {
|
||||||
build_err::cond.raise(fmt!("build failure on %s",
|
build_err::cond.raise(fmt!("build failure on %s",
|
||||||
path.to_str()));
|
path.to_str()));
|
||||||
|
@ -680,15 +691,15 @@ impl PkgSrc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(&self, dst_dir: &Path, cfgs: ~[~str], maybe_sysroot: Option<@Path>) {
|
fn build(&self, ctx: &Ctx, dst_dir: Path, cfgs: ~[~str]) {
|
||||||
let dir = self.check_dir();
|
let dir = self.check_dir();
|
||||||
debug!("Building libs");
|
debug!("Building libs");
|
||||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.libs, cfgs, Lib);
|
self.build_crates(ctx, &dst_dir, &dir, self.libs, cfgs, Lib);
|
||||||
debug!("Building mains");
|
debug!("Building mains");
|
||||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.mains, cfgs, Main);
|
self.build_crates(ctx, &dst_dir, &dir, self.mains, cfgs, Main);
|
||||||
debug!("Building tests");
|
debug!("Building tests");
|
||||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.tests, cfgs, Test);
|
self.build_crates(ctx, &dst_dir, &dir, self.tests, cfgs, Test);
|
||||||
debug!("Building benches");
|
debug!("Building benches");
|
||||||
self.build_crates(maybe_sysroot, dst_dir, &dir, self.benchs, cfgs, Bench);
|
self.build_crates(ctx, &dst_dir, &dir, self.benchs, cfgs, Bench);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/librustpkg/search.rs
Normal file
25
src/librustpkg/search.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use path_util::installed_library_in_workspace;
|
||||||
|
use core::prelude::*;
|
||||||
|
|
||||||
|
/// If a library with path `p` matching pkg_id's name exists under sroot_opt,
|
||||||
|
/// return Some(p). Return None if there's no such path or if sroot_opt is None.
|
||||||
|
pub fn find_library_in_search_path(sroot_opt: Option<@Path>, short_name: &str) -> Option<Path> {
|
||||||
|
match sroot_opt {
|
||||||
|
Some(sroot) => {
|
||||||
|
debug!("Will search for a library with short name %s in \
|
||||||
|
%s", short_name, (sroot.push("lib")).to_str());
|
||||||
|
installed_library_in_workspace(short_name, sroot)
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
23
src/librustpkg/target.rs
Normal file
23
src/librustpkg/target.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
|
||||||
|
// Data types that express build artifacts
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
pub enum OutputType { Main, Lib, Bench, Test }
|
||||||
|
|
||||||
|
#[deriving(Eq)]
|
||||||
|
pub enum Target {
|
||||||
|
// In-place build
|
||||||
|
Build,
|
||||||
|
// Install to bin/ or lib/ dir
|
||||||
|
Install
|
||||||
|
}
|
|
@ -17,10 +17,11 @@ use core::os;
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
use core::result;
|
use core::result;
|
||||||
use extra::tempfile::mkdtemp;
|
use extra::tempfile::mkdtemp;
|
||||||
use util::{PkgId, default_version};
|
use package_path::*;
|
||||||
|
use package_id::{PkgId, default_version};
|
||||||
use path_util::{target_executable_in_workspace, target_library_in_workspace,
|
use path_util::{target_executable_in_workspace, target_library_in_workspace,
|
||||||
target_test_in_workspace, target_bench_in_workspace,
|
target_test_in_workspace, target_bench_in_workspace,
|
||||||
make_dir_rwx, u_rwx, RemotePath, LocalPath, normalize,
|
make_dir_rwx, u_rwx,
|
||||||
built_bench_in_workspace, built_test_in_workspace};
|
built_bench_in_workspace, built_test_in_workspace};
|
||||||
|
|
||||||
fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
|
fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx {
|
||||||
|
@ -52,7 +53,7 @@ fn remote_pkg() -> PkgId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeFile(file_path: &Path, contents: ~str) {
|
fn writeFile(file_path: &Path, contents: &str) {
|
||||||
let out: @io::Writer =
|
let out: @io::Writer =
|
||||||
result::get(&io::file_writer(file_path,
|
result::get(&io::file_writer(file_path,
|
||||||
[io::Create, io::Truncate]));
|
[io::Create, io::Truncate]));
|
||||||
|
@ -64,15 +65,17 @@ fn mk_temp_workspace(short_name: &LocalPath) -> Path {
|
||||||
// include version number in directory name
|
// include version number in directory name
|
||||||
let package_dir = workspace.push("src").push(fmt!("%s-0.1", short_name.to_str()));
|
let package_dir = workspace.push("src").push(fmt!("%s-0.1", short_name.to_str()));
|
||||||
assert!(os::mkdir_recursive(&package_dir, u_rwx));
|
assert!(os::mkdir_recursive(&package_dir, u_rwx));
|
||||||
|
debug!("Created %s and does it exist? %?", package_dir.to_str(),
|
||||||
|
os::path_is_dir(&package_dir));
|
||||||
// Create main, lib, test, and bench files
|
// Create main, lib, test, and bench files
|
||||||
writeFile(&package_dir.push("main.rs"),
|
writeFile(&package_dir.push("main.rs"),
|
||||||
~"fn main() { let _x = (); }");
|
"fn main() { let _x = (); }");
|
||||||
writeFile(&package_dir.push("lib.rs"),
|
writeFile(&package_dir.push("lib.rs"),
|
||||||
~"pub fn f() { let _x = (); }");
|
"pub fn f() { let _x = (); }");
|
||||||
writeFile(&package_dir.push("test.rs"),
|
writeFile(&package_dir.push("test.rs"),
|
||||||
~"#[test] pub fn f() { (); }");
|
"#[test] pub fn f() { (); }");
|
||||||
writeFile(&package_dir.push("bench.rs"),
|
writeFile(&package_dir.push("bench.rs"),
|
||||||
~"#[bench] pub fn f() { (); }");
|
"#[bench] pub fn f() { (); }");
|
||||||
workspace
|
workspace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +114,8 @@ fn test_make_dir_rwx() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_install_valid() {
|
fn test_install_valid() {
|
||||||
|
use path_util::installed_library_in_workspace;
|
||||||
|
|
||||||
let sysroot = test_sysroot();
|
let sysroot = test_sysroot();
|
||||||
debug!("sysroot = %s", sysroot.to_str());
|
debug!("sysroot = %s", sysroot.to_str());
|
||||||
let ctxt = fake_ctxt(Some(@sysroot));
|
let ctxt = fake_ctxt(Some(@sysroot));
|
||||||
|
@ -123,10 +128,12 @@ fn test_install_valid() {
|
||||||
debug!("exec = %s", exec.to_str());
|
debug!("exec = %s", exec.to_str());
|
||||||
assert!(os::path_exists(&exec));
|
assert!(os::path_exists(&exec));
|
||||||
assert!(is_rwx(&exec));
|
assert!(is_rwx(&exec));
|
||||||
let lib = target_library_in_workspace(&temp_pkg_id, &temp_workspace);
|
|
||||||
debug!("lib = %s", lib.to_str());
|
let lib = installed_library_in_workspace(temp_pkg_id.short_name, &temp_workspace);
|
||||||
assert!(os::path_exists(&lib));
|
debug!("lib = %?", lib);
|
||||||
assert!(is_rwx(&lib));
|
assert!(lib.map_default(false, |l| os::path_exists(l)));
|
||||||
|
assert!(lib.map_default(false, |l| is_rwx(l)));
|
||||||
|
|
||||||
// And that the test and bench executables aren't installed
|
// And that the test and bench executables aren't installed
|
||||||
assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, &temp_workspace)));
|
assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, &temp_workspace)));
|
||||||
let bench = target_bench_in_workspace(&temp_pkg_id, &temp_workspace);
|
let bench = target_bench_in_workspace(&temp_pkg_id, &temp_workspace);
|
||||||
|
@ -149,6 +156,7 @@ fn test_install_invalid() {
|
||||||
}).in {
|
}).in {
|
||||||
do cond.trap(|_| {
|
do cond.trap(|_| {
|
||||||
error_occurred = true;
|
error_occurred = true;
|
||||||
|
copy temp_workspace
|
||||||
}).in {
|
}).in {
|
||||||
ctxt.install(&temp_workspace, &pkgid);
|
ctxt.install(&temp_workspace, &pkgid);
|
||||||
}
|
}
|
||||||
|
@ -174,10 +182,11 @@ fn test_install_url() {
|
||||||
debug!("lib = %s", lib.to_str());
|
debug!("lib = %s", lib.to_str());
|
||||||
assert!(os::path_exists(&lib));
|
assert!(os::path_exists(&lib));
|
||||||
assert!(is_rwx(&lib));
|
assert!(is_rwx(&lib));
|
||||||
let built_test = built_test_in_workspace(&temp_pkg_id, &workspace).expect("test_install_url");
|
let built_test = built_test_in_workspace(&temp_pkg_id,
|
||||||
|
&workspace).expect("test_install_url: built test should exist");
|
||||||
assert!(os::path_exists(&built_test));
|
assert!(os::path_exists(&built_test));
|
||||||
let built_bench = built_bench_in_workspace(&temp_pkg_id,
|
let built_bench = built_bench_in_workspace(&temp_pkg_id,
|
||||||
&workspace).expect("test_install_url");
|
&workspace).expect("test_install_url: built bench should exist");
|
||||||
assert!(os::path_exists(&built_bench));
|
assert!(os::path_exists(&built_bench));
|
||||||
// And that the test and bench executables aren't installed
|
// And that the test and bench executables aren't installed
|
||||||
let test = target_test_in_workspace(&temp_pkg_id, &workspace);
|
let test = target_test_in_workspace(&temp_pkg_id, &workspace);
|
||||||
|
|
|
@ -13,9 +13,12 @@ The test runner should check that, after `rustpkg install external crate`
|
||||||
with RUST_PATH undefined in the environment
|
with RUST_PATH undefined in the environment
|
||||||
and with `rustpkg install deeply/nested/path/foo` already
|
and with `rustpkg install deeply/nested/path/foo` already
|
||||||
executed:
|
executed:
|
||||||
* ./.rust/external_crate exists and is an executable
|
* ../bin/external_crate exists and is an executable
|
||||||
|
|
||||||
|
tjc: Also want a test like this where foo is an external URL,
|
||||||
|
which requires the `extern mod` changes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern mod foo; // refers to deeply/nested/path/foo
|
extern mod foo;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
11
src/librustpkg/testsuite/pass/src/foo/lib.rs
Normal file
11
src/librustpkg/testsuite/pass/src/foo/lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
fn f() {}
|
|
@ -9,23 +9,28 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
use core::*;
|
use core::{io, libc, os, result, str};
|
||||||
use core::cmp::Ord;
|
|
||||||
use core::hash::Streaming;
|
|
||||||
use core::rt::io::Writer;
|
|
||||||
use rustc::driver::{driver, session};
|
use rustc::driver::{driver, session};
|
||||||
use rustc::metadata::filesearch;
|
use rustc::metadata::filesearch;
|
||||||
use extra::getopts::groups::getopts;
|
use extra::getopts::groups::getopts;
|
||||||
use extra::semver;
|
|
||||||
use extra::term;
|
use extra::term;
|
||||||
|
#[cfg(not(test))]
|
||||||
|
use extra::getopts;
|
||||||
use syntax::ast_util::*;
|
use syntax::ast_util::*;
|
||||||
use syntax::codemap::{dummy_sp, spanned, dummy_spanned};
|
use syntax::codemap::{dummy_sp, spanned};
|
||||||
|
use syntax::codemap::dummy_spanned;
|
||||||
use syntax::ext::base::ExtCtxt;
|
use syntax::ext::base::ExtCtxt;
|
||||||
use syntax::{ast, attr, codemap, diagnostic, fold};
|
use syntax::{ast, attr, codemap, diagnostic, fold};
|
||||||
use syntax::ast::{meta_name_value, meta_list};
|
use syntax::ast::{meta_name_value, meta_list};
|
||||||
use syntax::attr::{mk_attr};
|
use syntax::attr::{mk_attr};
|
||||||
use rustc::back::link::output_type_exe;
|
use rustc::back::link::output_type_exe;
|
||||||
|
use rustc::driver::driver::compile_upto;
|
||||||
use rustc::driver::session::{lib_crate, bin_crate};
|
use rustc::driver::session::{lib_crate, bin_crate};
|
||||||
|
use context::Ctx;
|
||||||
|
use package_id::PkgId;
|
||||||
|
use path_util::target_library_in_workspace;
|
||||||
|
use search::find_library_in_search_path;
|
||||||
|
pub use target::{OutputType, Main, Lib, Bench, Test};
|
||||||
|
|
||||||
static Commands: &'static [&'static str] =
|
static Commands: &'static [&'static str] =
|
||||||
&["build", "clean", "do", "info", "install", "prefer", "test", "uninstall",
|
&["build", "clean", "do", "info", "install", "prefer", "test", "uninstall",
|
||||||
|
@ -34,119 +39,6 @@ static Commands: &'static [&'static str] =
|
||||||
|
|
||||||
pub type ExitCode = int; // For now
|
pub type ExitCode = int; // For now
|
||||||
|
|
||||||
/// 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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Eq)]
|
|
||||||
pub enum OutputType { Main, Lib, Bench, Test }
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PkgId {
|
|
||||||
pub 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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub 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())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub 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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Pkg {
|
pub struct Pkg {
|
||||||
id: PkgId,
|
id: PkgId,
|
||||||
bins: ~[~str],
|
bins: ~[~str],
|
||||||
|
@ -264,13 +156,6 @@ pub fn ready_crate(sess: session::Session,
|
||||||
@fold.fold_crate(crate)
|
@fold.fold_crate(crate)
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn need_dir(s: &Path) {
|
pub fn need_dir(s: &Path) {
|
||||||
if !os::path_is_dir(s) && !os::make_dir(s, 493_i32) {
|
if !os::path_is_dir(s) && !os::make_dir(s, 493_i32) {
|
||||||
fail!("can't create dir: %s", s.to_str());
|
fail!("can't create dir: %s", s.to_str());
|
||||||
|
@ -316,15 +201,8 @@ pub fn error(msg: ~str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(data: ~str) -> ~str {
|
|
||||||
let mut hasher = hash::default_state();
|
|
||||||
let buffer = str::as_bytes_slice(data);
|
|
||||||
hasher.write(buffer);
|
|
||||||
hasher.result_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME (#4432): Use workcache to only compile when needed
|
// FIXME (#4432): Use workcache to only compile when needed
|
||||||
pub fn compile_input(sysroot: Option<@Path>,
|
pub fn compile_input(ctxt: &Ctx,
|
||||||
pkg_id: &PkgId,
|
pkg_id: &PkgId,
|
||||||
in_file: &Path,
|
in_file: &Path,
|
||||||
out_dir: &Path,
|
out_dir: &Path,
|
||||||
|
@ -333,6 +211,8 @@ pub fn compile_input(sysroot: Option<@Path>,
|
||||||
opt: bool,
|
opt: bool,
|
||||||
what: OutputType) -> bool {
|
what: OutputType) -> bool {
|
||||||
|
|
||||||
|
let workspace = out_dir.pop().pop();
|
||||||
|
|
||||||
assert!(in_file.components.len() > 1);
|
assert!(in_file.components.len() > 1);
|
||||||
let input = driver::file_input(copy *in_file);
|
let input = driver::file_input(copy *in_file);
|
||||||
debug!("compile_input: %s / %?", in_file.to_str(), what);
|
debug!("compile_input: %s / %?", in_file.to_str(), what);
|
||||||
|
@ -340,23 +220,10 @@ pub fn compile_input(sysroot: Option<@Path>,
|
||||||
// not sure if we should support anything else
|
// not sure if we should support anything else
|
||||||
|
|
||||||
let binary = @(copy os::args()[0]);
|
let binary = @(copy os::args()[0]);
|
||||||
let building_library = what == Lib;
|
|
||||||
|
|
||||||
let out_file = if building_library {
|
|
||||||
out_dir.push(os::dll_filename(pkg_id.short_name))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out_dir.push(pkg_id.short_name + match what {
|
|
||||||
Test => ~"test", Bench => ~"bench", Main | Lib => ~""
|
|
||||||
} + os::EXE_SUFFIX)
|
|
||||||
};
|
|
||||||
|
|
||||||
debug!("compiling %s into %s",
|
|
||||||
in_file.to_str(),
|
|
||||||
out_file.to_str());
|
|
||||||
debug!("flags: %s", str::connect(flags, " "));
|
debug!("flags: %s", str::connect(flags, " "));
|
||||||
debug!("cfgs: %s", str::connect(cfgs, " "));
|
debug!("cfgs: %s", str::connect(cfgs, " "));
|
||||||
debug!("compile_input's sysroot = %?", sysroot);
|
debug!("compile_input's sysroot = %?", ctxt.sysroot_opt);
|
||||||
|
|
||||||
let crate_type = match what {
|
let crate_type = match what {
|
||||||
Lib => lib_crate,
|
Lib => lib_crate,
|
||||||
|
@ -372,28 +239,62 @@ pub fn compile_input(sysroot: Option<@Path>,
|
||||||
+ flags
|
+ flags
|
||||||
+ cfgs.flat_map(|&c| { ~[~"--cfg", c] }),
|
+ cfgs.flat_map(|&c| { ~[~"--cfg", c] }),
|
||||||
driver::optgroups()).get();
|
driver::optgroups()).get();
|
||||||
let mut options = session::options {
|
let options = @session::options {
|
||||||
crate_type: crate_type,
|
crate_type: crate_type,
|
||||||
optimize: if opt { session::Aggressive } else { session::No },
|
optimize: if opt { session::Aggressive } else { session::No },
|
||||||
test: what == Test || what == Bench,
|
test: what == Test || what == Bench,
|
||||||
maybe_sysroot: sysroot,
|
maybe_sysroot: ctxt.sysroot_opt,
|
||||||
addl_lib_search_paths: ~[copy *out_dir],
|
addl_lib_search_paths: @mut ~[copy *out_dir],
|
||||||
// output_type should be conditional
|
// output_type should be conditional
|
||||||
output_type: output_type_exe, // Use this to get a library? That's weird
|
output_type: output_type_exe, // Use this to get a library? That's weird
|
||||||
.. copy *driver::build_session_options(binary, &matches, diagnostic::emit)
|
.. copy *driver::build_session_options(binary, &matches, diagnostic::emit)
|
||||||
};
|
};
|
||||||
|
|
||||||
for cfgs.each |&cfg| {
|
let addl_lib_search_paths = @mut options.addl_lib_search_paths;
|
||||||
options.cfg.push(attr::mk_word_item(@cfg));
|
|
||||||
}
|
|
||||||
|
|
||||||
let sess = driver::build_session(@options, diagnostic::emit);
|
let sess = driver::build_session(options, diagnostic::emit);
|
||||||
|
|
||||||
|
// Infer dependencies that rustpkg needs to build, by scanning for
|
||||||
|
// `extern mod` directives.
|
||||||
|
let cfg = driver::build_configuration(sess, binary, &input);
|
||||||
|
let (crate_opt, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_expand, None);
|
||||||
|
|
||||||
|
let mut crate = match crate_opt {
|
||||||
|
Some(c) => c,
|
||||||
|
None => fail!("compile_input expected...")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Not really right. Should search other workspaces too, and the installed
|
||||||
|
// database (which doesn't exist yet)
|
||||||
|
find_and_install_dependencies(ctxt, sess, &workspace, crate,
|
||||||
|
|p| {
|
||||||
|
debug!("a dependency: %s", p.to_str());
|
||||||
|
// Pass the directory containing a dependency
|
||||||
|
// as an additional lib search path
|
||||||
|
addl_lib_search_paths.push(p);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inject the link attributes so we get the right package name and version
|
||||||
|
if attr::find_linkage_metas(crate.node.attrs).is_empty() {
|
||||||
|
let short_name_to_use = match what {
|
||||||
|
Test => fmt!("%stest", pkg_id.short_name),
|
||||||
|
Bench => fmt!("%sbench", pkg_id.short_name),
|
||||||
|
_ => copy pkg_id.short_name
|
||||||
|
};
|
||||||
|
debug!("Injecting link name: %s", short_name_to_use);
|
||||||
|
crate = @codemap::respan(crate.span, ast::crate_ {
|
||||||
|
attrs: ~[mk_attr(@dummy_spanned(
|
||||||
|
meta_list(@~"link",
|
||||||
|
~[@dummy_spanned(meta_name_value(@~"name",
|
||||||
|
mk_string_lit(@short_name_to_use))),
|
||||||
|
@dummy_spanned(meta_name_value(@~"vers",
|
||||||
|
mk_string_lit(@(copy pkg_id.version.to_str()))))])))],
|
||||||
|
..copy crate.node});
|
||||||
|
}
|
||||||
|
|
||||||
debug!("calling compile_crate_from_input, out_dir = %s,
|
debug!("calling compile_crate_from_input, out_dir = %s,
|
||||||
building_library = %?", out_dir.to_str(), sess.building_library);
|
building_library = %?", out_dir.to_str(), sess.building_library);
|
||||||
let _ = compile_crate_from_input(&input, pkg_id, Some(copy *out_dir), sess,
|
compile_crate_from_input(&input, out_dir, sess, crate, copy cfg);
|
||||||
None, &out_file, binary,
|
|
||||||
driver::cu_everything);
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,52 +304,31 @@ pub fn compile_input(sysroot: Option<@Path>,
|
||||||
// call compile_upto and return the crate
|
// call compile_upto and return the crate
|
||||||
// also, too many arguments
|
// also, too many arguments
|
||||||
pub fn compile_crate_from_input(input: &driver::input,
|
pub fn compile_crate_from_input(input: &driver::input,
|
||||||
pkg_id: &PkgId,
|
build_dir: &Path,
|
||||||
build_dir_opt: Option<Path>,
|
|
||||||
sess: session::Session,
|
sess: session::Session,
|
||||||
crate_opt: Option<@ast::crate>,
|
crate: @ast::crate,
|
||||||
out_file: &Path,
|
cfg: ast::crate_cfg) {
|
||||||
binary: @~str,
|
debug!("Calling build_output_filenames with %s, building library? %?",
|
||||||
what: driver::compile_upto) -> @ast::crate {
|
build_dir.to_str(), sess.building_library);
|
||||||
debug!("Calling build_output_filenames with %? and %s", build_dir_opt, out_file.to_str());
|
|
||||||
let outputs = driver::build_output_filenames(input, &build_dir_opt,
|
// bad copy
|
||||||
&Some(copy *out_file), sess);
|
let outputs = driver::build_output_filenames(input, &Some(copy *build_dir), &None,
|
||||||
|
crate.node.attrs, sess);
|
||||||
|
|
||||||
debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
|
debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
|
||||||
let cfg = driver::build_configuration(sess, binary, input);
|
debug!("additional libraries:");
|
||||||
match crate_opt {
|
for sess.opts.addl_lib_search_paths.each |lib| {
|
||||||
Some(c) => {
|
debug!("an additional library: %s", lib.to_str());
|
||||||
debug!("Calling compile_rest, outputs = %?", outputs);
|
|
||||||
assert_eq!(what, driver::cu_everything);
|
|
||||||
driver::compile_rest(sess, cfg, driver::cu_everything, Some(outputs), Some(c));
|
|
||||||
c
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
debug!("Calling compile_upto, outputs = %?", outputs);
|
|
||||||
let (crate, _) = driver::compile_upto(sess, copy cfg, input,
|
|
||||||
driver::cu_parse, Some(outputs));
|
|
||||||
let mut crate = crate.unwrap();
|
|
||||||
|
|
||||||
debug!("About to inject link_meta info...");
|
|
||||||
// Inject the inferred link_meta info if it's not already there
|
|
||||||
// (assumes that name and vers are the only linkage metas)
|
|
||||||
|
|
||||||
debug!("How many attrs? %?", attr::find_linkage_metas(crate.node.attrs).len());
|
|
||||||
|
|
||||||
if attr::find_linkage_metas(crate.node.attrs).is_empty() {
|
|
||||||
crate = @codemap::respan(crate.span, ast::crate_ {
|
|
||||||
attrs: ~[mk_attr(@dummy_spanned(
|
|
||||||
meta_list(@~"link",
|
|
||||||
~[@dummy_spanned(meta_name_value(@~"name",
|
|
||||||
mk_string_lit(@(copy pkg_id.short_name)))),
|
|
||||||
@dummy_spanned(meta_name_value(@~"vers",
|
|
||||||
mk_string_lit(@(copy pkg_id.version.to_str()))))])))],
|
|
||||||
..copy crate.node});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
driver::compile_rest(sess, cfg, what, Some(outputs), Some(crate));
|
driver::compile_rest(sess,
|
||||||
crate
|
cfg,
|
||||||
}
|
compile_upto {
|
||||||
}
|
from: driver::cu_expand,
|
||||||
|
to: driver::cu_everything
|
||||||
|
},
|
||||||
|
Some(outputs),
|
||||||
|
Some(crate));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -462,7 +342,7 @@ pub fn exe_suffix() -> ~str { ~"" }
|
||||||
|
|
||||||
// Called by build_crates
|
// Called by build_crates
|
||||||
// FIXME (#4432): Use workcache to only compile when needed
|
// FIXME (#4432): Use workcache to only compile when needed
|
||||||
pub fn compile_crate(sysroot: Option<@Path>, pkg_id: &PkgId,
|
pub fn compile_crate(ctxt: &Ctx, pkg_id: &PkgId,
|
||||||
crate: &Path, dir: &Path,
|
crate: &Path, dir: &Path,
|
||||||
flags: &[~str], cfgs: &[~str], opt: bool,
|
flags: &[~str], cfgs: &[~str], opt: bool,
|
||||||
what: OutputType) -> bool {
|
what: OutputType) -> bool {
|
||||||
|
@ -471,28 +351,53 @@ pub fn compile_crate(sysroot: Option<@Path>, pkg_id: &PkgId,
|
||||||
for flags.each |&fl| {
|
for flags.each |&fl| {
|
||||||
debug!("+++ %s", fl);
|
debug!("+++ %s", fl);
|
||||||
}
|
}
|
||||||
compile_input(sysroot, pkg_id, crate, dir, flags, cfgs, opt, what)
|
compile_input(ctxt, pkg_id, crate, dir, flags, cfgs, opt, what)
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize should be the only way to construct a LocalPath
|
/// Collect all `extern mod` directives in `c`, then
|
||||||
// (though this isn't enforced)
|
/// try to install their targets, failing if any target
|
||||||
/// Replace all occurrences of '-' in the stem part of path with '_'
|
/// can't be found.
|
||||||
/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux
|
fn find_and_install_dependencies(ctxt: &Ctx,
|
||||||
/// as the same name
|
sess: session::Session,
|
||||||
pub fn normalize(p_: RemotePath) -> LocalPath {
|
workspace: &Path,
|
||||||
let RemotePath(p) = p_;
|
c: &ast::crate,
|
||||||
match p.filestem() {
|
save: @fn(Path)
|
||||||
None => LocalPath(p),
|
) {
|
||||||
Some(st) => {
|
// :-(
|
||||||
let replaced = str::replace(st, "-", "_");
|
debug!("In find_and_install_dependencies...");
|
||||||
if replaced != st {
|
let my_workspace = copy *workspace;
|
||||||
LocalPath(p.with_filestem(replaced))
|
let my_ctxt = copy *ctxt;
|
||||||
|
for c.each_view_item() |vi: @ast::view_item| {
|
||||||
|
debug!("A view item!");
|
||||||
|
match vi.node {
|
||||||
|
// ignore metadata, I guess
|
||||||
|
ast::view_item_extern_mod(lib_ident, _, _) => {
|
||||||
|
match my_ctxt.sysroot_opt {
|
||||||
|
Some(ref x) => debug!("sysroot: %s", x.to_str()),
|
||||||
|
None => ()
|
||||||
|
};
|
||||||
|
let lib_name = sess.str_of(lib_ident);
|
||||||
|
match find_library_in_search_path(my_ctxt.sysroot_opt, *lib_name) {
|
||||||
|
Some(installed_path) => {
|
||||||
|
debug!("It exists: %s", installed_path.to_str());
|
||||||
}
|
}
|
||||||
else {
|
None => {
|
||||||
LocalPath(p)
|
// Try to install it
|
||||||
|
let pkg_id = PkgId::new(*lib_name);
|
||||||
|
my_ctxt.install(&my_workspace, &pkg_id);
|
||||||
|
// Also, add an additional search path
|
||||||
|
let installed_path = target_library_in_workspace(&pkg_id,
|
||||||
|
&my_workspace).pop();
|
||||||
|
debug!("Great, I installed %s, and it's in %s",
|
||||||
|
*lib_name, installed_path.to_str());
|
||||||
|
save(installed_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Ignore `use`s
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -526,10 +431,6 @@ pub fn mk_string_lit(s: @~str) -> ast::lit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrappers to prevent local and remote paths from getting confused
|
|
||||||
pub struct RemotePath (Path);
|
|
||||||
pub struct LocalPath (Path);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::is_cmd;
|
use super::is_cmd;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
// rustpkg utilities having to do with workspaces
|
// rustpkg utilities having to do with workspaces
|
||||||
|
|
||||||
use path_util::{rust_path, workspace_contains_package_id};
|
use path_util::{rust_path, workspace_contains_package_id};
|
||||||
use util::PkgId;
|
use package_id::PkgId;
|
||||||
use core::path::Path;
|
use core::path::Path;
|
||||||
|
|
||||||
pub fn pkg_parent_workspaces(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool {
|
pub fn pkg_parent_workspaces(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue