mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Merge branch 'trunk' into gui-example
This commit is contained in:
commit
a49b66e379
10 changed files with 142 additions and 46 deletions
|
@ -25,7 +25,49 @@ use roc_parse::{
|
||||||
};
|
};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
|
|
||||||
|
fn flatten_directories(files: std::vec::Vec<PathBuf>) -> std::vec::Vec<PathBuf> {
|
||||||
|
let mut to_flatten = files;
|
||||||
|
let mut files = vec![];
|
||||||
|
|
||||||
|
while let Some(path) = to_flatten.pop() {
|
||||||
|
if path.is_dir() {
|
||||||
|
match path.read_dir() {
|
||||||
|
Ok(directory) => {
|
||||||
|
for item in directory {
|
||||||
|
match item {
|
||||||
|
Ok(file) => {
|
||||||
|
let file_path = file.path();
|
||||||
|
if file_path.is_dir() {
|
||||||
|
to_flatten.push(file_path);
|
||||||
|
} else if file_path.ends_with(".roc") {
|
||||||
|
files.push(file_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(error) => internal_error!(
|
||||||
|
"There was an error while trying to read a file from a directory: {:?}",
|
||||||
|
error
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(error) => internal_error!(
|
||||||
|
"There was an error while trying to read the contents of a directory: {:?}",
|
||||||
|
error
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
files.push(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
files
|
||||||
|
}
|
||||||
|
|
||||||
pub fn format(files: std::vec::Vec<PathBuf>, mode: FormatMode) -> Result<(), String> {
|
pub fn format(files: std::vec::Vec<PathBuf>, mode: FormatMode) -> Result<(), String> {
|
||||||
|
let files = flatten_directories(files);
|
||||||
|
|
||||||
for file in files {
|
for file in files {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ use build::{BuildOutcome, BuiltFile};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use clap::{App, AppSettings, Arg, ArgMatches};
|
use clap::{App, AppSettings, Arg, ArgMatches};
|
||||||
use roc_build::link::LinkType;
|
use roc_build::link::LinkType;
|
||||||
|
use roc_error_macros::user_error;
|
||||||
use roc_load::file::LoadingProblem;
|
use roc_load::file::LoadingProblem;
|
||||||
use roc_mono::ir::OptLevel;
|
use roc_mono::ir::OptLevel;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -31,6 +32,7 @@ pub const CMD_FORMAT: &str = "format";
|
||||||
pub const FLAG_DEBUG: &str = "debug";
|
pub const FLAG_DEBUG: &str = "debug";
|
||||||
pub const FLAG_DEV: &str = "dev";
|
pub const FLAG_DEV: &str = "dev";
|
||||||
pub const FLAG_OPTIMIZE: &str = "optimize";
|
pub const FLAG_OPTIMIZE: &str = "optimize";
|
||||||
|
pub const FLAG_OPT_SIZE: &str = "opt-size";
|
||||||
pub const FLAG_LIB: &str = "lib";
|
pub const FLAG_LIB: &str = "lib";
|
||||||
pub const FLAG_BACKEND: &str = "backend";
|
pub const FLAG_BACKEND: &str = "backend";
|
||||||
pub const FLAG_TIME: &str = "time";
|
pub const FLAG_TIME: &str = "time";
|
||||||
|
@ -61,6 +63,12 @@ pub fn build_app<'a>() -> App<'a> {
|
||||||
.about("Optimize your compiled Roc program to run faster. (Optimization takes time to complete.)")
|
.about("Optimize your compiled Roc program to run faster. (Optimization takes time to complete.)")
|
||||||
.required(false),
|
.required(false),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(FLAG_OPT_SIZE)
|
||||||
|
.long(FLAG_OPT_SIZE)
|
||||||
|
.about("Optimize your compiled Roc program to have a small binary size. (Optimization takes time to complete.)")
|
||||||
|
.required(false),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(FLAG_DEV)
|
Arg::new(FLAG_DEV)
|
||||||
.long(FLAG_DEV)
|
.long(FLAG_DEV)
|
||||||
|
@ -166,6 +174,12 @@ pub fn build_app<'a>() -> App<'a> {
|
||||||
.requires(ROC_FILE)
|
.requires(ROC_FILE)
|
||||||
.required(false),
|
.required(false),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(FLAG_OPT_SIZE)
|
||||||
|
.long(FLAG_OPT_SIZE)
|
||||||
|
.about("Optimize your compiled Roc program to have a small binary size. (Optimization takes time to complete.)")
|
||||||
|
.required(false),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(FLAG_DEV)
|
Arg::new(FLAG_DEV)
|
||||||
.long(FLAG_DEV)
|
.long(FLAG_DEV)
|
||||||
|
@ -272,12 +286,14 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||||
let original_cwd = std::env::current_dir()?;
|
let original_cwd = std::env::current_dir()?;
|
||||||
let opt_level = match (
|
let opt_level = match (
|
||||||
matches.is_present(FLAG_OPTIMIZE),
|
matches.is_present(FLAG_OPTIMIZE),
|
||||||
|
matches.is_present(FLAG_OPT_SIZE),
|
||||||
matches.is_present(FLAG_DEV),
|
matches.is_present(FLAG_DEV),
|
||||||
) {
|
) {
|
||||||
(true, false) => OptLevel::Optimize,
|
(true, false, false) => OptLevel::Optimize,
|
||||||
(true, true) => panic!("development cannot be optimized!"),
|
(false, true, false) => OptLevel::Size,
|
||||||
(false, true) => OptLevel::Development,
|
(false, false, true) => OptLevel::Development,
|
||||||
(false, false) => OptLevel::Normal,
|
(false, false, false) => OptLevel::Normal,
|
||||||
|
_ => user_error!("build can be only one of `--dev`, `--optimize`, or `--opt-size`"),
|
||||||
};
|
};
|
||||||
let emit_debug_info = matches.is_present(FLAG_DEBUG);
|
let emit_debug_info = matches.is_present(FLAG_DEBUG);
|
||||||
let emit_timings = matches.is_present(FLAG_TIME);
|
let emit_timings = matches.is_present(FLAG_TIME);
|
||||||
|
|
|
@ -12,8 +12,8 @@ extern crate indoc;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod cli_run {
|
mod cli_run {
|
||||||
use cli_utils::helpers::{
|
use cli_utils::helpers::{
|
||||||
example_file, examples_dir, extract_valgrind_errors, fixture_file, known_bad_file, run_cmd,
|
example_file, examples_dir, extract_valgrind_errors, fixture_file, fixtures_dir,
|
||||||
run_roc, run_with_valgrind, Out, ValgrindError, ValgrindErrorXWhat,
|
known_bad_file, run_cmd, run_roc, run_with_valgrind, Out, ValgrindError, ValgrindErrorXWhat,
|
||||||
};
|
};
|
||||||
use roc_test_utils::assert_multiline_str_eq;
|
use roc_test_utils::assert_multiline_str_eq;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
@ -904,6 +904,15 @@ mod cli_run {
|
||||||
fn format_check_reformatting_needed() {
|
fn format_check_reformatting_needed() {
|
||||||
check_format_check_as_expected(&fixture_file("format", "NotFormatted.roc"), false);
|
check_format_check_as_expected(&fixture_file("format", "NotFormatted.roc"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_check_folders() {
|
||||||
|
// This fails, because "NotFormatted.roc" is present in this folder
|
||||||
|
check_format_check_as_expected(&fixtures_dir("format"), false);
|
||||||
|
|
||||||
|
// This doesn't fail, since only "Formatted.roc" is present in this folder
|
||||||
|
check_format_check_as_expected(&fixtures_dir("format/formatted_directory"), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
6
cli/tests/fixtures/format/formatted_directory/Formatted.roc
vendored
Normal file
6
cli/tests/fixtures/format/formatted_directory/Formatted.roc
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
app "formatted"
|
||||||
|
packages { pf: "platform" } imports []
|
||||||
|
provides [ main ] to pf
|
||||||
|
|
||||||
|
main : Str
|
||||||
|
main = Dep1.value1 {}
|
|
@ -137,6 +137,8 @@ pub fn build_zig_host_native(
|
||||||
|
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.args(&["-O", "ReleaseSafe"]);
|
command.args(&["-O", "ReleaseSafe"]);
|
||||||
|
} else if matches!(opt_level, OptLevel::Size) {
|
||||||
|
command.args(&["-O", "ReleaseSmall"]);
|
||||||
}
|
}
|
||||||
command.output().unwrap()
|
command.output().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -231,6 +233,8 @@ pub fn build_zig_host_native(
|
||||||
]);
|
]);
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.args(&["-O", "ReleaseSafe"]);
|
command.args(&["-O", "ReleaseSafe"]);
|
||||||
|
} else if matches!(opt_level, OptLevel::Size) {
|
||||||
|
command.args(&["-O", "ReleaseSmall"]);
|
||||||
}
|
}
|
||||||
command.output().unwrap()
|
command.output().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -282,6 +286,8 @@ pub fn build_zig_host_wasm32(
|
||||||
]);
|
]);
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.args(&["-O", "ReleaseSafe"]);
|
command.args(&["-O", "ReleaseSafe"]);
|
||||||
|
} else if matches!(opt_level, OptLevel::Size) {
|
||||||
|
command.args(&["-O", "ReleaseSmall"]);
|
||||||
}
|
}
|
||||||
command.output().unwrap()
|
command.output().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -317,7 +323,9 @@ pub fn build_c_host_native(
|
||||||
command.args(&["-fPIC", "-c"]);
|
command.args(&["-fPIC", "-c"]);
|
||||||
}
|
}
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.arg("-O2");
|
command.arg("-O3");
|
||||||
|
} else if matches!(opt_level, OptLevel::Size) {
|
||||||
|
command.arg("-Os");
|
||||||
}
|
}
|
||||||
command.output().unwrap()
|
command.output().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -351,6 +359,8 @@ pub fn build_swift_host_native(
|
||||||
|
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.arg("-O");
|
command.arg("-O");
|
||||||
|
} else if matches!(opt_level, OptLevel::Size) {
|
||||||
|
command.arg("-Osize");
|
||||||
}
|
}
|
||||||
|
|
||||||
command.output().unwrap()
|
command.output().unwrap()
|
||||||
|
@ -456,18 +466,18 @@ pub fn rebuild_host(
|
||||||
} else if cargo_host_src.exists() {
|
} else if cargo_host_src.exists() {
|
||||||
// Compile and link Cargo.toml, if it exists
|
// Compile and link Cargo.toml, if it exists
|
||||||
let cargo_dir = host_input_path.parent().unwrap();
|
let cargo_dir = host_input_path.parent().unwrap();
|
||||||
let cargo_out_dir =
|
let cargo_out_dir = cargo_dir.join("target").join(
|
||||||
cargo_dir
|
if matches!(opt_level, OptLevel::Optimize | OptLevel::Size) {
|
||||||
.join("target")
|
|
||||||
.join(if matches!(opt_level, OptLevel::Optimize) {
|
|
||||||
"release"
|
"release"
|
||||||
} else {
|
} else {
|
||||||
"debug"
|
"debug"
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let mut command = Command::new("cargo");
|
let mut command = Command::new("cargo");
|
||||||
command.arg("build").current_dir(cargo_dir);
|
command.arg("build").current_dir(cargo_dir);
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
// Rust doesn't expose size without editing the cargo.toml. Instead just use release.
|
||||||
|
if matches!(opt_level, OptLevel::Optimize | OptLevel::Size) {
|
||||||
command.arg("--release");
|
command.arg("--release");
|
||||||
}
|
}
|
||||||
let source_file = if shared_lib_path.is_some() {
|
let source_file = if shared_lib_path.is_some() {
|
||||||
|
@ -533,6 +543,8 @@ pub fn rebuild_host(
|
||||||
]);
|
]);
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.arg("-O");
|
command.arg("-O");
|
||||||
|
} else if matches!(opt_level, OptLevel::Size) {
|
||||||
|
command.arg("-C opt-level=s");
|
||||||
}
|
}
|
||||||
let output = command.output().unwrap();
|
let output = command.output().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ pub fn gen_from_mono_module(
|
||||||
emit_debug_info: bool,
|
emit_debug_info: bool,
|
||||||
) -> CodeGenTiming {
|
) -> CodeGenTiming {
|
||||||
match opt_level {
|
match opt_level {
|
||||||
OptLevel::Normal | OptLevel::Optimize => gen_from_mono_module_llvm(
|
OptLevel::Normal | OptLevel::Size | OptLevel::Optimize => gen_from_mono_module_llvm(
|
||||||
arena,
|
arena,
|
||||||
loaded,
|
loaded,
|
||||||
roc_file_path,
|
roc_file_path,
|
||||||
|
|
|
@ -114,6 +114,8 @@ pub fn target_machine(
|
||||||
pub fn convert_opt_level(level: OptLevel) -> OptimizationLevel {
|
pub fn convert_opt_level(level: OptLevel) -> OptimizationLevel {
|
||||||
match level {
|
match level {
|
||||||
OptLevel::Development | OptLevel::Normal => OptimizationLevel::None,
|
OptLevel::Development | OptLevel::Normal => OptimizationLevel::None,
|
||||||
|
// Default is O2/Os. If we want Oz, we have to explicitly turn of loop vectorization as well.
|
||||||
|
OptLevel::Size => OptimizationLevel::Default,
|
||||||
OptLevel::Optimize => OptimizationLevel::Aggressive,
|
OptLevel::Optimize => OptimizationLevel::Aggressive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -657,11 +657,20 @@ pub fn construct_optimization_passes<'a>(
|
||||||
OptLevel::Development | OptLevel::Normal => {
|
OptLevel::Development | OptLevel::Normal => {
|
||||||
pmb.set_optimization_level(OptimizationLevel::None);
|
pmb.set_optimization_level(OptimizationLevel::None);
|
||||||
}
|
}
|
||||||
|
OptLevel::Size => {
|
||||||
|
pmb.set_optimization_level(OptimizationLevel::Default);
|
||||||
|
// TODO: For some usecase, like embedded, it is useful to expose this and tune it.
|
||||||
|
pmb.set_inliner_with_threshold(50);
|
||||||
|
}
|
||||||
OptLevel::Optimize => {
|
OptLevel::Optimize => {
|
||||||
pmb.set_optimization_level(OptimizationLevel::Aggressive);
|
pmb.set_optimization_level(OptimizationLevel::Aggressive);
|
||||||
// this threshold seems to do what we want
|
// this threshold seems to do what we want
|
||||||
pmb.set_inliner_with_threshold(275);
|
pmb.set_inliner_with_threshold(275);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add optimization passes for Size and Optimize.
|
||||||
|
if matches!(opt_level, OptLevel::Size | OptLevel::Optimize) {
|
||||||
// TODO figure out which of these actually help
|
// TODO figure out which of these actually help
|
||||||
|
|
||||||
// function passes
|
// function passes
|
||||||
|
@ -684,7 +693,6 @@ pub fn construct_optimization_passes<'a>(
|
||||||
|
|
||||||
mpm.add_function_inlining_pass();
|
mpm.add_function_inlining_pass();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pmb.populate_module_pass_manager(&mpm);
|
pmb.populate_module_pass_manager(&mpm);
|
||||||
pmb.populate_function_pass_manager(&fpm);
|
pmb.populate_function_pass_manager(&fpm);
|
||||||
|
|
|
@ -245,7 +245,7 @@ where
|
||||||
|
|
||||||
match opt_level {
|
match opt_level {
|
||||||
OptLevel::Development | OptLevel::Normal => morphic_lib::solve_trivial(program),
|
OptLevel::Development | OptLevel::Normal => morphic_lib::solve_trivial(program),
|
||||||
OptLevel::Optimize => morphic_lib::solve(program),
|
OptLevel::Optimize | OptLevel::Size => morphic_lib::solve(program),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ macro_rules! return_on_layout_error_help {
|
||||||
pub enum OptLevel {
|
pub enum OptLevel {
|
||||||
Development,
|
Development,
|
||||||
Normal,
|
Normal,
|
||||||
|
Size,
|
||||||
Optimize,
|
Optimize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue