From 177f740311639165fb1464688752c01a039fa577 Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Sun, 5 Jan 2014 10:17:51 +0100 Subject: [PATCH 1/4] Command is now an enum --- src/librustpkg/context.rs | 69 ++++++++++++++++++++++++++++++--------- src/librustpkg/lib.rs | 66 ++++++++++++++----------------------- src/librustpkg/usage.rs | 21 ++++++++++++ src/librustpkg/util.rs | 30 ----------------- 4 files changed, 98 insertions(+), 88 deletions(-) diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs index 31515f0cb727c..3fb6f9caeb82c 100644 --- a/src/librustpkg/context.rs +++ b/src/librustpkg/context.rs @@ -234,85 +234,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 { + 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 } } + diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index 7051c7de058fa..43f190f37a23e 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -45,6 +45,8 @@ use workspace::determine_destination; use context::{Context, BuildContext, RustcFlags, Trans, Link, Nothing, Pretty, Analysis, Assemble, 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}; @@ -205,7 +207,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)>; @@ -281,13 +283,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 } @@ -304,17 +306,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) => { @@ -360,21 +362,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)); @@ -388,14 +390,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(); } @@ -417,14 +419,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) } } @@ -864,14 +865,8 @@ pub fn main_args(args: &[~str]) -> int { 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 { + let cmd_opt = args.iter().filter_map( |s| from_str(s.clone())).next(); + let command = match(cmd_opt) { None => { usage::general(); return 0; @@ -879,23 +874,10 @@ pub fn main_args(args: &[~str]) -> int { Some(cmd) => { let bad_option = context::flags_forbidden_for_cmd(&rustc_flags, cfgs, - *cmd, + 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() - }; + usage::usage_for_command(cmd); if bad_option { return BAD_FLAG_CODE; } @@ -909,9 +891,10 @@ pub fn main_args(args: &[~str]) -> int { }; // 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(); + let mut remaining_args: ~[~str] = args.iter().skip_while(|&s| { + let maybe_command: Option = from_str(*s); + maybe_command.is_none() + }).map(|s| s.clone()).collect(); remaining_args.shift(); let sroot = match supplied_sysroot { Some(s) => Path::new(s), @@ -923,7 +906,6 @@ pub fn main_args(args: &[~str]) -> int { 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 { @@ -935,7 +917,7 @@ pub fn main_args(args: &[~str]) -> int { }, workcache_context: api::default_context(sroot.clone(), default_workspace()).workcache_context - }.run(sub_cmd, rm_args.clone()) + }.run(command, rm_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, diff --git a/src/librustpkg/usage.rs b/src/librustpkg/usage.rs index ef6ac485b7294..a41e99f6d663d 100644 --- a/src/librustpkg/usage.rs +++ b/src/librustpkg/usage.rs @@ -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] [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(), + }; +} + + + diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 7e43fde7b3235..5f5c34dc04b82 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -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, @@ -634,25 +623,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(x: Option) -> ~[T] { match x { Some(y) => ~[y], From e1c59828b4fd1f2049b9ec21d657c2adda2fe55d Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Sun, 5 Jan 2014 10:24:08 +0100 Subject: [PATCH 2/4] Move syslog to BuildContext --- src/librustpkg/api.rs | 2 +- src/librustpkg/context.rs | 44 ++++++++++++++------------------------- src/librustpkg/lib.rs | 2 +- src/librustpkg/tests.rs | 4 ++-- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs index 0730a6fc3a210..45c37a93e3e1e 100644 --- a/src/librustpkg/api.rs +++ b/src/librustpkg/api.rs @@ -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 } } diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs index 3fb6f9caeb82c..fddfa02032cc4 100644 --- a/src/librustpkg/context.rs +++ b/src/librustpkg/context.rs @@ -26,25 +26,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 @@ -131,28 +141,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] { diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index 43f190f37a23e..39bc4c7570e52 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -913,8 +913,8 @@ pub fn main_args(args: &[~str]) -> int { cfgs: cfgs.clone(), rustc_flags: rustc_flags.clone(), use_rust_path_hack: use_rust_path_hack, - sysroot: sroot.clone(), // Currently, only tests override this }, + sysroot: sroot.clone(), // Currently, only tests override this workcache_context: api::default_context(sroot.clone(), default_workspace()).workcache_context }.run(command, rm_args.clone()) diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 2ceed4f3df7e4..aa6dab05addd5 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -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 } } From aa50ebd03ed1d1f698d0d275f9570ef53e720831 Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Sun, 5 Jan 2014 11:23:39 +0100 Subject: [PATCH 3/4] Move command line parsing to parse_args.rs --- src/librustpkg/lib.rs | 189 ++++++---------------------------- src/librustpkg/parse_args.rs | 190 +++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+), 160 deletions(-) create mode 100644 src/librustpkg/parse_args.rs diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index 39bc4c7570e52..e9c41d6b897bb 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -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,9 +41,8 @@ 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; @@ -52,7 +50,7 @@ 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; @@ -63,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; @@ -751,173 +750,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 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"); - - 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 (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 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 cmd_opt = args.iter().filter_map( |s| from_str(s.clone())).next(); - let command = 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 { - usage::usage_for_command(cmd); - if bad_option { - return BAD_FLAG_CODE; - } - else { - return 0; - } - } else { - cmd - } - } - }; - - // Pop off all flags, plus the command - let mut remaining_args: ~[~str] = args.iter().skip_while(|&s| { - let maybe_command: Option = from_str(*s); - maybe_command.is_none() - }).map(|s| s.clone()).collect(); - remaining_args.shift(); - let sroot = match supplied_sysroot { + 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); + + 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(); // 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(command, 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, diff --git a/src/librustpkg/parse_args.rs b/src/librustpkg/parse_args.rs new file mode 100644 index 0000000000000..8f21c6d3bfa68 --- /dev/null +++ b/src/librustpkg/parse_args.rs @@ -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 or the MIT license +// , 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 { + 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 = 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 + }) +} + From 4140b2950bf21a0a06c35f953f275087d4e9d5c9 Mon Sep 17 00:00:00 2001 From: Niels langager Ellegaard Date: Sun, 5 Jan 2014 12:41:56 +0100 Subject: [PATCH 4/4] Fix some of the testcases simple-lib and deeply and c-dependencies still have problems. But they were nt caused by this pull request --- src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs | 2 +- src/librustpkg/testsuite/pass/src/foo/lib.rs | 2 +- src/librustpkg/testsuite/pass/src/hello-world/main.rs | 2 +- src/librustpkg/testsuite/pass/src/install-paths/bench.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs b/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs index e5386aa701bf1..85ddd3e58d483 100644 --- a/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs +++ b/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs @@ -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 diff --git a/src/librustpkg/testsuite/pass/src/foo/lib.rs b/src/librustpkg/testsuite/pass/src/foo/lib.rs index 91fc466f8c65b..63743160d12e1 100644 --- a/src/librustpkg/testsuite/pass/src/foo/lib.rs +++ b/src/librustpkg/testsuite/pass/src/foo/lib.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f() {} +pub fn f() {} diff --git a/src/librustpkg/testsuite/pass/src/hello-world/main.rs b/src/librustpkg/testsuite/pass/src/hello-world/main.rs index d4c65954fe629..1d18a3aaa4315 100644 --- a/src/librustpkg/testsuite/pass/src/hello-world/main.rs +++ b/src/librustpkg/testsuite/pass/src/hello-world/main.rs @@ -19,5 +19,5 @@ The test runner should check that, after `rustpkg build hello-world`: */ fn main() { - println(~"Hello world!"); + println("Hello world!"); } diff --git a/src/librustpkg/testsuite/pass/src/install-paths/bench.rs b/src/librustpkg/testsuite/pass/src/install-paths/bench.rs index 3d22ddc57faa3..a886a7e0079d9 100644 --- a/src/librustpkg/testsuite/pass/src/install-paths/bench.rs +++ b/src/librustpkg/testsuite/pass/src/install-paths/bench.rs @@ -9,7 +9,7 @@ // except according to those terms. #[bench] -fn g() { +pub fn g() { let mut x = 0; while(x < 1000) { x += 1;