auto merge of #11327 : nielsle/rust/rustpkg_argparse, r=alexcrichton
Rearrange some code in rustpkg: * Move command line argument parsing to parse_args.rs * Introduce an enum to descibe commands such as Build, Install, and Clean. * Move sysroot from Context to BuildContext, to make parse_args more modular. This is my first pull request, so please tell me if there is anything I need to do.
This commit is contained in:
commit
55bb5e584c
|
@ -49,8 +49,8 @@ pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext {
|
|||
cfgs: ~[],
|
||||
rustc_flags: RustcFlags::default(),
|
||||
use_rust_path_hack: false,
|
||||
sysroot: p
|
||||
},
|
||||
sysroot: p,
|
||||
workcache_context: c
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,25 +27,35 @@ pub struct Context {
|
|||
// FOO/src/bar-0.1 instead of FOO). The flag doesn't affect where
|
||||
// rustpkg stores build artifacts.
|
||||
use_rust_path_hack: bool,
|
||||
// The root directory containing the Rust standard libraries
|
||||
sysroot: Path
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct BuildContext {
|
||||
// Context for workcache
|
||||
workcache_context: workcache::Context,
|
||||
// Everything else
|
||||
context: Context
|
||||
// Parsed command line options
|
||||
context: Context,
|
||||
// The root directory containing the Rust standard libraries
|
||||
sysroot: Path
|
||||
}
|
||||
|
||||
impl BuildContext {
|
||||
pub fn sysroot(&self) -> Path {
|
||||
self.context.sysroot.clone()
|
||||
self.sysroot.clone()
|
||||
}
|
||||
|
||||
// Hack so that rustpkg can run either out of a rustc target dir,
|
||||
// or the host dir
|
||||
pub fn sysroot_to_use(&self) -> Path {
|
||||
self.context.sysroot_to_use()
|
||||
if !in_target(&self.sysroot) {
|
||||
self.sysroot.clone()
|
||||
} else {
|
||||
let mut p = self.sysroot.clone();
|
||||
p.pop();
|
||||
p.pop();
|
||||
p.pop();
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the flags to pass to rustc, as a vector of strings
|
||||
|
@ -132,28 +142,6 @@ pub enum StopBefore {
|
|||
}
|
||||
|
||||
impl Context {
|
||||
pub fn sysroot(&self) -> Path {
|
||||
self.sysroot.clone()
|
||||
}
|
||||
|
||||
/// Debugging
|
||||
pub fn sysroot_str(&self) -> ~str {
|
||||
self.sysroot.as_str().unwrap().to_owned()
|
||||
}
|
||||
|
||||
// Hack so that rustpkg can run either out of a rustc target dir,
|
||||
// or the host dir
|
||||
pub fn sysroot_to_use(&self) -> Path {
|
||||
if !in_target(&self.sysroot) {
|
||||
self.sysroot.clone()
|
||||
} else {
|
||||
let mut p = self.sysroot.clone();
|
||||
p.pop();
|
||||
p.pop();
|
||||
p.pop();
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the flags to pass to rustc, as a vector of strings
|
||||
pub fn flag_strs(&self) -> ~[~str] {
|
||||
|
@ -235,85 +223,122 @@ impl RustcFlags {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum Command {
|
||||
BuildCmd,
|
||||
CleanCmd,
|
||||
DoCmd,
|
||||
InfoCmd,
|
||||
InstallCmd,
|
||||
ListCmd,
|
||||
PreferCmd,
|
||||
TestCmd,
|
||||
InitCmd,
|
||||
UninstallCmd,
|
||||
UnpreferCmd,
|
||||
}
|
||||
|
||||
impl FromStr for Command {
|
||||
|
||||
fn from_str(s: &str) -> Option<Command> {
|
||||
match s {
|
||||
&"build" => Some(BuildCmd),
|
||||
&"clean" => Some(CleanCmd),
|
||||
&"do" => Some(DoCmd),
|
||||
&"info" => Some(InfoCmd),
|
||||
&"install" => Some(InstallCmd),
|
||||
&"list" => Some(ListCmd),
|
||||
&"prefer" => Some(PreferCmd),
|
||||
&"test" => Some(TestCmd),
|
||||
&"init" => Some(InitCmd),
|
||||
&"uninstall" => Some(UninstallCmd),
|
||||
&"unprefer" => Some(UnpreferCmd),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if any of the flags given are incompatible with the cmd
|
||||
pub fn flags_forbidden_for_cmd(flags: &RustcFlags,
|
||||
cfgs: &[~str],
|
||||
cmd: &str, user_supplied_opt_level: bool) -> bool {
|
||||
cmd: Command, user_supplied_opt_level: bool) -> bool {
|
||||
let complain = |s| {
|
||||
println!("The {} option can only be used with the `build` command:
|
||||
rustpkg [options..] build {} [package-ID]", s, s);
|
||||
};
|
||||
|
||||
if flags.linker.is_some() && cmd != "build" && cmd != "install" {
|
||||
if flags.linker.is_some() && cmd != BuildCmd && cmd != InstallCmd {
|
||||
println("The --linker option can only be used with the build or install commands.");
|
||||
return true;
|
||||
}
|
||||
if flags.link_args.is_some() && cmd != "build" && cmd != "install" {
|
||||
if flags.link_args.is_some() && cmd != BuildCmd && cmd != InstallCmd {
|
||||
println("The --link-args option can only be used with the build or install commands.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if !cfgs.is_empty() && cmd != "build" && cmd != "install" && cmd != "test" {
|
||||
if !cfgs.is_empty() && cmd != BuildCmd && cmd != InstallCmd && cmd != TestCmd {
|
||||
println("The --cfg option can only be used with the build, test, or install commands.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if user_supplied_opt_level && cmd != "build" && cmd != "install" {
|
||||
if user_supplied_opt_level && cmd != BuildCmd && cmd != InstallCmd {
|
||||
println("The -O and --opt-level options can only be used with the build \
|
||||
or install commands.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if flags.save_temps && cmd != "build" && cmd != "install" {
|
||||
if flags.save_temps && cmd != BuildCmd && cmd != InstallCmd {
|
||||
println("The --save-temps option can only be used with the build \
|
||||
or install commands.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if flags.target.is_some() && cmd != "build" && cmd != "install" {
|
||||
if flags.target.is_some() && cmd != BuildCmd && cmd != InstallCmd {
|
||||
println("The --target option can only be used with the build \
|
||||
or install commands.");
|
||||
return true;
|
||||
}
|
||||
if flags.target_cpu.is_some() && cmd != "build" && cmd != "install" {
|
||||
if flags.target_cpu.is_some() && cmd != BuildCmd && cmd != InstallCmd {
|
||||
println("The --target-cpu option can only be used with the build \
|
||||
or install commands.");
|
||||
return true;
|
||||
}
|
||||
if flags.experimental_features.is_some() && cmd != "build" && cmd != "install" {
|
||||
if flags.experimental_features.is_some() && cmd != BuildCmd && cmd != InstallCmd {
|
||||
println("The -Z option can only be used with the build or install commands.");
|
||||
return true;
|
||||
}
|
||||
|
||||
match flags.compile_upto {
|
||||
Link if cmd != "build" => {
|
||||
Link if cmd != BuildCmd => {
|
||||
complain("--no-link");
|
||||
true
|
||||
}
|
||||
Trans if cmd != "build" => {
|
||||
Trans if cmd != BuildCmd => {
|
||||
complain("--no-trans");
|
||||
true
|
||||
}
|
||||
Assemble if cmd != "build" => {
|
||||
Assemble if cmd != BuildCmd => {
|
||||
complain("-S");
|
||||
true
|
||||
}
|
||||
Pretty if cmd != "build" => {
|
||||
Pretty if cmd != BuildCmd => {
|
||||
complain("--pretty");
|
||||
true
|
||||
}
|
||||
Analysis if cmd != "build" => {
|
||||
Analysis if cmd != BuildCmd => {
|
||||
complain("--parse-only");
|
||||
true
|
||||
}
|
||||
LLVMCompileBitcode if cmd != "build" => {
|
||||
LLVMCompileBitcode if cmd != BuildCmd => {
|
||||
complain("--emit-llvm");
|
||||
true
|
||||
}
|
||||
LLVMAssemble if cmd != "build" => {
|
||||
LLVMAssemble if cmd != BuildCmd => {
|
||||
complain("--emit-llvm");
|
||||
true
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,8 @@ extern mod extra;
|
|||
extern mod rustc;
|
||||
extern mod syntax;
|
||||
|
||||
use std::{os, result, run, str, task};
|
||||
use std::{os, run, str, task};
|
||||
use std::io::process;
|
||||
use std::hashmap::HashSet;
|
||||
use std::io;
|
||||
use std::io::fs;
|
||||
pub use std::path::Path;
|
||||
|
@ -32,9 +31,9 @@ use rustc::driver::{driver, session};
|
|||
use rustc::metadata::filesearch;
|
||||
use rustc::metadata::filesearch::rust_path;
|
||||
use rustc::util::sha2;
|
||||
use extra::{getopts};
|
||||
use syntax::{ast, diagnostic};
|
||||
use messages::{error, warn, note};
|
||||
use parse_args::{ParseResult, parse_args};
|
||||
use path_util::{build_pkg_id_in_workspace, built_test_in_workspace};
|
||||
use path_util::in_rust_path;
|
||||
use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace};
|
||||
|
@ -42,15 +41,16 @@ use path_util::{target_executable_in_workspace, target_library_in_workspace, dir
|
|||
use source_control::{CheckedOutSources, is_git_dir, make_read_only};
|
||||
use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, cwd_to_workspace};
|
||||
use workspace::determine_destination;
|
||||
use context::{Context, BuildContext,
|
||||
RustcFlags, Trans, Link, Nothing, Pretty, Analysis, Assemble,
|
||||
LLVMAssemble, LLVMCompileBitcode};
|
||||
use context::{BuildContext, Trans, Nothing, Pretty, Analysis,
|
||||
LLVMAssemble, LLVMCompileBitcode};
|
||||
use context::{Command, BuildCmd, CleanCmd, DoCmd, InfoCmd, InstallCmd, ListCmd,
|
||||
PreferCmd, TestCmd, InitCmd, UninstallCmd, UnpreferCmd};
|
||||
use crate_id::CrateId;
|
||||
use package_source::PkgSrc;
|
||||
use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench};
|
||||
use target::{Main, Tests, MaybeCustom, Inferred, JustOne};
|
||||
use workcache_support::digest_only_date;
|
||||
use exit_codes::{COPY_FAILED_CODE, BAD_FLAG_CODE};
|
||||
use exit_codes::{COPY_FAILED_CODE};
|
||||
|
||||
pub mod api;
|
||||
mod conditions;
|
||||
|
@ -61,6 +61,7 @@ mod installed_packages;
|
|||
mod messages;
|
||||
pub mod crate_id;
|
||||
pub mod package_source;
|
||||
mod parse_args;
|
||||
mod path_util;
|
||||
mod source_control;
|
||||
mod target;
|
||||
|
@ -207,7 +208,7 @@ impl<'a> PkgScript<'a> {
|
|||
}
|
||||
|
||||
pub trait CtxMethods {
|
||||
fn run(&self, cmd: &str, args: ~[~str]);
|
||||
fn run(&self, cmd: Command, args: ~[~str]);
|
||||
fn do_cmd(&self, _cmd: &str, _pkgname: &str);
|
||||
/// Returns a pair of the selected package ID, and the destination workspace
|
||||
fn build_args(&self, args: ~[~str], what: &WhatToBuild) -> Option<(CrateId, Path)>;
|
||||
|
@ -283,13 +284,13 @@ impl CtxMethods for BuildContext {
|
|||
Some((crateid, dest_ws))
|
||||
}
|
||||
}
|
||||
fn run(&self, cmd: &str, args: ~[~str]) {
|
||||
fn run(&self, cmd: Command, args: ~[~str]) {
|
||||
let cwd = os::getcwd();
|
||||
match cmd {
|
||||
"build" => {
|
||||
BuildCmd => {
|
||||
self.build_args(args, &WhatToBuild::new(MaybeCustom, Everything));
|
||||
}
|
||||
"clean" => {
|
||||
CleanCmd => {
|
||||
if args.len() < 1 {
|
||||
match cwd_to_workspace() {
|
||||
None => { usage::clean(); return }
|
||||
|
@ -306,17 +307,17 @@ impl CtxMethods for BuildContext {
|
|||
self.clean(&cwd, &crateid); // tjc: should use workspace, not cwd
|
||||
}
|
||||
}
|
||||
"do" => {
|
||||
DoCmd => {
|
||||
if args.len() < 2 {
|
||||
return usage::do_cmd();
|
||||
}
|
||||
|
||||
self.do_cmd(args[0].clone(), args[1].clone());
|
||||
}
|
||||
"info" => {
|
||||
InfoCmd => {
|
||||
self.info();
|
||||
}
|
||||
"install" => {
|
||||
InstallCmd => {
|
||||
if args.len() < 1 {
|
||||
match cwd_to_workspace() {
|
||||
None if dir_has_crate_file(&cwd) => {
|
||||
|
@ -362,21 +363,21 @@ impl CtxMethods for BuildContext {
|
|||
}
|
||||
}
|
||||
}
|
||||
"list" => {
|
||||
ListCmd => {
|
||||
println("Installed packages:");
|
||||
installed_packages::list_installed_packages(|pkg_id| {
|
||||
pkg_id.path.display().with_str(|s| println(s));
|
||||
true
|
||||
});
|
||||
}
|
||||
"prefer" => {
|
||||
PreferCmd => {
|
||||
if args.len() < 1 {
|
||||
return usage::uninstall();
|
||||
}
|
||||
|
||||
self.prefer(args[0], None);
|
||||
}
|
||||
"test" => {
|
||||
TestCmd => {
|
||||
// Build the test executable
|
||||
let maybe_id_and_workspace = self.build_args(args,
|
||||
&WhatToBuild::new(MaybeCustom, Tests));
|
||||
|
@ -390,14 +391,14 @@ impl CtxMethods for BuildContext {
|
|||
}
|
||||
}
|
||||
}
|
||||
"init" => {
|
||||
InitCmd => {
|
||||
if args.len() != 0 {
|
||||
return usage::init();
|
||||
} else {
|
||||
self.init();
|
||||
}
|
||||
}
|
||||
"uninstall" => {
|
||||
UninstallCmd => {
|
||||
if args.len() < 1 {
|
||||
return usage::uninstall();
|
||||
}
|
||||
|
@ -419,14 +420,13 @@ impl CtxMethods for BuildContext {
|
|||
});
|
||||
}
|
||||
}
|
||||
"unprefer" => {
|
||||
UnpreferCmd => {
|
||||
if args.len() < 1 {
|
||||
return usage::unprefer();
|
||||
}
|
||||
|
||||
self.unprefer(args[0], None);
|
||||
}
|
||||
_ => fail!("I don't know the command `{}`", cmd)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -752,192 +752,43 @@ pub fn main() {
|
|||
}
|
||||
|
||||
pub fn main_args(args: &[~str]) -> int {
|
||||
let opts = ~[getopts::optflag("h"), getopts::optflag("help"),
|
||||
getopts::optflag("no-link"),
|
||||
getopts::optflag("no-trans"),
|
||||
// n.b. Ignores different --pretty options for now
|
||||
getopts::optflag("pretty"),
|
||||
getopts::optflag("parse-only"),
|
||||
getopts::optflag("S"), getopts::optflag("assembly"),
|
||||
getopts::optmulti("c"), getopts::optmulti("cfg"),
|
||||
getopts::optflag("v"), getopts::optflag("version"),
|
||||
getopts::optflag("r"), getopts::optflag("rust-path-hack"),
|
||||
getopts::optopt("sysroot"),
|
||||
getopts::optflag("emit-llvm"),
|
||||
getopts::optopt("linker"),
|
||||
getopts::optopt("link-args"),
|
||||
getopts::optopt("opt-level"),
|
||||
getopts::optflag("O"),
|
||||
getopts::optflag("save-temps"),
|
||||
getopts::optopt("target"),
|
||||
getopts::optopt("target-cpu"),
|
||||
getopts::optmulti("Z") ];
|
||||
let matches = &match getopts::getopts(args, opts) {
|
||||
result::Ok(m) => m,
|
||||
result::Err(f) => {
|
||||
error(format!("{}", f.to_err_msg()));
|
||||
|
||||
return 1;
|
||||
let (command, args, context, supplied_sysroot) = match parse_args(args) {
|
||||
Ok(ParseResult {
|
||||
command: cmd,
|
||||
args: args,
|
||||
context: ctx,
|
||||
sysroot: sroot}) => (cmd, args, ctx, sroot),
|
||||
Err(error_code) => {
|
||||
debug!("Parsing failed. Returning error code {}", error_code);
|
||||
return error_code
|
||||
}
|
||||
};
|
||||
let help = matches.opt_present("h") ||
|
||||
matches.opt_present("help");
|
||||
let no_link = matches.opt_present("no-link");
|
||||
let no_trans = matches.opt_present("no-trans");
|
||||
let supplied_sysroot = matches.opt_str("sysroot");
|
||||
let generate_asm = matches.opt_present("S") ||
|
||||
matches.opt_present("assembly");
|
||||
let parse_only = matches.opt_present("parse-only");
|
||||
let pretty = matches.opt_present("pretty");
|
||||
let emit_llvm = matches.opt_present("emit-llvm");
|
||||
debug!("Finished parsing commandline args {:?}", args);
|
||||
debug!(" Using command: {:?}", command);
|
||||
debug!(" Using args {:?}", args);
|
||||
debug!(" Using cflags: {:?}", context.rustc_flags);
|
||||
debug!(" Using rust_path_hack {:b}", context.use_rust_path_hack);
|
||||
debug!(" Using cfgs: {:?}", context.cfgs);
|
||||
debug!(" Using supplied_sysroot: {:?}", supplied_sysroot);
|
||||
|
||||
if matches.opt_present("v") ||
|
||||
matches.opt_present("version") {
|
||||
rustc::version(args[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
let use_rust_path_hack = matches.opt_present("r") ||
|
||||
matches.opt_present("rust-path-hack");
|
||||
|
||||
let linker = matches.opt_str("linker");
|
||||
let link_args = matches.opt_str("link-args");
|
||||
let cfgs = matches.opt_strs("cfg") + matches.opt_strs("c");
|
||||
let mut user_supplied_opt_level = true;
|
||||
let opt_level = match matches.opt_str("opt-level") {
|
||||
Some(~"0") => session::No,
|
||||
Some(~"1") => session::Less,
|
||||
Some(~"2") => session::Default,
|
||||
Some(~"3") => session::Aggressive,
|
||||
_ if matches.opt_present("O") => session::Default,
|
||||
_ => {
|
||||
user_supplied_opt_level = false;
|
||||
session::No
|
||||
}
|
||||
};
|
||||
|
||||
let save_temps = matches.opt_present("save-temps");
|
||||
let target = matches.opt_str("target");
|
||||
let target_cpu = matches.opt_str("target-cpu");
|
||||
let experimental_features = {
|
||||
let strs = matches.opt_strs("Z");
|
||||
if matches.opt_present("Z") {
|
||||
Some(strs)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let mut args = matches.free.clone();
|
||||
args.shift();
|
||||
|
||||
if (args.len() < 1) {
|
||||
usage::general();
|
||||
return 1;
|
||||
}
|
||||
|
||||
let rustc_flags = RustcFlags {
|
||||
linker: linker,
|
||||
link_args: link_args,
|
||||
optimization_level: opt_level,
|
||||
compile_upto: if no_trans {
|
||||
Trans
|
||||
} else if no_link {
|
||||
Link
|
||||
} else if pretty {
|
||||
Pretty
|
||||
} else if parse_only {
|
||||
Analysis
|
||||
} else if emit_llvm && generate_asm {
|
||||
LLVMAssemble
|
||||
} else if generate_asm {
|
||||
Assemble
|
||||
} else if emit_llvm {
|
||||
LLVMCompileBitcode
|
||||
} else {
|
||||
Nothing
|
||||
},
|
||||
save_temps: save_temps,
|
||||
target: target,
|
||||
target_cpu: target_cpu,
|
||||
additional_library_paths:
|
||||
HashSet::new(), // No way to set this from the rustpkg command line
|
||||
experimental_features: experimental_features
|
||||
};
|
||||
|
||||
let mut cmd_opt = None;
|
||||
for a in args.iter() {
|
||||
if util::is_cmd(*a) {
|
||||
cmd_opt = Some(a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let cmd = match cmd_opt {
|
||||
None => {
|
||||
usage::general();
|
||||
return 0;
|
||||
}
|
||||
Some(cmd) => {
|
||||
let bad_option = context::flags_forbidden_for_cmd(&rustc_flags,
|
||||
cfgs,
|
||||
*cmd,
|
||||
user_supplied_opt_level);
|
||||
if help || bad_option {
|
||||
match *cmd {
|
||||
~"build" => usage::build(),
|
||||
~"clean" => usage::clean(),
|
||||
~"do" => usage::do_cmd(),
|
||||
~"info" => usage::info(),
|
||||
~"install" => usage::install(),
|
||||
~"list" => usage::list(),
|
||||
~"prefer" => usage::prefer(),
|
||||
~"test" => usage::test(),
|
||||
~"init" => usage::init(),
|
||||
~"uninstall" => usage::uninstall(),
|
||||
~"unprefer" => usage::unprefer(),
|
||||
_ => usage::general()
|
||||
};
|
||||
if bad_option {
|
||||
return BAD_FLAG_CODE;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
cmd
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Pop off all flags, plus the command
|
||||
let remaining_args = args.iter().skip_while(|s| !util::is_cmd(**s));
|
||||
// I had to add this type annotation to get the code to typecheck
|
||||
let mut remaining_args: ~[~str] = remaining_args.map(|s| (*s).clone()).collect();
|
||||
remaining_args.shift();
|
||||
let sroot = match supplied_sysroot {
|
||||
let sysroot = match supplied_sysroot {
|
||||
Some(s) => Path::new(s),
|
||||
_ => filesearch::get_or_default_sysroot()
|
||||
};
|
||||
|
||||
debug!("Using sysroot: {}", sroot.display());
|
||||
debug!("Using sysroot: {}", sysroot.display());
|
||||
let ws = default_workspace();
|
||||
debug!("Will store workcache in {}", ws.display());
|
||||
|
||||
let rm_args = remaining_args.clone();
|
||||
let sub_cmd = cmd.clone();
|
||||
// Wrap the rest in task::try in case of a condition failure in a task
|
||||
let result = do task::try {
|
||||
BuildContext {
|
||||
context: Context {
|
||||
cfgs: cfgs.clone(),
|
||||
rustc_flags: rustc_flags.clone(),
|
||||
use_rust_path_hack: use_rust_path_hack,
|
||||
sysroot: sroot.clone(), // Currently, only tests override this
|
||||
},
|
||||
workcache_context: api::default_context(sroot.clone(),
|
||||
context: context,
|
||||
sysroot: sysroot.clone(), // Currently, only tests override this
|
||||
workcache_context: api::default_context(sysroot.clone(),
|
||||
default_workspace()).workcache_context
|
||||
}.run(sub_cmd, rm_args.clone())
|
||||
}.run(command, args.clone())
|
||||
};
|
||||
// FIXME #9262: This is using the same error code for all errors,
|
||||
// and at least one test case succeeds if rustpkg returns COPY_FAILED_CODE,
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
// Copyright 2012-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 context::{Context, RustcFlags, Trans, Link, Nothing, Pretty, Analysis, Assemble,
|
||||
LLVMAssemble, LLVMCompileBitcode};
|
||||
use context::{Command, flags_forbidden_for_cmd};
|
||||
use rustc::version;
|
||||
use exit_codes::{BAD_FLAG_CODE};
|
||||
use rustc::driver::{session};
|
||||
|
||||
use usage;
|
||||
|
||||
use extra::{getopts};
|
||||
use std::{result};
|
||||
use std::hashmap::HashSet;
|
||||
|
||||
/// Result of parsing command line arguments
|
||||
pub struct ParseResult {
|
||||
// Command
|
||||
command: Command,
|
||||
// Args
|
||||
args: ~[~str],
|
||||
// Parsed command line flags
|
||||
context: Context,
|
||||
// Path to system root
|
||||
sysroot: Option<~str>
|
||||
}
|
||||
|
||||
/// Parses command line arguments of rustpkg.
|
||||
/// Returns a triplet (command, remaining_args, context)
|
||||
pub fn parse_args(args: &[~str]) -> Result<ParseResult, int> {
|
||||
let opts = ~[ getopts::optflag("no-link"),
|
||||
getopts::optflag("no-trans"),
|
||||
// n.b. Ignores different --pretty options for now
|
||||
getopts::optflag("pretty"),
|
||||
getopts::optflag("parse-only"),
|
||||
getopts::optflag("S"), getopts::optflag("assembly"),
|
||||
getopts::optmulti("c"), getopts::optmulti("cfg"),
|
||||
getopts::optflag("v"), getopts::optflag("version"),
|
||||
getopts::optflag("r"), getopts::optflag("rust-path-hack"),
|
||||
getopts::optopt("sysroot"),
|
||||
getopts::optflag("emit-llvm"),
|
||||
getopts::optopt("linker"),
|
||||
getopts::optopt("link-args"),
|
||||
getopts::optopt("opt-level"),
|
||||
getopts::optflag("O"),
|
||||
getopts::optflag("save-temps"),
|
||||
getopts::optopt("target"),
|
||||
getopts::optopt("target-cpu"),
|
||||
getopts::optmulti("Z") ];
|
||||
let matches = &match getopts::getopts(args, opts) {
|
||||
result::Ok(m) => m,
|
||||
result::Err(f) => {
|
||||
error!("{}", f.to_err_msg());
|
||||
return Err(1);
|
||||
}
|
||||
};
|
||||
let no_link = matches.opt_present("no-link");
|
||||
let no_trans = matches.opt_present("no-trans");
|
||||
let supplied_sysroot = matches.opt_str("sysroot");
|
||||
let generate_asm = matches.opt_present("S") ||
|
||||
matches.opt_present("assembly");
|
||||
let parse_only = matches.opt_present("parse-only");
|
||||
let pretty = matches.opt_present("pretty");
|
||||
let emit_llvm = matches.opt_present("emit-llvm");
|
||||
|
||||
if matches.opt_present("v") ||
|
||||
matches.opt_present("version") {
|
||||
version(args[0]);
|
||||
return Err(0);
|
||||
}
|
||||
|
||||
let use_rust_path_hack = matches.opt_present("r") ||
|
||||
matches.opt_present("rust-path-hack");
|
||||
|
||||
let linker = matches.opt_str("linker");
|
||||
let link_args = matches.opt_str("link-args");
|
||||
let cfgs = matches.opt_strs("cfg") + matches.opt_strs("c");
|
||||
let mut user_supplied_opt_level = true;
|
||||
let opt_level = match matches.opt_str("opt-level") {
|
||||
Some(~"0") => session::No,
|
||||
Some(~"1") => session::Less,
|
||||
Some(~"2") => session::Default,
|
||||
Some(~"3") => session::Aggressive,
|
||||
_ if matches.opt_present("O") => session::Default,
|
||||
_ => {
|
||||
user_supplied_opt_level = false;
|
||||
session::No
|
||||
}
|
||||
};
|
||||
|
||||
let save_temps = matches.opt_present("save-temps");
|
||||
let target = matches.opt_str("target");
|
||||
let target_cpu = matches.opt_str("target-cpu");
|
||||
let experimental_features = {
|
||||
let strs = matches.opt_strs("Z");
|
||||
if matches.opt_present("Z") {
|
||||
Some(strs)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let mut args = matches.free.clone();
|
||||
args.shift();
|
||||
|
||||
if (args.len() < 1) {
|
||||
usage::general();
|
||||
return Err(1);
|
||||
}
|
||||
|
||||
let rustc_flags = RustcFlags {
|
||||
linker: linker,
|
||||
link_args: link_args,
|
||||
optimization_level: opt_level,
|
||||
compile_upto: if no_trans {
|
||||
Trans
|
||||
} else if no_link {
|
||||
Link
|
||||
} else if pretty {
|
||||
Pretty
|
||||
} else if parse_only {
|
||||
Analysis
|
||||
} else if emit_llvm && generate_asm {
|
||||
LLVMAssemble
|
||||
} else if generate_asm {
|
||||
Assemble
|
||||
} else if emit_llvm {
|
||||
LLVMCompileBitcode
|
||||
} else {
|
||||
Nothing
|
||||
},
|
||||
save_temps: save_temps,
|
||||
target: target,
|
||||
target_cpu: target_cpu,
|
||||
additional_library_paths:
|
||||
HashSet::new(), // No way to set this from the rustpkg command line
|
||||
experimental_features: experimental_features
|
||||
};
|
||||
|
||||
let cmd_opt = args.iter().filter_map( |s| from_str(s.clone())).next();
|
||||
let command = match(cmd_opt){
|
||||
None => {
|
||||
debug!("No legal command. Returning 0");
|
||||
usage::general();
|
||||
return Err(0);
|
||||
}
|
||||
Some(cmd) => {
|
||||
let bad_option = flags_forbidden_for_cmd(&rustc_flags,
|
||||
cfgs,
|
||||
cmd,
|
||||
user_supplied_opt_level);
|
||||
if bad_option {
|
||||
usage::usage_for_command(cmd);
|
||||
debug!("Bad option, returning BAD_FLAG_CODE");
|
||||
return Err(BAD_FLAG_CODE);
|
||||
} else {
|
||||
cmd
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Pop off all flags, plus the command
|
||||
let mut remaining_args: ~[~str] = args.iter().skip_while(|&s| {
|
||||
let maybe_command: Option<Command> = from_str(*s);
|
||||
maybe_command.is_none()
|
||||
}).map(|s| s.clone()).collect();
|
||||
remaining_args.shift();
|
||||
|
||||
let context = Context{
|
||||
rustc_flags: rustc_flags,
|
||||
cfgs: cfgs,
|
||||
use_rust_path_hack: use_rust_path_hack,
|
||||
};
|
||||
Ok(ParseResult {
|
||||
command: command,
|
||||
args: remaining_args,
|
||||
context: context,
|
||||
sysroot: supplied_sysroot
|
||||
})
|
||||
}
|
||||
|
|
@ -54,8 +54,8 @@ fn fake_ctxt(sysroot: Path, workspace: &Path) -> BuildContext {
|
|||
rustc_flags: RustcFlags::default(),
|
||||
|
||||
use_rust_path_hack: false,
|
||||
sysroot: sysroot
|
||||
}
|
||||
},
|
||||
sysroot: sysroot
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ pub fn main() {
|
|||
[~"-c"],
|
||||
[~"foo.c"],
|
||||
"foo");
|
||||
let out_p = Path::new(out_path);
|
||||
let out_p = Path::new(out_path.unwrap());
|
||||
out_p.as_str().unwrap().to_owned()
|
||||
};
|
||||
out_path
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn f() {}
|
||||
pub fn f() {}
|
||||
|
|
|
@ -19,5 +19,5 @@ The test runner should check that, after `rustpkg build hello-world`:
|
|||
*/
|
||||
|
||||
fn main() {
|
||||
println(~"Hello world!");
|
||||
println("Hello world!");
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
#[bench]
|
||||
fn g() {
|
||||
pub fn g() {
|
||||
let mut x = 0;
|
||||
while(x < 1000) {
|
||||
x += 1;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use context::Command;
|
||||
|
||||
pub fn general() {
|
||||
println("Usage: rustpkg [options] <cmd> [args..]
|
||||
|
||||
|
@ -154,3 +156,22 @@ This will turn the current working directory into a workspace. The first
|
|||
command you run when starting off a new project.
|
||||
");
|
||||
}
|
||||
|
||||
pub fn usage_for_command(command: Command){
|
||||
match command {
|
||||
BuildCmd => build(),
|
||||
CleanCmd => clean(),
|
||||
DoCmd => do_cmd(),
|
||||
InfoCmd => info(),
|
||||
InstallCmd => install(),
|
||||
ListCmd => list(),
|
||||
PreferCmd => prefer(),
|
||||
TestCmd => test(),
|
||||
InitCmd => init(),
|
||||
UninstallCmd => uninstall(),
|
||||
UnpreferCmd => unprefer(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -41,13 +41,6 @@ pub use target::{lib_name_of, lib_crate_filename, WhatToBuild, MaybeCustom, Infe
|
|||
use workcache_support::{digest_file_with_date, digest_only_date};
|
||||
use messages::error;
|
||||
|
||||
// It would be nice to have the list of commands in just one place -- for example,
|
||||
// you could update the match in rustpkg.rc but forget to update this list. I think
|
||||
// that should be fixed.
|
||||
static COMMANDS: &'static [&'static str] =
|
||||
&["build", "clean", "do", "info", "init", "install", "list", "prefer", "test", "uninstall",
|
||||
"unprefer"];
|
||||
|
||||
|
||||
pub type ExitCode = int; // For now
|
||||
|
||||
|
@ -63,10 +56,6 @@ impl ToStr for Pkg {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_cmd(cmd: &str) -> bool {
|
||||
COMMANDS.iter().any(|&c| c == cmd)
|
||||
}
|
||||
|
||||
struct ListenerFn {
|
||||
cmds: ~[~str],
|
||||
span: codemap::Span,
|
||||
|
@ -636,25 +625,6 @@ pub fn mk_string_lit(s: @str) -> ast::lit {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::is_cmd;
|
||||
|
||||
#[test]
|
||||
fn test_is_cmd() {
|
||||
assert!(is_cmd("build"));
|
||||
assert!(is_cmd("clean"));
|
||||
assert!(is_cmd("do"));
|
||||
assert!(is_cmd("info"));
|
||||
assert!(is_cmd("install"));
|
||||
assert!(is_cmd("prefer"));
|
||||
assert!(is_cmd("test"));
|
||||
assert!(is_cmd("uninstall"));
|
||||
assert!(is_cmd("unprefer"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn option_to_vec<T>(x: Option<T>) -> ~[T] {
|
||||
match x {
|
||||
Some(y) => ~[y],
|
||||
|
|
Loading…
Reference in New Issue