+++ /dev/null
-// 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],
- cfgs: ~[~str]
-}
-
-pub struct Listener {
- cmds: ~[~str],
- cb: fn~()
-}
-
-pub fn run(listeners: ~[Listener]) {
- let rcmd = os::args()[2];
- let mut found = false;
-
- for listeners.each |listener| {
- for listener.cmds.each |&cmd| {
- if cmd == rcmd {
- (listener.cb)();
-
- found = true;
-
- break;
- }
- }
- }
-
- if !found {
- os::set_exit_status(1);
- }
-}
-
-pub impl 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
- }
- }
-}
-
-/// 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;
- let sysroot = Path(os::args()[1]);
-
- for crates.each |&crate| {
- let path = &dir.push_rel(&Path(crate.file)).normalize();
-
- note(fmt!("compiling %s", path.to_str()));
-
- success = compile_crate(Some(sysroot), path, &work_dir, crate.flags, crate.cfgs,
- false, false);
-
- if !success { break; }
- }
-
- if !success {
- os::set_exit_status(2);
- }
-
- success
-}
-
-pub mod util {
- // TODO: utilities for working with things like autotools
-}
use syntax::{ast, attr, codemap, diagnostic, parse, visit};
use semver::Version;
-mod api;
mod usage;
mod util;
}
// Build the bootstrap and run a command
- // TODO: Use JIT once it works, it should be faster
+ // FIXME: Use workcache to only compile the script when changed
+ // FIXME: Use JIT once it works, it should be faster
fn run(cmd: ~str) -> int {
let work_dir = self.work_dir();
let input = self.input;
}
~"install" => {
self.install(if args.len() >= 1 { Some(args[0]) }
- else { None },
+ else { None },
if args.len() >= 2 { Some(args[1]) }
else { None }, false);
}
result::Err(err) => {
util::error(err);
- return None;
+ return None;
}
};
let work_dir = script.work_dir();
if !success {
- util::error(fmt!("building %s v%s failed: a dep wasn't installed",
- script.name, script.vers.to_str()));
+ util::error(
+ fmt!("building %s v%s failed: a dep wasn't installed",
+ script.name, script.vers.to_str()));
return None;
}
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()));
+ util::error(
+ fmt!("building %s v%s failed: custom build logic failed",
+ script.name, script.vers.to_str()));
return None;
}
}
if !success {
- util::error(fmt!("building %s v%s failed: a crate failed to compile",
- script.name, script.vers.to_str()));
+ util::error(
+ fmt!("building %s v%s failed: a crate failed to compile",
+ script.name, script.vers.to_str()));
return None;
}
if verbose {
- util::note(fmt!("built %s v%s", script.name, script.vers.to_str()));
+ util::note(fmt!("built %s v%s", script.name,
+ script.vers.to_str()));
}
Some(script)
};
let dir = script.work_dir();
- util::note(fmt!("cleaning %s v%s (%s)", script.name, script.vers.to_str(),
- script.id));
+ util::note(fmt!("cleaning %s v%s (%s)", script.name,
+ script.vers.to_str(), script.id));
if os::path_exists(&dir) {
util::remove_dir_r(&dir);
}
fn install(url: Option<~str>, target: Option<~str>, cache: bool) -> bool {
- let mut success = true;
+ let mut success;
let mut dir;
if url.is_none() {
}
fn fetch(dir: &Path, url: ~str, target: Option<~str>) -> bool {
- let url = match url::from_str(if str::find_str(url, "://").is_none() { ~"http://" + url }
- else { url }) {
+ let url = if str::find_str(url, "://").is_none() {
+ ~"http://" + url }
+ else { url };
+ let url = match url::from_str(url) {
result::Ok(url) => url,
result::Err(err) => {
util::error(fmt!("failed parsing %s", err.to_lower()));
let tar = dir.dir_path().push(&dir.file_path().to_str() + ~".tar");
- if run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o", tar.to_str(), url]).status != 0 {
+ if run::program_output(~"curl", ~[~"-f", ~"-s",
+ ~"-o", tar.to_str(),
+ url]).status != 0 {
util::error(~"fetching failed: downloading using curl failed");
return false;
}
- if run::program_output(~"tar", ~[~"-x", ~"--strip-components=1", ~"-C", dir.to_str(), ~"-f", tar.to_str()]).status != 0 {
- util::error(~"fetching failed: extracting using tar failed (is it a valid tar archive?)");
+ if run::program_output(~"tar", ~[~"-x", ~"--strip-components=1",
+ ~"-C", dir.to_str(), ~"-f",
+ tar.to_str()]).status != 0 {
+ util::error(~"fetching failed: extracting using tar failed" +
+ ~"(is it a valid tar archive?)");
return false;
}
// Git can't clone into a non-empty directory
util::remove_dir_r(dir);
- if run::program_output(~"git", ~[~"clone", url, dir.to_str()]).status != 0 {
+ if run::program_output(~"git", ~[~"clone", url,
+ dir.to_str()]).status != 0 {
util::error(~"fetching failed: can't clone repository");
return false;
let mut success = true;
do util::temp_change_dir(dir) {
- success = run::program_output(~"git", ~[~"checkout", target.get()]).status != 0
+ success = run::program_output(~"git",
+ ~[~"checkout",
+ target.get()]).status != 0
}
if !success {
}
};
- util::note(fmt!("uninstalling %s v%s (%s)", name, package.vers.to_str(),
- package.id));
+ util::note(fmt!("uninstalling %s v%s (%s)", name,
+ package.vers.to_str(), package.id));
for vec::append(package.bins, package.libs).each |&file| {
let path = Path(file);
}
};
- util::note(fmt!("unpreferring %s v%s (%s)", name, package.vers.to_str(),
- package.id));
+ util::note(fmt!("unpreferring %s v%s (%s)", name,
+ package.vers.to_str(), package.id));
let bin_dir = util::root().push(~"bin");
}.run(cmd, args);
}
-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;
+
+/// A crate is a unit of Rust code to be compiled into a binary or library
+pub struct Crate {
+ file: ~str,
+ flags: ~[~str],
+ cfgs: ~[~str]
+}
+
+pub struct Listener {
+ cmds: ~[~str],
+ cb: fn~()
+}
+
+pub fn run(listeners: ~[Listener]) {
+ let rcmd = os::args()[2];
+ let mut found = false;
+
+ for listeners.each |listener| {
+ for listener.cmds.each |&cmd| {
+ if cmd == rcmd {
+ (listener.cb)();
+
+ found = true;
+
+ break;
+ }
+ }
+ }
+
+ if !found {
+ os::set_exit_status(1);
+ }
+}
+
+pub impl Crate {
+ pub fn flag(flag: ~str) -> Crate {
+ Crate {
+ flags: vec::append(copy self.flags, ~[flag]),
+ .. copy self
+ }
+ }
+
+ pub fn flags(flags: ~[~str]) -> Crate {
+ Crate {
+ flags: vec::append(copy self.flags, flags),
+ .. copy self
+ }
+ }
+
+ pub fn cfg(cfg: ~str) -> Crate {
+ Crate {
+ cfgs: vec::append(copy self.cfgs, ~[cfg]),
+ .. copy self
+ }
+ }
+
+ pub fn cfgs(cfgs: ~[~str]) -> Crate {
+ Crate {
+ cfgs: vec::append(copy self.cfgs, cfgs),
+ .. copy self
+ }
+ }
+}
+
+/// 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()
+}
+
+/// 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;
+ let sysroot = Path(os::args()[1]);
+
+ for crates.each |&crate| {
+ let path = &dir.push_rel(&Path(crate.file)).normalize();
+
+ util::note(fmt!("compiling %s", path.to_str()));
+
+ success = util::compile_crate(Some(sysroot), path, &work_dir,
+ crate.flags, crate.cfgs,
+ false, false);
+
+ if !success { break; }
+ }
+
+ if !success {
+ os::set_exit_status(2);
+ }
+
+ success
+}
use semver::Version;
use std::{json, term, sort, getopts};
use getopts::groups::getopts;
-use api::Listener;
+use Listener;
pub struct Package {
id: ~str,
for parts.each |&part| {
for str::chars(part).each |&char| {
if char::is_whitespace(char) {
- return result::Err(~"could not parse id: contains whitespace");
+ return result::Err(
+ ~"could not parse id: contains whitespace");
} else if char::is_uppercase(char) {
- return result::Err(~"could not parse id: should be all lowercase");
+ return result::Err(
+ ~"could not parse id: should be all lowercase");
}
}
}
}
}
- fold::noop_fold_mod({
+ fold::noop_fold_mod(ast::_mod {
view_items: vec::append_one(m.view_items, mk_rustpkg_use(ctx)),
items: do vec::map(m.items) |item| {
strip_main(*item)
}
}
-fn fold_item(ctx: @ReadyCtx, &&item: @ast::item,
+fn fold_item(ctx: @ReadyCtx, item: @ast::item,
fold: fold::ast_fold) -> Option<@ast::item> {
ctx.path.push(item.ident);
fn add_pkg_module(ctx: @ReadyCtx, m: ast::_mod) -> ast::_mod {
let listeners = mk_listeners(ctx);
let main = mk_main(ctx);
- let pkg_mod = @{
+ let pkg_mod = @ast::_mod {
view_items: ~[mk_rustpkg_import(ctx)],
items: ~[main, listeners]
};
span: dummy_sp(),
};
- {
+ ast::_mod {
items: vec::append_one(/*bad*/copy m.items, item),
.. m
}
fn mk_listeners(ctx: @ReadyCtx) -> @ast::item {
let ret_ty = mk_listener_vec_ty(ctx);
- let decl = {
+ let decl = ast::fn_decl {
inputs: ~[],
output: ret_ty,
cf: ast::return_val
fn mk_listener_vec_ty(ctx: @ReadyCtx) -> @ast::Ty {
let listener_ty_path = mk_path(ctx, ~[ctx.sess.ident_of(~"Listener")]);
- let listener_ty = {
+ let listener_ty = ast::Ty {
id: ctx.sess.next_node_id(),
node: ast::ty_path(listener_ty_path,
ctx.sess.next_node_id()),
ty: @listener_ty,
mutbl: ast::m_imm
};
- let inner_ty = @{
+ let inner_ty = @ast::Ty {
id: ctx.sess.next_node_id(),
node: ast::ty_vec(vec_mt),
span: dummy_sp()
};
- @{
+ @ast::Ty {
id: ctx.sess.next_node_id(),
node: ast::ty_uniq(ast::mt {
ty: inner_ty,
let descs = do fns.map |listener| {
mk_listener_rec(ctx, *listener)
};
- let inner_expr = @{
+ let inner_expr = @ast::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()
};
- @{
+ @ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: ast::expr_vstore(inner_expr, ast::expr_vstore_uniq),
let span = listener.span;
let path = /*bad*/copy listener.path;
let descs = do listener.cmds.map |&cmd| {
- let inner = @{
+ let inner = @ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: ast::expr_lit(@no_span(ast::lit_str(@cmd))),
span: span
};
- @{
+ @ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: ast::expr_vstore(inner, ast::expr_vstore_uniq),
span: dummy_sp()
}
};
- let cmd_expr_inner = @{
+ let cmd_expr_inner = @ast::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()
};
- let cmd_expr = {
+ let cmd_expr = ast::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),
});
let cb_path = path_node_global(path);
- let cb_expr = {
+ let cb_expr = ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: ast::expr_path(cb_path),
let listener_rec_ = ast::expr_struct(listener_path,
~[cmd_field, cb_field],
option::None);
- @{
+ @ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: listener_rec_,
fn mk_fn_wrapper(ctx: @ReadyCtx, fn_path_expr: ast::expr,
span: span) -> @ast::expr {
- let call_expr = {
+ let call_expr = ast::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 = {
+ let call_stmt = no_span(ast::stmt_semi(@call_expr,
+ ctx.sess.next_node_id()));
+ let wrapper_decl = ast::fn_decl {
inputs: ~[],
- output: @{
+ output: @ast::Ty {
id: ctx.sess.next_node_id(),
node: ast::ty_nil, span: span
},
rules: ast::default_blk
});
- @{
+ @ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: ast::expr_fn(ast::ProtoBare, wrapper_decl,
}
fn mk_main(ctx: @ReadyCtx) -> @ast::item {
- let ret_ty = {
+ let ret_ty = ast::Ty {
id: ctx.sess.next_node_id(),
node: ast::ty_nil,
span: dummy_sp()
};
- let decl = {
+ let decl = ast::fn_decl {
inputs: ~[],
output: @ret_ty,
cf: ast::return_val
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 = {
+ let listener_path_expr = ast::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 = {
+ let listener_call_expr = ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: listener_call_expr_,
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 = {
+ let rustpkg_run_path_expr = ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: rustpkg_run_path_expr_,
let rustpkg_run_call_expr_ = ast::expr_call(@rustpkg_run_path_expr,
~[@listener_call_expr],
false);
- @{
+ @ast::expr {
id: ctx.sess.next_node_id(),
callee_id: ctx.sess.next_node_id(),
node: rustpkg_run_call_expr_,
match map.get(&~"vers") {
json::String(str) => {
- if pkg.vers.to_str() == str {
+ if has_id && pkg.vers.to_str() == str {
return packages;
}
}
match map.get(&~"vers") {
json::String(str) => {
- if pkg.vers.to_str() == str { None }
- else { Some(package) }
+ if has_id && pkg.vers.to_str() == str { None }
+ else { Some(package) }
}
_ => { Some(package) }
}
_ => {
os::remove_file(&db_lock);
- return result::Err(~"package db's json is not a list");
+ return result::Err(
+ ~"package db's json is not a list");
}
}
}
result::Err(err) => {
os::remove_file(&db_lock);
- return result::Err(fmt!("failed to parse package db: %s", err.to_str()));
+ return result::Err(
+ fmt!("failed to parse package db: %s",
+ err.to_str()));
}
}
}
result::Err(err) => {
os::remove_file(&db_lock);
- return result::Err(fmt!("failed to read package db: %s", err));
+ return result::Err(fmt!("failed to read package db: %s",
+ err));
}
}
} else { ~[] };
result::Ok(packages)
}
-pub fn get_pkg(id: ~str, vers: Option<~str>) -> result::Result<Package, ~str> {
+pub fn get_pkg(id: ~str,
+ vers: Option<~str>) -> result::Result<Package, ~str> {
let name = match parse_name(id) {
result::Ok(name) => name,
result::Err(err) => return result::Err(err)
match io::mk_file_writer(&db, ~[io::Create]) {
result::Ok(writer) => {
- writer.write_line(json::to_pretty_str(&json::List(_add_pkg(packages, pkg))));
+ writer.write_line(json::to_pretty_str(&json::List(
+ _add_pkg(packages, pkg))));
}
result::Err(err) => {
error(fmt!("failed to dump package db: %s", err));
match io::mk_file_writer(&db, ~[io::Create]) {
result::Ok(writer) => {
- writer.write_line(json::to_pretty_str(&json::List(_rm_pkg(packages, pkg))));
+ writer.write_line(json::to_pretty_str(&json::List(
+ _rm_pkg(packages, pkg))));
}
result::Err(err) => {
error(fmt!("failed to dump package db: %s", err));
let test_dir = dir.push(~"test");
let binary = os::args()[0];
let matches = getopts(flags, driver::optgroups()).get();
- let mut options = driver::build_session_options(binary, matches,
- diagnostic::emit);
+ let options = @{
+ crate_type: session::unknown_crate,
+ optimize: if opt { session::Aggressive } else { session::No },
+ test: test,
+ maybe_sysroot: sysroot,
+ .. *driver::build_session_options(binary, &matches, diagnostic::emit)
+ };
+ let mut crate_cfg = options.cfg;
- options.crate_type = session::unknown_crate;
- options.optimize = if opt { session::Aggressive } else { session::No };
- options.test = test;
- options.maybe_sysroot = sysroot;
+ for cfgs.each |&cfg| {
+ crate_cfg.push(attr::mk_word_item(cfg));
+ }
+ let options = @{
+ cfg: vec::append(options.cfg, crate_cfg),
+ .. *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,
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);
+ outputs = driver::build_output_filenames(input, &None, &Some(path),
+ sess);
} else {
need_dir(&lib_dir);
#[cfg(target_os = "macos")]
pub fn exe_suffix() -> ~str { ~"" }
-pub fn compile_crate(sysroot: Option<Path>, crate: &Path, dir: &Path, flags: ~[~str],
- cfgs: ~[~str], opt: bool, test: bool) -> bool {
- compile_input(sysroot, driver::file_input(*crate), dir, flags, cfgs, opt, test)
+
+// FIXME: Use workcache to only compile when needed
+pub fn compile_crate(sysroot: Option<Path>, crate: &Path, dir: &Path,
+ flags: ~[~str], cfgs: ~[~str], opt: bool,
+ test: bool) -> bool {
+ compile_input(sysroot, driver::file_input(*crate), dir, flags, cfgs,
+ opt, test)
}
-pub fn compile_str(sysroot: Option<Path>, code: ~str, dir: &Path, flags: ~[~str],
- cfgs: ~[~str], opt: bool, test: bool) -> bool {
- compile_input(sysroot, driver::str_input(code), dir, flags, cfgs, opt, test)
+pub fn compile_str(sysroot: Option<Path>, code: ~str, dir: &Path,
+ flags: ~[~str], cfgs: ~[~str], opt: bool,
+ test: bool) -> bool {
+ compile_input(sysroot, driver::str_input(code), dir, flags, cfgs,
+ opt, test)
}
#[cfg(windows)]
-pub fn link_exe(_src: &Path, _dest: &Path) -> bool{
+pub fn link_exe(_src: &Path, _dest: &Path) -> bool {
/* FIXME: Investigate how to do this on win32
Node wraps symlinks by having a .bat,
but that won't work with minGW. */