rustpkg: Add preliminary imperative API support
This commit is contained in:
parent
bd28fa4af5
commit
7079441843
@ -184,14 +184,14 @@ pub enum compile_upto {
|
||||
cu_everything,
|
||||
}
|
||||
|
||||
pub fn compile_upto(sess: Session, cfg: ast::crate_cfg,
|
||||
input: input, upto: compile_upto,
|
||||
outputs: Option<output_filenames>)
|
||||
-> {crate: @ast::crate, tcx: Option<ty::ctxt>} {
|
||||
// For continuing compilation after a parsed crate has been
|
||||
// modified
|
||||
pub fn compile_rest(sess: Session, cfg: ast::crate_cfg,
|
||||
upto: compile_upto, outputs: Option<output_filenames>,
|
||||
curr: Option<@ast::crate>)
|
||||
-> {crate: @ast::crate, tcx: Option<ty::ctxt>} {
|
||||
let time_passes = sess.time_passes();
|
||||
let mut crate = time(time_passes, ~"parsing",
|
||||
|| parse_input(sess, copy cfg, input) );
|
||||
if upto == cu_parse { return {crate: crate, tcx: None}; }
|
||||
let mut crate = curr.get();
|
||||
|
||||
*sess.building_library = session::building_library(
|
||||
sess.opts.crate_type, crate, sess.opts.test);
|
||||
@ -322,7 +322,6 @@ pub fn compile_upto(sess: Session, cfg: ast::crate_cfg,
|
||||
|
||||
};
|
||||
|
||||
|
||||
time(time_passes, ~"LLVM passes", ||
|
||||
link::write::run_passes(sess, llmod,
|
||||
&outputs.obj_filename));
|
||||
@ -342,9 +341,20 @@ pub fn compile_upto(sess: Session, cfg: ast::crate_cfg,
|
||||
return {crate: crate, tcx: None};
|
||||
}
|
||||
|
||||
pub fn compile_upto(sess: Session, +cfg: ast::crate_cfg,
|
||||
input: input, upto: compile_upto,
|
||||
outputs: Option<output_filenames>)
|
||||
-> {crate: @ast::crate, tcx: Option<ty::ctxt>} {
|
||||
let time_passes = sess.time_passes();
|
||||
let mut crate = time(time_passes, ~"parsing",
|
||||
|| parse_input(sess, copy cfg, input) );
|
||||
if upto == cu_parse { return {crate: crate, tcx: None}; }
|
||||
|
||||
compile_rest(sess, cfg, upto, outputs, Some(crate))
|
||||
}
|
||||
|
||||
pub fn compile_input(sess: Session, +cfg: ast::crate_cfg, input: input,
|
||||
outdir: &Option<Path>, output: &Option<Path>) {
|
||||
|
||||
let upto = if sess.opts.parse_only { cu_parse }
|
||||
else if sess.opts.no_trans { cu_no_trans }
|
||||
else { cu_everything };
|
||||
|
@ -1,24 +1,130 @@
|
||||
use core::*;
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use core::*;
|
||||
use util::{compile_crate, note};
|
||||
|
||||
/// A crate is a unit of Rust code to be compiled into a binary or library
|
||||
pub struct Crate {
|
||||
file: ~str,
|
||||
flags: ~[~str],
|
||||
cfg: ~[~str]
|
||||
cfgs: ~[~str]
|
||||
}
|
||||
|
||||
pub struct Listener {
|
||||
cmd: ~str,
|
||||
cb: fn~()
|
||||
}
|
||||
|
||||
pub fn run(listeners: ~[Listener]) {
|
||||
io::println(src_dir().to_str());
|
||||
io::println(work_dir().to_str());
|
||||
|
||||
let cmd = os::args()[1];
|
||||
|
||||
for listeners.each |listener| {
|
||||
if listener.cmd == cmd {
|
||||
(listener.cb)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub impl Crate {
|
||||
fn flag(flag: ~str) -> Crate {
|
||||
fn flag(flag: ~str) -> Crate {
|
||||
Crate {
|
||||
flags: vec::append(copy self.flags, ~[flag]),
|
||||
.. copy self
|
||||
}
|
||||
}
|
||||
|
||||
fn flags(flags: ~[~str]) -> Crate {
|
||||
Crate {
|
||||
flags: vec::append(copy self.flags, flags),
|
||||
.. copy self
|
||||
}
|
||||
}
|
||||
|
||||
fn cfg(cfg: ~str) -> Crate {
|
||||
Crate {
|
||||
cfgs: vec::append(copy self.cfgs, ~[cfg]),
|
||||
.. copy self
|
||||
}
|
||||
}
|
||||
|
||||
fn cfgs(cfgs: ~[~str]) -> Crate {
|
||||
Crate {
|
||||
cfgs: vec::append(copy self.cfgs, cfgs),
|
||||
.. copy self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(_targets: ~[Crate]) {
|
||||
// TODO: magic
|
||||
/// Create a crate target from a source file
|
||||
pub fn Crate(file: ~str) -> Crate {
|
||||
Crate {
|
||||
file: file,
|
||||
flags: ~[],
|
||||
cfgs: ~[]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the working directory of the package script.
|
||||
* Assumes that the package script has been compiled
|
||||
* in is the working directory.
|
||||
*/
|
||||
fn work_dir() -> Path {
|
||||
os::self_exe_path().get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source directory of the package (i.e.
|
||||
* where the crates are located). Assumes
|
||||
* that the cwd is changed to it before
|
||||
* running this executable.
|
||||
*/
|
||||
fn src_dir() -> Path {
|
||||
os::getcwd()
|
||||
}
|
||||
|
||||
pub fn args() -> ~[~str] {
|
||||
let mut args = os::args();
|
||||
|
||||
args.shift();
|
||||
args.shift();
|
||||
|
||||
args
|
||||
}
|
||||
|
||||
/// Build a set of crates, should be called once
|
||||
pub fn build(crates: ~[Crate]) -> bool {
|
||||
let dir = src_dir();
|
||||
let work_dir = work_dir();
|
||||
let mut success = true;
|
||||
|
||||
for crates.each |&crate| {
|
||||
let path = &dir.push_rel(&Path(crate.file)).normalize();
|
||||
|
||||
note(fmt!("compiling %s", path.to_str()));
|
||||
|
||||
success = compile_crate(path, &work_dir, crate.flags, crate.cfgs,
|
||||
false, false);
|
||||
|
||||
if !success { break; }
|
||||
}
|
||||
|
||||
os::set_exit_status(101);
|
||||
|
||||
success
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
|
||||
// TODO: utilities for working with things like autotools
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ use std::getopts;
|
||||
use std::net::url;
|
||||
use send_map::linear::LinearMap;
|
||||
use rustc::driver::{driver, session};
|
||||
use rustc::metadata::{filesearch};
|
||||
use syntax::{ast, attr, codemap, diagnostic, parse, visit};
|
||||
use semver::Version;
|
||||
|
||||
@ -46,19 +45,33 @@ struct PackageScript {
|
||||
name: ~str,
|
||||
vers: Version,
|
||||
crates: ~[~str],
|
||||
deps: ~[(~str, Option<~str>)]
|
||||
deps: ~[(~str, Option<~str>)],
|
||||
input: driver::input,
|
||||
sess: session::Session,
|
||||
cfg: ast::crate_cfg,
|
||||
crate: @ast::crate,
|
||||
custom: bool
|
||||
}
|
||||
|
||||
impl PackageScript {
|
||||
static fn parse(parent: Path) -> Result<PackageScript, ~str> {
|
||||
static fn parse(parent: &Path) -> Result<PackageScript, ~str> {
|
||||
let script = parent.push(~"package.rs");
|
||||
|
||||
if !os::path_exists(&script) {
|
||||
return result::Err(~"no package.rs file");
|
||||
}
|
||||
|
||||
let sess = parse::new_parse_sess(None);
|
||||
let crate = parse::parse_crate_from_file(&script, ~[], sess);
|
||||
let binary = os::args()[0];
|
||||
let options: @session::options = @{
|
||||
binary: binary,
|
||||
crate_type: session::bin_crate,
|
||||
.. *session::basic_options()
|
||||
};
|
||||
let input = driver::file_input(script);
|
||||
let sess = driver::build_session(options, diagnostic::emit);
|
||||
let cfg = driver::build_configuration(sess, binary, input);
|
||||
let {crate, _} = driver::compile_upto(sess, cfg, input,
|
||||
driver::cu_parse, None);
|
||||
let mut id = None;
|
||||
let mut vers = None;
|
||||
let mut crates = ~[];
|
||||
@ -165,8 +178,19 @@ impl PackageScript {
|
||||
}
|
||||
}
|
||||
|
||||
let mut custom = false;
|
||||
|
||||
// If we hit a function, we assume they want to use
|
||||
// the build API.
|
||||
for crate.node.module.items.each |i| {
|
||||
match i.node {
|
||||
ast::item_fn(_, _, _, _) => custom = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if id.is_none() || vers.is_none() {
|
||||
return result::Err(~"package's pkg attr is missing required data (id, vers)");
|
||||
return result::Err(~"pkg attr without (id, vers) values");
|
||||
}
|
||||
|
||||
let id = id.get();
|
||||
@ -184,12 +208,35 @@ impl PackageScript {
|
||||
name: name,
|
||||
vers: vers,
|
||||
crates: crates,
|
||||
deps: deps
|
||||
deps: deps,
|
||||
input: input,
|
||||
sess: sess,
|
||||
cfg: cfg,
|
||||
crate: crate,
|
||||
custom: custom
|
||||
})
|
||||
}
|
||||
|
||||
// Build the bootstrap and run a command
|
||||
// TODO: Use JIT once it works, it should be faster
|
||||
fn run(cmd: ~str) -> int {
|
||||
let work_dir = self.work_dir();
|
||||
let input = self.input;
|
||||
let sess = self.sess;
|
||||
let cfg = self.cfg;
|
||||
let crate = util::ready_crate(sess, self.crate);
|
||||
let outputs = driver::build_output_filenames(input, &Some(work_dir),
|
||||
&None, sess);
|
||||
let exe = work_dir.push(~"package" + util::exe_suffix());
|
||||
|
||||
driver::compile_rest(sess, cfg, driver::cu_parse,
|
||||
Some(outputs), Some(crate));
|
||||
run::run_program(exe.to_str(), ~[cmd])
|
||||
}
|
||||
|
||||
fn hash() -> ~str {
|
||||
fmt!("%s-%s-%s", self.name, util::hash(self.id + self.vers.to_str()), self.vers.to_str())
|
||||
fmt!("%s-%s-%s", self.name, util::hash(self.id + self.vers.to_str()),
|
||||
self.vers.to_str())
|
||||
}
|
||||
|
||||
fn work_dir() -> Path {
|
||||
@ -198,7 +245,7 @@ impl PackageScript {
|
||||
}
|
||||
|
||||
struct Ctx {
|
||||
cfg: ast::crate_cfg,
|
||||
cfgs: ~[~str],
|
||||
mut dep_cache: LinearMap<~str, bool>
|
||||
}
|
||||
|
||||
@ -229,13 +276,17 @@ impl Ctx {
|
||||
}
|
||||
|
||||
match cmd {
|
||||
~"build" => self.build(),
|
||||
~"clean" => self.clean(),
|
||||
~"build" => {
|
||||
self.build(&os::getcwd(), true, false, false);
|
||||
}
|
||||
~"clean" => {
|
||||
self.clean();
|
||||
}
|
||||
~"install" => {
|
||||
self.install(if args.len() >= 1 { Some(args[0]) }
|
||||
else { None },
|
||||
if args.len() >= 2 { Some(args[1]) }
|
||||
else { None }, false)
|
||||
else { None }, false);
|
||||
}
|
||||
~"prefer" => {
|
||||
if args.len() < 1 {
|
||||
@ -244,9 +295,11 @@ impl Ctx {
|
||||
|
||||
let (name, vers) = sep_name_vers(args[0]);
|
||||
|
||||
self.prefer(name.get(), vers)
|
||||
self.prefer(name.get(), vers);
|
||||
}
|
||||
~"test" => {
|
||||
self.test();
|
||||
}
|
||||
~"test" => self.test(),
|
||||
~"uninstall" => {
|
||||
if args.len() < 1 {
|
||||
return usage::uninstall();
|
||||
@ -254,7 +307,7 @@ impl Ctx {
|
||||
|
||||
let (name, vers) = sep_name_vers(args[0]);
|
||||
|
||||
self.uninstall(name.get(), vers)
|
||||
self.uninstall(name.get(), vers);
|
||||
}
|
||||
~"unprefer" => {
|
||||
if args.len() < 1 {
|
||||
@ -263,28 +316,27 @@ impl Ctx {
|
||||
|
||||
let (name, vers) = sep_name_vers(args[0]);
|
||||
|
||||
self.unprefer(name.get(), vers)
|
||||
self.unprefer(name.get(), vers);
|
||||
}
|
||||
_ => fail ~"reached an unhandled command"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn build() -> bool {
|
||||
let dir = os::getcwd();
|
||||
fn build(dir: &Path, verbose: bool, opt: bool,
|
||||
test: bool) -> Option<PackageScript> {
|
||||
let cwd = &os::getcwd();
|
||||
let script = match PackageScript::parse(dir) {
|
||||
result::Ok(script) => script,
|
||||
result::Err(err) => {
|
||||
util::error(err);
|
||||
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let work_dir = script.work_dir();
|
||||
let mut success = true;
|
||||
|
||||
util::need_dir(&work_dir);
|
||||
util::note(fmt!("building %s v%s (%s)", script.name, script.vers.to_str(),
|
||||
script.id));
|
||||
|
||||
if script.deps.len() >= 1 {
|
||||
util::note(~"installing dependencies");
|
||||
@ -302,15 +354,31 @@ impl Ctx {
|
||||
util::error(fmt!("building %s v%s failed: a dep wasn't installed",
|
||||
script.name, script.vers.to_str()));
|
||||
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
|
||||
util::note(~"installed dependencies");
|
||||
}
|
||||
|
||||
// Build imperative crates
|
||||
os::change_dir(dir);
|
||||
|
||||
if script.custom && script.run(~"build") != 0 {
|
||||
util::error(fmt!("building %s v%s failed: custom build logic failed",
|
||||
script.name, script.vers.to_str()));
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
os::change_dir(cwd);
|
||||
|
||||
for script.crates.each |&crate| {
|
||||
success = self.compile(&work_dir, &dir.push_rel(&Path(crate)), ~[],
|
||||
false, false);
|
||||
let crate = &dir.push_rel(&Path(crate)).normalize();
|
||||
|
||||
util::note(fmt!("compiling %s", crate.to_str()));
|
||||
|
||||
success = self.compile(crate, &work_dir, ~[],
|
||||
~[], opt, test);
|
||||
|
||||
if !success { break; }
|
||||
}
|
||||
@ -319,159 +387,23 @@ impl Ctx {
|
||||
util::error(fmt!("building %s v%s failed: a crate failed to compile",
|
||||
script.name, script.vers.to_str()));
|
||||
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
|
||||
util::note(fmt!("built %s v%s", script.name, script.vers.to_str()));
|
||||
if verbose {
|
||||
util::note(fmt!("built %s v%s", script.name, script.vers.to_str()));
|
||||
}
|
||||
|
||||
true
|
||||
Some(script)
|
||||
}
|
||||
|
||||
fn compile(dir: &Path, crate: &Path, flags: ~[~str],
|
||||
opt: bool, test: bool) -> bool {
|
||||
util::note(~"compiling " + crate.to_str());
|
||||
|
||||
let lib_dir = dir.push(~"lib");
|
||||
let bin_dir = dir.push(~"bin");
|
||||
let test_dir = dir.push(~"test");
|
||||
let binary = os::args()[0];
|
||||
let options: @session::options = @{
|
||||
binary: binary,
|
||||
addl_lib_search_paths: ~[util::root().push(~"lib")],
|
||||
crate_type: session::unknown_crate,
|
||||
optimize: if opt { session::Aggressive } else { session::No },
|
||||
test: test,
|
||||
.. *session::basic_options()
|
||||
};
|
||||
let input = driver::file_input(*crate);
|
||||
let sess = driver::build_session(options, diagnostic::emit);
|
||||
let cfg = driver::build_configuration(sess, binary, input);
|
||||
let mut outputs = driver::build_output_filenames(input, &None, &None,
|
||||
sess);
|
||||
let {crate, _} = driver::compile_upto(sess, cfg, input, driver::cu_parse,
|
||||
Some(outputs));
|
||||
|
||||
let mut name = None;
|
||||
let mut vers = None;
|
||||
let mut uuid = None;
|
||||
let mut crate_type = None;
|
||||
|
||||
fn load_link_attr(mis: ~[@ast::meta_item]) -> (Option<~str>,
|
||||
Option<~str>,
|
||||
Option<~str>) {
|
||||
let mut name = None;
|
||||
let mut vers = None;
|
||||
let mut uuid = None;
|
||||
|
||||
for mis.each |a| {
|
||||
match a.node {
|
||||
ast::meta_name_value(v, ast::spanned {node: ast::lit_str(s),
|
||||
span: _}) => {
|
||||
match v {
|
||||
~"name" => name = Some(*s),
|
||||
~"vers" => vers = Some(*s),
|
||||
~"uuid" => uuid = Some(*s),
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
(name, vers, uuid)
|
||||
}
|
||||
|
||||
for crate.node.attrs.each |a| {
|
||||
match a.node.value.node {
|
||||
ast::meta_name_value(v, ast::spanned {node: ast::lit_str(s),
|
||||
span: _}) => {
|
||||
match v {
|
||||
~"crate_type" => crate_type = Some(*s),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ast::meta_list(v, mis) => {
|
||||
match v {
|
||||
~"link" => {
|
||||
let (n, v, u) = load_link_attr(mis);
|
||||
|
||||
name = n;
|
||||
vers = v;
|
||||
uuid = u;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if name.is_none() || vers.is_none() || uuid.is_none() {
|
||||
util::error(~"crate's link attr is missing required data (name, vers, uuid)");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let name = name.get();
|
||||
let vers = vers.get();
|
||||
let uuid = uuid.get();
|
||||
|
||||
let is_bin = match crate_type {
|
||||
Some(crate_type) => {
|
||||
match crate_type {
|
||||
~"bin" => true,
|
||||
~"lib" => false,
|
||||
_ => {
|
||||
util::warn(~"unknown crate_type, falling back to lib");
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
util::warn(~"missing crate_type attr, assuming lib");
|
||||
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
if test {
|
||||
util::need_dir(&test_dir);
|
||||
|
||||
outputs = driver::build_output_filenames(input, &Some(test_dir),
|
||||
&None, sess)
|
||||
}
|
||||
else if is_bin {
|
||||
util::need_dir(&bin_dir);
|
||||
|
||||
#[cfg(windows)]
|
||||
fn suffix() -> ~str { ~".exe" }
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "android")]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn suffix() -> ~str { ~"" }
|
||||
|
||||
let path = bin_dir.push(fmt!("%s-%s-%s%s", name,
|
||||
util::hash(name + uuid + vers),
|
||||
vers, suffix()));
|
||||
outputs = driver::build_output_filenames(input, &None, &Some(path), sess);
|
||||
} else {
|
||||
util::need_dir(&lib_dir);
|
||||
|
||||
outputs = driver::build_output_filenames(input, &Some(lib_dir),
|
||||
&None, sess)
|
||||
}
|
||||
|
||||
driver::compile_upto(sess, cfg, input, driver::cu_everything,
|
||||
Some(outputs));
|
||||
|
||||
true
|
||||
fn compile(crate: &Path, dir: &Path, flags: ~[~str],
|
||||
cfgs: ~[~str], opt: bool, test: bool) -> bool {
|
||||
util::compile_crate(crate, dir, flags, cfgs, opt, test)
|
||||
}
|
||||
|
||||
fn clean() -> bool {
|
||||
let script = match PackageScript::parse(os::getcwd()) {
|
||||
let script = match PackageScript::parse(&os::getcwd()) {
|
||||
result::Ok(script) => script,
|
||||
result::Err(err) => {
|
||||
util::error(err);
|
||||
@ -505,7 +437,8 @@ impl Ctx {
|
||||
dir = os::getcwd();
|
||||
} else {
|
||||
let url = url.get();
|
||||
let hash = util::hash(if !target.is_none() { url + target.get() } else { url });
|
||||
let hash = util::hash(if !target.is_none() { url + target.get() }
|
||||
else { url });
|
||||
|
||||
if self.dep_cache.contains_key(&hash) {
|
||||
util::warn(~"already installed dep this run");
|
||||
@ -528,53 +461,13 @@ impl Ctx {
|
||||
}
|
||||
}
|
||||
|
||||
let script = match PackageScript::parse(dir) {
|
||||
result::Ok(script) => script,
|
||||
result::Err(err) => {
|
||||
util::error(err);
|
||||
|
||||
let script = match self.build(&dir, false, true, false) {
|
||||
Some(script) => script,
|
||||
None => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let work_dir = script.work_dir();
|
||||
|
||||
util::need_dir(&work_dir);
|
||||
util::note(fmt!("installing %s v%s (%s)", script.name, script.vers.to_str(),
|
||||
script.id));
|
||||
|
||||
if script.deps.len() >= 1 {
|
||||
util::note(~"installing dependencies");
|
||||
|
||||
for script.deps.each |&dep| {
|
||||
let (url, target) = dep;
|
||||
|
||||
success = self.install(Some(url), target, false);
|
||||
|
||||
if !success { break; }
|
||||
}
|
||||
|
||||
if !success {
|
||||
util::error(fmt!("installing %s v%s failed: a dep wasn't installed",
|
||||
script.name, script.vers.to_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
util::note(~"installed dependencies");
|
||||
}
|
||||
|
||||
for script.crates.each |&crate| {
|
||||
success = self.compile(&work_dir, &dir.push_rel(&Path(crate)), ~[],
|
||||
true, false);
|
||||
|
||||
if !success { break; }
|
||||
}
|
||||
|
||||
if !success {
|
||||
util::error(fmt!("installing %s v%s failed: a crate failed to compile",
|
||||
script.name, script.vers.to_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
let from_bin_dir = work_dir.push(~"bin");
|
||||
let from_lib_dir = work_dir.push(~"lib");
|
||||
let to_bin_dir = util::root().push(~"bin");
|
||||
@ -728,58 +621,14 @@ impl Ctx {
|
||||
}
|
||||
|
||||
fn test() -> bool {
|
||||
let dir = os::getcwd();
|
||||
let script = match PackageScript::parse(dir) {
|
||||
result::Ok(script) => script,
|
||||
result::Err(err) => {
|
||||
util::error(err);
|
||||
|
||||
return false;
|
||||
let script = match self.build(&os::getcwd(), false, false, true) {
|
||||
Some(script) => script,
|
||||
None => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let work_dir = script.work_dir();
|
||||
let test_dir = work_dir.push(~"test");
|
||||
let mut success = true;
|
||||
|
||||
util::need_dir(&work_dir);
|
||||
util::note(fmt!("testing %s v%s (%s)", script.name, script.vers.to_str(),
|
||||
script.id));
|
||||
|
||||
if script.deps.len() >= 1 {
|
||||
util::note(~"installing dependencies");
|
||||
|
||||
for script.deps.each |&dep| {
|
||||
let (url, target) = dep;
|
||||
|
||||
success = self.install(Some(url), target, true);
|
||||
|
||||
if !success { break; }
|
||||
}
|
||||
|
||||
|
||||
if !success {
|
||||
util::error(fmt!("testing %s v%s failed: a dep wasn't installed",
|
||||
script.name, script.vers.to_str()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
util::note(~"installed dependencies");
|
||||
}
|
||||
|
||||
for script.crates.each |&crate| {
|
||||
success = self.compile(&work_dir, &dir.push_rel(&Path(crate)), ~[],
|
||||
false, true);
|
||||
|
||||
if !success { break; }
|
||||
}
|
||||
|
||||
if !success {
|
||||
util::error(fmt!("testing %s v%s failed: a crate failed to compile",
|
||||
script.name, script.vers.to_str()));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
for os::walk_dir(&test_dir) |test| {
|
||||
util::note(fmt!("running %s", test.to_str()));
|
||||
@ -892,7 +741,7 @@ pub fn main() {
|
||||
};
|
||||
let help = getopts::opt_present(matches, ~"h") ||
|
||||
getopts::opt_present(matches, ~"help");
|
||||
let cfg = vec::append(getopts::opt_strs(matches, ~"cfg"),
|
||||
let cfgs = vec::append(getopts::opt_strs(matches, ~"cfg"),
|
||||
getopts::opt_strs(matches, ~"c"));
|
||||
let mut args = copy matches.free;
|
||||
|
||||
@ -919,14 +768,8 @@ pub fn main() {
|
||||
};
|
||||
}
|
||||
|
||||
let mut cfg_specs = ~[];
|
||||
|
||||
for cfg.each |s| {
|
||||
cfg_specs.push(attr::mk_word_item(/*bad*/copy *s));
|
||||
}
|
||||
|
||||
Ctx {
|
||||
cfg: cfg_specs,
|
||||
cfgs: cfgs,
|
||||
mut dep_cache: LinearMap()
|
||||
}.run(cmd, args);
|
||||
}
|
||||
@ -934,3 +777,5 @@ pub fn main() {
|
||||
pub use Crate = api::Crate;
|
||||
pub use build = api::build;
|
||||
pub use util = api::util;
|
||||
pub use Listener = api::Listener;
|
||||
pub use run = api::run;
|
||||
|
@ -1,3 +1,13 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use core::io;
|
||||
|
||||
pub fn general() {
|
||||
|
@ -1,8 +1,23 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use core::*;
|
||||
use send_map::linear::LinearMap;
|
||||
use rustc::metadata::filesearch;
|
||||
use rustc::driver::{driver, session};
|
||||
use syntax::ast_util::*;
|
||||
use syntax::{ast, attr, codemap, diagnostic, fold, parse, visit};
|
||||
use codemap::span;
|
||||
use semver::Version;
|
||||
use std::{json, term, sort};
|
||||
use api::Listener;
|
||||
|
||||
pub struct Package {
|
||||
id: ~str,
|
||||
@ -41,6 +56,401 @@ pub fn parse_name(id: ~str) -> result::Result<~str, ~str> {
|
||||
result::Ok(parts.last())
|
||||
}
|
||||
|
||||
fn mk_rustpkg_use(ctx: @ReadyCtx) -> @ast::view_item {
|
||||
let vers = ast::lit_str(@~"0.6");
|
||||
let vers = no_span(vers);
|
||||
let mi = ast::meta_name_value(~"vers", vers);
|
||||
let mi = no_span(mi);
|
||||
let vi = ast::view_item_use(ctx.sess.ident_of(~"rustpkg"),
|
||||
~[@mi],
|
||||
ctx.sess.next_node_id());
|
||||
|
||||
@ast::view_item {
|
||||
node: vi,
|
||||
attrs: ~[],
|
||||
vis: ast::private,
|
||||
span: dummy_sp()
|
||||
}
|
||||
}
|
||||
|
||||
struct ListenerFn {
|
||||
span: codemap::span,
|
||||
path: ~[ast::ident]
|
||||
}
|
||||
|
||||
struct ReadyCtx {
|
||||
sess: session::Session,
|
||||
crate: @ast::crate,
|
||||
mut path: ~[ast::ident],
|
||||
mut fns: ~[ListenerFn]
|
||||
}
|
||||
|
||||
fn fold_mod(ctx: @ReadyCtx, m: ast::_mod,
|
||||
fold: fold::ast_fold) -> ast::_mod {
|
||||
fn strip_main(item: @ast::item) -> @ast::item {
|
||||
@ast::item {
|
||||
attrs: do item.attrs.filtered |attr| {
|
||||
attr::get_attr_name(*attr) != ~"main"
|
||||
},
|
||||
.. copy *item
|
||||
}
|
||||
}
|
||||
|
||||
fold::noop_fold_mod({
|
||||
view_items: vec::append_one(m.view_items, mk_rustpkg_use(ctx)),
|
||||
items: do vec::map(m.items) |item| {
|
||||
strip_main(*item)
|
||||
}
|
||||
}, fold)
|
||||
}
|
||||
|
||||
fn fold_crate(ctx: @ReadyCtx, crate: ast::crate_,
|
||||
fold: fold::ast_fold) -> ast::crate_ {
|
||||
let folded = fold::noop_fold_crate(crate, fold);
|
||||
|
||||
ast::crate_ {
|
||||
module: add_pkg_module(ctx, /*bad*/copy folded.module),
|
||||
.. folded
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_item(ctx: @ReadyCtx, &&item: @ast::item,
|
||||
fold: fold::ast_fold) -> Option<@ast::item> {
|
||||
|
||||
ctx.path.push(item.ident);
|
||||
|
||||
if attr::find_attrs_by_name(item.attrs, ~"pkg_do").is_not_empty() {
|
||||
ctx.fns.push(ListenerFn {
|
||||
span: item.span,
|
||||
path: /*bad*/copy ctx.path
|
||||
});
|
||||
}
|
||||
|
||||
let res = fold::noop_fold_item(item, fold);
|
||||
|
||||
ctx.path.pop();
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn mk_rustpkg_import(ctx: @ReadyCtx) -> @ast::view_item {
|
||||
let path = @ast::path {
|
||||
span: dummy_sp(),
|
||||
global: false,
|
||||
idents: ~[ctx.sess.ident_of(~"rustpkg")],
|
||||
rp: None,
|
||||
types: ~[]
|
||||
};
|
||||
let vp = @no_span(ast::view_path_simple(ctx.sess.ident_of(~"rustpkg"),
|
||||
path, ast::type_value_ns,
|
||||
ctx.sess.next_node_id()));
|
||||
|
||||
@ast::view_item {
|
||||
node: ast::view_item_import(~[vp]),
|
||||
attrs: ~[],
|
||||
vis: ast::private,
|
||||
span: dummy_sp()
|
||||
}
|
||||
}
|
||||
|
||||
fn add_pkg_module(ctx: @ReadyCtx, m: ast::_mod) -> ast::_mod {
|
||||
let listeners = mk_listeners(ctx);
|
||||
let main = mk_main(ctx);
|
||||
let pkg_mod = @{
|
||||
view_items: ~[mk_rustpkg_import(ctx)],
|
||||
items: ~[main, listeners]
|
||||
};
|
||||
let resolve_unexported_attr =
|
||||
attr::mk_attr(attr::mk_word_item(~"!resolve_unexported"));
|
||||
let item_ = ast::item_mod(*pkg_mod);
|
||||
let item = @ast::item {
|
||||
ident: ctx.sess.ident_of(~"__pkg"),
|
||||
attrs: ~[resolve_unexported_attr],
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: item_,
|
||||
vis: ast::public,
|
||||
span: dummy_sp(),
|
||||
};
|
||||
|
||||
{
|
||||
items: vec::append_one(/*bad*/copy m.items, item),
|
||||
.. m
|
||||
}
|
||||
}
|
||||
|
||||
fn no_span<T: Copy>(t: T) -> ast::spanned<T> {
|
||||
ast::spanned {
|
||||
node: t,
|
||||
span: dummy_sp()
|
||||
}
|
||||
}
|
||||
|
||||
fn path_node(ids: ~[ast::ident]) -> @ast::path {
|
||||
@ast::path {
|
||||
span: dummy_sp(),
|
||||
global: false,
|
||||
idents: ids,
|
||||
rp: None,
|
||||
types: ~[]
|
||||
}
|
||||
}
|
||||
|
||||
fn path_node_global(ids: ~[ast::ident]) -> @ast::path {
|
||||
@ast::path {
|
||||
span: dummy_sp(),
|
||||
global: true,
|
||||
idents: ids,
|
||||
rp: None,
|
||||
types: ~[]
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_listeners(ctx: @ReadyCtx) -> @ast::item {
|
||||
let ret_ty = mk_listener_vec_ty(ctx);
|
||||
let decl = {
|
||||
inputs: ~[],
|
||||
output: ret_ty,
|
||||
cf: ast::return_val
|
||||
};
|
||||
let listeners = mk_listener_vec(ctx);
|
||||
let body_ = default_block(~[], option::Some(listeners),
|
||||
ctx.sess.next_node_id());
|
||||
let body = no_span(body_);
|
||||
let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
|
||||
|
||||
@ast::item {
|
||||
ident: ctx.sess.ident_of(~"listeners"),
|
||||
attrs: ~[],
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: item_,
|
||||
vis: ast::public,
|
||||
span: dummy_sp(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_path(ctx: @ReadyCtx, path: ~[ast::ident]) -> @ast::path {
|
||||
path_node(~[ctx.sess.ident_of(~"rustpkg")] + path)
|
||||
}
|
||||
|
||||
fn mk_listener_vec_ty(ctx: @ReadyCtx) -> @ast::Ty {
|
||||
let listener_ty_path = mk_path(ctx, ~[ctx.sess.ident_of(~"Listener")]);
|
||||
let listener_ty = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: ast::ty_path(listener_ty_path,
|
||||
ctx.sess.next_node_id()),
|
||||
span: dummy_sp()
|
||||
};
|
||||
let vec_mt = ast::mt {
|
||||
ty: @listener_ty,
|
||||
mutbl: ast::m_imm
|
||||
};
|
||||
let inner_ty = @{
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: ast::ty_vec(vec_mt),
|
||||
span: dummy_sp()
|
||||
};
|
||||
|
||||
@{
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: ast::ty_uniq(ast::mt {
|
||||
ty: inner_ty,
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
span: dummy_sp()
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_listener_vec(ctx: @ReadyCtx) -> @ast::expr {
|
||||
let fns = ctx.fns;
|
||||
|
||||
let descs = do fns.map |listener| {
|
||||
mk_listener_rec(ctx, *listener)
|
||||
};
|
||||
let inner_expr = @{
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: ast::expr_vec(descs, ast::m_imm),
|
||||
span: dummy_sp()
|
||||
};
|
||||
|
||||
@{
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: ast::expr_vstore(inner_expr, ast::expr_vstore_uniq),
|
||||
span: dummy_sp()
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_listener_rec(ctx: @ReadyCtx, listener: ListenerFn) -> @ast::expr {
|
||||
let span = listener.span;
|
||||
let path = /*bad*/copy listener.path;
|
||||
let cmd_lit = no_span(ast::lit_str(@path_name_i(path,
|
||||
ctx.sess.parse_sess.interner)));
|
||||
let cmd_expr_inner = @{
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: ast::expr_lit(@cmd_lit),
|
||||
span: span
|
||||
};
|
||||
let cmd_expr = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: ast::expr_vstore(cmd_expr_inner, ast::expr_vstore_uniq),
|
||||
span: dummy_sp()
|
||||
};
|
||||
let cmd_field = no_span(ast::field_ {
|
||||
mutbl: ast::m_imm,
|
||||
ident: ctx.sess.ident_of(~"cmd"),
|
||||
expr: @cmd_expr,
|
||||
});
|
||||
|
||||
let cb_path = path_node_global(path);
|
||||
let cb_expr = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: ast::expr_path(cb_path),
|
||||
span: span
|
||||
};
|
||||
let cb_wrapper_expr = mk_fn_wrapper(ctx, cb_expr, span);
|
||||
let cb_field = no_span(ast::field_ {
|
||||
mutbl: ast::m_imm,
|
||||
ident: ctx.sess.ident_of(~"cb"),
|
||||
expr: cb_wrapper_expr
|
||||
});
|
||||
|
||||
let listener_path = mk_path(ctx, ~[ctx.sess.ident_of(~"Listener")]);
|
||||
let listener_rec_ = ast::expr_struct(listener_path,
|
||||
~[cmd_field, cb_field],
|
||||
option::None);
|
||||
@{
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: listener_rec_,
|
||||
span: span
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_fn_wrapper(ctx: @ReadyCtx, fn_path_expr: ast::expr,
|
||||
span: span) -> @ast::expr {
|
||||
let call_expr = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: ast::expr_call(@fn_path_expr, ~[], false),
|
||||
span: span
|
||||
};
|
||||
let call_stmt = no_span(ast::stmt_semi(@call_expr, ctx.sess.next_node_id()));
|
||||
let wrapper_decl = {
|
||||
inputs: ~[],
|
||||
output: @{
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: ast::ty_nil, span: span
|
||||
},
|
||||
cf: ast::return_val
|
||||
};
|
||||
let wrapper_body = no_span(ast::blk_ {
|
||||
view_items: ~[],
|
||||
stmts: ~[@call_stmt],
|
||||
expr: option::None,
|
||||
id: ctx.sess.next_node_id(),
|
||||
rules: ast::default_blk
|
||||
});
|
||||
|
||||
@{
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: ast::expr_fn(ast::ProtoBare, wrapper_decl,
|
||||
wrapper_body, @~[]),
|
||||
span: span
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_main(ctx: @ReadyCtx) -> @ast::item {
|
||||
let ret_ty = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: ast::ty_nil,
|
||||
span: dummy_sp()
|
||||
};
|
||||
let decl = {
|
||||
inputs: ~[],
|
||||
output: @ret_ty,
|
||||
cf: ast::return_val
|
||||
};
|
||||
let run_call_expr = mk_run_call(ctx);
|
||||
let body_ = default_block(~[], option::Some(run_call_expr),
|
||||
ctx.sess.next_node_id());
|
||||
let body = ast::spanned {
|
||||
node: body_,
|
||||
span: dummy_sp()
|
||||
};
|
||||
let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
|
||||
|
||||
@ast::item {
|
||||
ident: ctx.sess.ident_of(~"main"),
|
||||
attrs: ~[attr::mk_attr(attr::mk_word_item(~"main"))],
|
||||
id: ctx.sess.next_node_id(),
|
||||
node: item_,
|
||||
vis: ast::public,
|
||||
span: dummy_sp(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_run_call(ctx: @ReadyCtx) -> @ast::expr {
|
||||
let listener_path = path_node(~[ctx.sess.ident_of(~"listeners")]);
|
||||
let listener_path_expr_ = ast::expr_path(listener_path);
|
||||
let listener_path_expr = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: listener_path_expr_,
|
||||
span: dummy_sp()
|
||||
};
|
||||
let listener_call_expr_ = ast::expr_call(@listener_path_expr, ~[], false);
|
||||
let listener_call_expr = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: listener_call_expr_,
|
||||
span: dummy_sp()
|
||||
};
|
||||
let rustpkg_run_path = mk_path(ctx, ~[ctx.sess.ident_of(~"run")]);
|
||||
|
||||
let rustpkg_run_path_expr_ = ast::expr_path(rustpkg_run_path);
|
||||
let rustpkg_run_path_expr = {
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: rustpkg_run_path_expr_,
|
||||
span: dummy_sp()
|
||||
};
|
||||
let rustpkg_run_call_expr_ = ast::expr_call(@rustpkg_run_path_expr,
|
||||
~[@listener_call_expr],
|
||||
false);
|
||||
@{
|
||||
id: ctx.sess.next_node_id(),
|
||||
callee_id: ctx.sess.next_node_id(),
|
||||
node: rustpkg_run_call_expr_,
|
||||
span: dummy_sp()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate/filter main function, add the list of commands, etc.
|
||||
pub fn ready_crate(sess: session::Session,
|
||||
crate: @ast::crate) -> @ast::crate {
|
||||
let ctx = @ReadyCtx {
|
||||
sess: sess,
|
||||
crate: crate,
|
||||
mut path: ~[],
|
||||
mut fns: ~[]
|
||||
};
|
||||
let precursor = @fold::AstFoldFns {
|
||||
fold_crate: fold::wrap(|a, b| fold_crate(ctx, a, b)),
|
||||
fold_item: |a, b| fold_item(ctx, a, b),
|
||||
fold_mod: |a, b| fold_mod(ctx, a, b),
|
||||
.. *fold::default_ast_fold()
|
||||
};
|
||||
|
||||
let fold = fold::make_fold(precursor);
|
||||
|
||||
@fold.fold_crate(*crate)
|
||||
}
|
||||
|
||||
pub fn parse_vers(vers: ~str) -> result::Result<Version, ~str> {
|
||||
match semver::parse(vers) {
|
||||
Some(vers) => result::Ok(vers),
|
||||
@ -417,6 +827,155 @@ pub fn remove_pkg(pkg: &Package) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn compile_input(input: driver::input, dir: &Path,
|
||||
flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool {
|
||||
let lib_dir = dir.push(~"lib");
|
||||
let bin_dir = dir.push(~"bin");
|
||||
let test_dir = dir.push(~"test");
|
||||
let binary = os::args()[0];
|
||||
let options: @session::options = @{
|
||||
binary: binary,
|
||||
crate_type: session::unknown_crate,
|
||||
optimize: if opt { session::Aggressive } else { session::No },
|
||||
test: test,
|
||||
.. *session::basic_options()
|
||||
};
|
||||
let sess = driver::build_session(options, diagnostic::emit);
|
||||
let cfg = driver::build_configuration(sess, binary, input);
|
||||
let mut outputs = driver::build_output_filenames(input, &None, &None,
|
||||
sess);
|
||||
let {crate, _} = driver::compile_upto(sess, cfg, input, driver::cu_parse,
|
||||
Some(outputs));
|
||||
|
||||
let mut name = None;
|
||||
let mut vers = None;
|
||||
let mut uuid = None;
|
||||
let mut crate_type = None;
|
||||
|
||||
fn load_link_attr(mis: ~[@ast::meta_item]) -> (Option<~str>,
|
||||
Option<~str>,
|
||||
Option<~str>) {
|
||||
let mut name = None;
|
||||
let mut vers = None;
|
||||
let mut uuid = None;
|
||||
|
||||
for mis.each |a| {
|
||||
match a.node {
|
||||
ast::meta_name_value(v, ast::spanned {node: ast::lit_str(s),
|
||||
span: _}) => {
|
||||
match v {
|
||||
~"name" => name = Some(*s),
|
||||
~"vers" => vers = Some(*s),
|
||||
~"uuid" => uuid = Some(*s),
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
(name, vers, uuid)
|
||||
}
|
||||
|
||||
for crate.node.attrs.each |a| {
|
||||
match a.node.value.node {
|
||||
ast::meta_name_value(v, ast::spanned {node: ast::lit_str(s),
|
||||
span: _}) => {
|
||||
match v {
|
||||
~"crate_type" => crate_type = Some(*s),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ast::meta_list(v, mis) => {
|
||||
match v {
|
||||
~"link" => {
|
||||
let (n, v, u) = load_link_attr(mis);
|
||||
|
||||
name = n;
|
||||
vers = v;
|
||||
uuid = u;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if name.is_none() || vers.is_none() || uuid.is_none() {
|
||||
error(~"link attr without (name, vers, uuid) values");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
let name = name.get();
|
||||
let vers = vers.get();
|
||||
let uuid = uuid.get();
|
||||
|
||||
let is_bin = match crate_type {
|
||||
Some(crate_type) => {
|
||||
match crate_type {
|
||||
~"bin" => true,
|
||||
~"lib" => false,
|
||||
_ => {
|
||||
warn(~"unknown crate_type, falling back to lib");
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
warn(~"missing crate_type attr, assuming lib");
|
||||
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
if test {
|
||||
need_dir(&test_dir);
|
||||
|
||||
outputs = driver::build_output_filenames(input, &Some(test_dir),
|
||||
&None, sess)
|
||||
}
|
||||
else if is_bin {
|
||||
need_dir(&bin_dir);
|
||||
|
||||
let path = bin_dir.push(fmt!("%s-%s-%s%s", name,
|
||||
hash(name + uuid + vers),
|
||||
vers, exe_suffix()));
|
||||
outputs = driver::build_output_filenames(input, &None, &Some(path), sess);
|
||||
} else {
|
||||
need_dir(&lib_dir);
|
||||
|
||||
outputs = driver::build_output_filenames(input, &Some(lib_dir),
|
||||
&None, sess)
|
||||
}
|
||||
|
||||
driver::compile_rest(sess, cfg, driver::cu_everything,
|
||||
Some(outputs), Some(crate));
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn exe_suffix() -> ~str { ~".exe" }
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "android")]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn exe_suffix() -> ~str { ~"" }
|
||||
|
||||
pub fn compile_crate(crate: &Path, dir: &Path, flags: ~[~str],
|
||||
cfgs: ~[~str], opt: bool, test: bool) -> bool {
|
||||
compile_input(driver::file_input(*crate), dir, flags, cfgs, opt, test)
|
||||
}
|
||||
|
||||
pub fn compile_str(code: ~str, dir: &Path, flags: ~[~str],
|
||||
cfgs: ~[~str], opt: bool, test: bool) -> bool {
|
||||
compile_input(driver::str_input(code), dir, flags, cfgs, opt, test)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn link_exe(_src: &Path, _dest: &Path) -> bool{
|
||||
/* FIXME: Investigate how to do this on win32
|
||||
|
Loading…
Reference in New Issue
Block a user