mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 00:09:33 +03:00
Merge pull request #3005 from rtfeldman/fix-clap
Fix clap argument parsing
This commit is contained in:
commit
fcfe66f84d
235
cli/src/lib.rs
235
cli/src/lib.rs
@ -40,7 +40,6 @@ pub const FLAG_LIB: &str = "lib";
|
||||
pub const FLAG_NO_LINK: &str = "no-link";
|
||||
pub const FLAG_TARGET: &str = "target";
|
||||
pub const FLAG_TIME: &str = "time";
|
||||
pub const FLAG_LINK: &str = "roc-linker";
|
||||
pub const FLAG_LINKER: &str = "linker";
|
||||
pub const FLAG_PRECOMPILED: &str = "precompiled-host";
|
||||
pub const FLAG_VALGRIND: &str = "valgrind";
|
||||
@ -53,34 +52,63 @@ pub const ARGS_FOR_APP: &str = "ARGS_FOR_APP";
|
||||
const VERSION: &str = include_str!("../../version.txt");
|
||||
|
||||
pub fn build_app<'a>() -> Command<'a> {
|
||||
let flag_optimize = Arg::new(FLAG_OPTIMIZE)
|
||||
.long(FLAG_OPTIMIZE)
|
||||
.help("Optimize the compiled program to run faster. (Optimization takes time to complete.)")
|
||||
.requires(ROC_FILE)
|
||||
.required(false);
|
||||
|
||||
let flag_opt_size = Arg::new(FLAG_OPT_SIZE)
|
||||
.long(FLAG_OPT_SIZE)
|
||||
.help("Optimize the compiled program to have a small binary size. (Optimization takes time to complete.)")
|
||||
.required(false);
|
||||
|
||||
let flag_dev = Arg::new(FLAG_DEV)
|
||||
.long(FLAG_DEV)
|
||||
.help("Make compilation finish as soon as possible, at the expense of runtime performance.")
|
||||
.required(false);
|
||||
|
||||
let flag_debug = Arg::new(FLAG_DEBUG)
|
||||
.long(FLAG_DEBUG)
|
||||
.help("Store LLVM debug information in the generated program.")
|
||||
.requires(ROC_FILE)
|
||||
.required(false);
|
||||
|
||||
let flag_valgrind = Arg::new(FLAG_VALGRIND)
|
||||
.long(FLAG_VALGRIND)
|
||||
.help("Some assembly instructions are not supported by valgrind, this flag prevents those from being output when building the host.")
|
||||
.required(false);
|
||||
|
||||
let flag_time = Arg::new(FLAG_TIME)
|
||||
.long(FLAG_TIME)
|
||||
.help("Prints detailed compilation time information.")
|
||||
.required(false);
|
||||
|
||||
let flag_linker = Arg::new(FLAG_LINKER)
|
||||
.long(FLAG_LINKER)
|
||||
.help("Sets which linker to use. The surgical linker is enabled by default only when building for wasm32 or x86_64 Linux, because those are the only targets it currently supports. Otherwise the legacy linker is used by default.")
|
||||
.possible_values(["surgical", "legacy"])
|
||||
.required(false);
|
||||
|
||||
let flag_precompiled = Arg::new(FLAG_PRECOMPILED)
|
||||
.long(FLAG_PRECOMPILED)
|
||||
.help("Assumes the host has been precompiled and skips recompiling the host. (Enabled by default when using `roc build` with a --target other than `--target host`)")
|
||||
.possible_values(["true", "false"])
|
||||
.required(false);
|
||||
|
||||
let app = Command::new("roc")
|
||||
.version(concatcp!(VERSION, "\n"))
|
||||
.about("Runs the given .roc file, if there are no compilation errors.\nUse one of the SUBCOMMANDS below to do something else!")
|
||||
.subcommand(Command::new(CMD_BUILD)
|
||||
.about("Build a binary from the given .roc file, but don't run it")
|
||||
.arg(
|
||||
Arg::new(ROC_FILE)
|
||||
.help("The .roc file to build")
|
||||
.required(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_OPTIMIZE)
|
||||
.long(FLAG_OPTIMIZE)
|
||||
.help("Optimize your compiled Roc program to run faster. (Optimization takes time to complete.)")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_OPT_SIZE)
|
||||
.long(FLAG_OPT_SIZE)
|
||||
.help("Optimize your compiled Roc program to have a small binary size. (Optimization takes time to complete.)")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_DEV)
|
||||
.long(FLAG_DEV)
|
||||
.help("Make compilation as fast as possible. (Runtime performance may suffer)")
|
||||
.required(false),
|
||||
)
|
||||
.arg(flag_optimize.clone())
|
||||
.arg(flag_opt_size.clone())
|
||||
.arg(flag_dev.clone())
|
||||
.arg(flag_debug.clone())
|
||||
.arg(flag_time.clone())
|
||||
.arg(flag_linker.clone())
|
||||
.arg(flag_precompiled.clone())
|
||||
.arg(flag_valgrind.clone())
|
||||
.arg(
|
||||
Arg::new(FLAG_TARGET)
|
||||
.long(FLAG_TARGET)
|
||||
@ -102,42 +130,9 @@ pub fn build_app<'a>() -> Command<'a> {
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_DEBUG)
|
||||
.long(FLAG_DEBUG)
|
||||
.help("Store LLVM debug information in the generated program")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_TIME)
|
||||
.long(FLAG_TIME)
|
||||
.help("Prints detailed compilation time information.")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_LINK)
|
||||
.long(FLAG_LINK)
|
||||
.help("Deprecated in favor of --linker")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_LINKER)
|
||||
.long(FLAG_LINKER)
|
||||
.help("Sets which linker to use. The surgical linker is enabeld by default only when building for wasm32 or x86_64 Linux, because those are the only targets it currently supports. Otherwise the legacy linker is used by default.")
|
||||
.possible_values(["surgical", "legacy"])
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_PRECOMPILED)
|
||||
.long(FLAG_PRECOMPILED)
|
||||
.help("Assumes the host has been precompiled and skips recompiling the host. (Enabled by default when using a --target other than `--target host`)")
|
||||
.possible_values(["true", "false"])
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_VALGRIND)
|
||||
.long(FLAG_VALGRIND)
|
||||
.help("Some assembly instructions are not supported by valgrind, this flag prevents those from being output when building the host.")
|
||||
.required(false),
|
||||
Arg::new(ROC_FILE)
|
||||
.help("The .roc file to build")
|
||||
.required(true),
|
||||
)
|
||||
)
|
||||
.subcommand(Command::new(CMD_REPL)
|
||||
@ -145,6 +140,14 @@ pub fn build_app<'a>() -> Command<'a> {
|
||||
)
|
||||
.subcommand(Command::new(CMD_RUN)
|
||||
.about("Run a .roc file even if it has build errors")
|
||||
.arg(flag_optimize.clone())
|
||||
.arg(flag_opt_size.clone())
|
||||
.arg(flag_dev.clone())
|
||||
.arg(flag_debug.clone())
|
||||
.arg(flag_time.clone())
|
||||
.arg(flag_linker.clone())
|
||||
.arg(flag_precompiled.clone())
|
||||
.arg(flag_valgrind.clone())
|
||||
.arg(
|
||||
Arg::new(ROC_FILE)
|
||||
.help("The .roc file of an app to run")
|
||||
@ -170,12 +173,7 @@ pub fn build_app<'a>() -> Command<'a> {
|
||||
.about(concatcp!("Print the Roc compiler’s version, which is currently ", VERSION)))
|
||||
.subcommand(Command::new(CMD_CHECK)
|
||||
.about("Check the code for problems, but doesn’t build or run it")
|
||||
.arg(
|
||||
Arg::new(FLAG_TIME)
|
||||
.long(FLAG_TIME)
|
||||
.help("Prints detailed compilation time information.")
|
||||
.required(false),
|
||||
)
|
||||
.arg(flag_time.clone())
|
||||
.arg(
|
||||
Arg::new(ROC_FILE)
|
||||
.help("The .roc file of an app to check")
|
||||
@ -194,58 +192,14 @@ pub fn build_app<'a>() -> Command<'a> {
|
||||
)
|
||||
)
|
||||
.trailing_var_arg(true)
|
||||
.arg(
|
||||
Arg::new(FLAG_OPTIMIZE)
|
||||
.long(FLAG_OPTIMIZE)
|
||||
.help("Optimize the compiled program to run faster. (Optimization takes time to complete.)")
|
||||
.requires(ROC_FILE)
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_OPT_SIZE)
|
||||
.long(FLAG_OPT_SIZE)
|
||||
.help("Optimize the compiled program to have a small binary size. (Optimization takes time to complete.)")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_DEV)
|
||||
.long(FLAG_DEV)
|
||||
.help("Make compilation finish as soon as possible, at the expense of runtime performance.")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_DEBUG)
|
||||
.long(FLAG_DEBUG)
|
||||
.help("Store LLVM debug information in the generated program.")
|
||||
.requires(ROC_FILE)
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_TIME)
|
||||
.long(FLAG_TIME)
|
||||
.help("Prints detailed compilation time information.")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_LINK)
|
||||
.long(FLAG_LINK)
|
||||
.help("Deprecated in favor of --linker")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_LINKER)
|
||||
.long(FLAG_LINKER)
|
||||
.help("Sets which linker to use. The surgical linker is enabeld by default only when building for wasm32 or x86_64 Linux, because those are the only targets it currently supports. Otherwise the legacy linker is used by default.")
|
||||
.possible_values(["surgical", "legacy"])
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_PRECOMPILED)
|
||||
.long(FLAG_PRECOMPILED)
|
||||
.help("Assumes the host has been precompiled and skips recompiling the host. (Enabled by default when using `roc build` with a --target other than `--target host`)")
|
||||
.possible_values(["true", "false"])
|
||||
.required(false),
|
||||
)
|
||||
.arg(flag_optimize)
|
||||
.arg(flag_opt_size)
|
||||
.arg(flag_dev)
|
||||
.arg(flag_debug)
|
||||
.arg(flag_time)
|
||||
.arg(flag_linker)
|
||||
.arg(flag_precompiled)
|
||||
.arg(flag_valgrind)
|
||||
.arg(
|
||||
Arg::new(ROC_FILE)
|
||||
.help("The .roc file of an app to build and run")
|
||||
@ -291,18 +245,15 @@ pub enum FormatMode {
|
||||
CheckOnly,
|
||||
}
|
||||
|
||||
pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||
pub fn build(
|
||||
matches: &ArgMatches,
|
||||
config: BuildConfig,
|
||||
triple: Triple,
|
||||
link_type: LinkType,
|
||||
) -> io::Result<i32> {
|
||||
use build::build_file;
|
||||
use std::str::FromStr;
|
||||
use BuildConfig::*;
|
||||
|
||||
let target = match matches.value_of(FLAG_TARGET) {
|
||||
Some(name) => Target::from_str(name).unwrap(),
|
||||
None => Target::default(),
|
||||
};
|
||||
|
||||
let triple = target.to_triple();
|
||||
|
||||
let arena = Bump::new();
|
||||
let filename = matches.value_of(ROC_FILE).unwrap();
|
||||
|
||||
@ -321,22 +272,6 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||
let emit_debug_info = matches.is_present(FLAG_DEBUG);
|
||||
let emit_timings = matches.is_present(FLAG_TIME);
|
||||
|
||||
let link_type = match (
|
||||
matches.is_present(FLAG_LIB),
|
||||
matches.is_present(FLAG_NO_LINK),
|
||||
) {
|
||||
(true, false) => LinkType::Dylib,
|
||||
(true, true) => user_error!("build can only be one of `--lib` or `--no-link`"),
|
||||
(false, true) => LinkType::None,
|
||||
(false, false) => LinkType::Executable,
|
||||
};
|
||||
|
||||
// TODO remove FLAG_LINK from the code base anytime after the end of May 2022
|
||||
if matches.is_present(FLAG_LINK) {
|
||||
eprintln!("ERROR: The --roc-linker flag has been deprecated because the roc linker is now used automatically where it's supported. (Currently that's only x64 Linux.) No need to use --roc-linker anymore, but you can use the --linker flag to switch linkers.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// Use surgical linking when supported, or when explicitly requested with --linker surgical
|
||||
let surgically_link = if matches.is_present(FLAG_LINKER) {
|
||||
matches.value_of(FLAG_LINKER) == Some("surgical")
|
||||
@ -349,7 +284,7 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||
} else {
|
||||
// When compiling for a different target, default to assuming a precompiled host.
|
||||
// Otherwise compilation would most likely fail!
|
||||
target != Target::System
|
||||
triple != Triple::host()
|
||||
};
|
||||
let path = Path::new(filename);
|
||||
|
||||
@ -658,7 +593,7 @@ fn run_with_wasmer(_wasm_path: &std::path::Path, _args: &[String]) {
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum Target {
|
||||
pub enum Target {
|
||||
System,
|
||||
Linux32,
|
||||
Linux64,
|
||||
@ -691,7 +626,7 @@ impl Target {
|
||||
Target::Wasm32.as_str(),
|
||||
];
|
||||
|
||||
fn to_triple(self) -> Triple {
|
||||
pub fn to_triple(self) -> Triple {
|
||||
use Target::*;
|
||||
|
||||
match self {
|
||||
@ -734,15 +669,15 @@ impl std::fmt::Display for Target {
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Target {
|
||||
type Err = ();
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
match string {
|
||||
"system" => Ok(Target::System),
|
||||
"linux32" => Ok(Target::Linux32),
|
||||
"linux64" => Ok(Target::Linux64),
|
||||
"wasm32" => Ok(Target::Wasm32),
|
||||
_ => Err(()),
|
||||
_ => Err(format!("Roc does not know how to compile to {}", string)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,16 @@
|
||||
use roc_build::link::LinkType;
|
||||
use roc_cli::build::check_file;
|
||||
use roc_cli::{
|
||||
build_app, docs, format, BuildConfig, FormatMode, CMD_BUILD, CMD_CHECK, CMD_DOCS, CMD_EDIT,
|
||||
CMD_FORMAT, CMD_REPL, CMD_RUN, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_TIME,
|
||||
ROC_FILE,
|
||||
build_app, docs, format, BuildConfig, FormatMode, Target, CMD_BUILD, CMD_CHECK, CMD_DOCS,
|
||||
CMD_EDIT, CMD_FORMAT, CMD_REPL, CMD_RUN, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_LIB,
|
||||
FLAG_NO_LINK, FLAG_TARGET, FLAG_TIME, ROC_FILE,
|
||||
};
|
||||
use roc_error_macros::user_error;
|
||||
use roc_load::LoadingProblem;
|
||||
use std::fs::{self, FileType};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use target_lexicon::Triple;
|
||||
|
||||
#[macro_use]
|
||||
extern crate const_format;
|
||||
@ -31,6 +34,8 @@ fn main() -> io::Result<()> {
|
||||
build(
|
||||
&matches,
|
||||
BuildConfig::BuildAndRunIfNoErrors { roc_file_arg_index },
|
||||
Triple::host(),
|
||||
LinkType::Executable,
|
||||
)
|
||||
}
|
||||
|
||||
@ -46,7 +51,12 @@ fn main() -> io::Result<()> {
|
||||
Some(arg_index) => {
|
||||
let roc_file_arg_index = arg_index + 1; // Not sure why this +1 is necessary, but it is!
|
||||
|
||||
build(matches, BuildConfig::BuildAndRun { roc_file_arg_index })
|
||||
build(
|
||||
matches,
|
||||
BuildConfig::BuildAndRun { roc_file_arg_index },
|
||||
Triple::host(),
|
||||
LinkType::Executable,
|
||||
)
|
||||
}
|
||||
|
||||
None => {
|
||||
@ -56,7 +66,26 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some((CMD_BUILD, matches)) => Ok(build(matches, BuildConfig::BuildOnly)?),
|
||||
Some((CMD_BUILD, matches)) => {
|
||||
let target: Target = matches.value_of_t(FLAG_TARGET).unwrap_or_default();
|
||||
|
||||
let link_type = match (
|
||||
matches.is_present(FLAG_LIB),
|
||||
matches.is_present(FLAG_NO_LINK),
|
||||
) {
|
||||
(true, false) => LinkType::Dylib,
|
||||
(true, true) => user_error!("build can only be one of `--lib` or `--no-link`"),
|
||||
(false, true) => LinkType::None,
|
||||
(false, false) => LinkType::Executable,
|
||||
};
|
||||
|
||||
Ok(build(
|
||||
matches,
|
||||
BuildConfig::BuildOnly,
|
||||
target.to_triple(),
|
||||
link_type,
|
||||
)?)
|
||||
}
|
||||
Some((CMD_CHECK, matches)) => {
|
||||
let arena = bumpalo::Bump::new();
|
||||
|
||||
|
@ -35,7 +35,6 @@ pub fn infer_expr(
|
||||
abilities_store: &mut AbilitiesStore,
|
||||
expr_var: Variable,
|
||||
) -> (Content, Subs) {
|
||||
let env = solve::Env::default();
|
||||
let (solved, _) = solve::run(
|
||||
constraints,
|
||||
problems,
|
||||
|
Loading…
Reference in New Issue
Block a user