From 8bafbf3bebb8c1f474abdc5870c53df2f799f242 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 17:33:53 -0300 Subject: [PATCH 01/11] extracts .roc files from folders before formatting --- cli/src/format.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cli/src/format.rs b/cli/src/format.rs index fdc1d2bd6f..348f16bbd3 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -25,7 +25,45 @@ use roc_parse::{ }; use roc_region::all::{Loc, Region}; +fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { + files.into_iter().flat_map(|file| { + if file.is_dir() { + match file.read_dir() { + Ok(directory) => directory + .flat_map(|result| match result { + Ok(file) => { + let path = file.path(); + + if path.is_dir() { + flatten_folders(vec![path]) + } else if path.ends_with(".roc") { + vec![path] + } else { + vec![] + } + } + Err(error) => internal_error!( + "There was an error while trying to read a file from a folder: {:?}", + error + ), + }) + .collect(), + Err(error) => { + internal_error!( + "There was an error while trying to read the contents of a directory: {:?}", + error + ); + } + } + } else { + vec![file] + } + }).collect() +} + pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { + let files = flatten_folders(files); + for file in files { let arena = Bump::new(); From 797605cd72bd8f88f0eb043d6e7e71ad08a18c15 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 17:56:48 -0300 Subject: [PATCH 02/11] uses the word 'folder' consistently --- cli/src/format.rs | 51 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/cli/src/format.rs b/cli/src/format.rs index 348f16bbd3..98c31faaa0 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -26,39 +26,42 @@ use roc_parse::{ use roc_region::all::{Loc, Region}; fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { - files.into_iter().flat_map(|file| { - if file.is_dir() { - match file.read_dir() { - Ok(directory) => directory - .flat_map(|result| match result { - Ok(file) => { - let path = file.path(); + files + .into_iter() + .flat_map(|file| { + if file.is_dir() { + match file.read_dir() { + Ok(folder) => folder + .flat_map(|result| match result { + Ok(file) => { + let path = file.path(); - if path.is_dir() { - flatten_folders(vec![path]) - } else if path.ends_with(".roc") { - vec![path] - } else { - vec![] + if path.is_dir() { + flatten_folders(vec![path]) + } else if path.ends_with(".roc") { + vec![path] + } else { + vec![] + } } - } - Err(error) => internal_error!( + Err(error) => internal_error!( "There was an error while trying to read a file from a folder: {:?}", error ), - }) - .collect(), - Err(error) => { - internal_error!( - "There was an error while trying to read the contents of a directory: {:?}", + }) + .collect(), + Err(error) => { + internal_error!( + "There was an error while trying to read the contents of a folder: {:?}", error ); + } } + } else { + vec![file] } - } else { - vec![file] - } - }).collect() + }) + .collect() } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { From 9d487a4a95483ee6c53e0421b43ee1bec967b156 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 18:06:42 -0300 Subject: [PATCH 03/11] adds tests --- cli/tests/cli_run.rs | 8 +++++++- cli/tests/fixtures/format/formatted_folder/Formatted.roc | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 cli/tests/fixtures/format/formatted_folder/Formatted.roc diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 45a32eecd9..b29890cfff 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -13,7 +13,7 @@ extern crate indoc; mod cli_run { use cli_utils::helpers::{ example_file, examples_dir, extract_valgrind_errors, fixture_file, known_bad_file, run_cmd, - run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, + run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, fixtures_dir, }; use roc_test_utils::assert_multiline_str_eq; use serial_test::serial; @@ -884,6 +884,12 @@ mod cli_run { fn format_check_reformatting_needed() { check_format_check_as_expected(&fixture_file("format", "NotFormatted.roc"), false); } + + #[test] + fn format_check_folders() { + check_format_check_as_expected(&fixtures_dir("format"), false); + check_format_check_as_expected(&fixtures_dir("format/formatted_folder"), true); + } } #[allow(dead_code)] diff --git a/cli/tests/fixtures/format/formatted_folder/Formatted.roc b/cli/tests/fixtures/format/formatted_folder/Formatted.roc new file mode 100644 index 0000000000..b62c494e66 --- /dev/null +++ b/cli/tests/fixtures/format/formatted_folder/Formatted.roc @@ -0,0 +1,6 @@ +app "formatted" + packages { pf: "platform" } imports [] + provides [ main ] to pf + +main : Str +main = Dep1.value1 {} From 214d4e025b31457a9a0d16785db652710745164f Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 18:10:39 -0300 Subject: [PATCH 04/11] changes wording from 'folder' to 'directory' --- cli/src/format.rs | 12 ++++++------ cli/tests/cli_run.rs | 2 +- .../Formatted.roc | 0 3 files changed, 7 insertions(+), 7 deletions(-) rename cli/tests/fixtures/format/{formatted_folder => formatted_directory}/Formatted.roc (100%) diff --git a/cli/src/format.rs b/cli/src/format.rs index 98c31faaa0..f334c3ca69 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -25,19 +25,19 @@ use roc_parse::{ }; use roc_region::all::{Loc, Region}; -fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { +fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec { files .into_iter() .flat_map(|file| { if file.is_dir() { match file.read_dir() { - Ok(folder) => folder + Ok(directory) => directory .flat_map(|result| match result { Ok(file) => { let path = file.path(); if path.is_dir() { - flatten_folders(vec![path]) + flatten_directories(vec![path]) } else if path.ends_with(".roc") { vec![path] } else { @@ -45,14 +45,14 @@ fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { } } Err(error) => internal_error!( - "There was an error while trying to read a file from a folder: {:?}", + "There was an error while trying to read a file from a directory: {:?}", error ), }) .collect(), Err(error) => { internal_error!( - "There was an error while trying to read the contents of a folder: {:?}", + "There was an error while trying to read the contents of a directory: {:?}", error ); } @@ -65,7 +65,7 @@ fn flatten_folders(files: std::vec::Vec) -> std::vec::Vec { } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { - let files = flatten_folders(files); + let files = flatten_directories(files); for file in files { let arena = Bump::new(); diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index b29890cfff..2e6f21e020 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -888,7 +888,7 @@ mod cli_run { #[test] fn format_check_folders() { check_format_check_as_expected(&fixtures_dir("format"), false); - check_format_check_as_expected(&fixtures_dir("format/formatted_folder"), true); + check_format_check_as_expected(&fixtures_dir("format/formatted_directory"), true); } } diff --git a/cli/tests/fixtures/format/formatted_folder/Formatted.roc b/cli/tests/fixtures/format/formatted_directory/Formatted.roc similarity index 100% rename from cli/tests/fixtures/format/formatted_folder/Formatted.roc rename to cli/tests/fixtures/format/formatted_directory/Formatted.roc From 7f186249a1a7a83def1cd1cc911052b709e119c7 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 18:11:57 -0300 Subject: [PATCH 05/11] formats cli test file --- cli/tests/cli_run.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 2e6f21e020..3f3c507dfb 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -12,8 +12,8 @@ extern crate indoc; #[cfg(test)] mod cli_run { use cli_utils::helpers::{ - example_file, examples_dir, extract_valgrind_errors, fixture_file, known_bad_file, run_cmd, - run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, fixtures_dir, + example_file, examples_dir, extract_valgrind_errors, fixture_file, fixtures_dir, + known_bad_file, run_cmd, run_roc, run_with_valgrind, ValgrindError, ValgrindErrorXWhat, }; use roc_test_utils::assert_multiline_str_eq; use serial_test::serial; From c0709a91f3a5f5d2332e41b1d24a17b40b78d6ca Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 19:57:58 -0300 Subject: [PATCH 06/11] adds comments to format_check_folders test --- cli/tests/cli_run.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/tests/cli_run.rs b/cli/tests/cli_run.rs index 3f3c507dfb..ea5bd4f33d 100644 --- a/cli/tests/cli_run.rs +++ b/cli/tests/cli_run.rs @@ -887,7 +887,10 @@ mod cli_run { #[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); } } From 36dffc8c5f360f7477c34cd23e9935a297802e19 Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 19:58:20 -0300 Subject: [PATCH 07/11] changes implementation of folder flattening --- cli/src/format.rs | 53 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/cli/src/format.rs b/cli/src/format.rs index f334c3ca69..157254293f 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -26,42 +26,41 @@ use roc_parse::{ use roc_region::all::{Loc, Region}; fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec { - files - .into_iter() - .flat_map(|file| { - if file.is_dir() { - match file.read_dir() { - Ok(directory) => directory - .flat_map(|result| match result { - Ok(file) => { - let path = file.path(); + let mut to_flatten = files; + let mut files = vec![]; - if path.is_dir() { - flatten_directories(vec![path]) - } else if path.ends_with(".roc") { - vec![path] - } else { - 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 - ), - }) - .collect(), - Err(error) => { - internal_error!( - "There was an error while trying to read the contents of a directory: {:?}", - error - ); + ), + } } } - } else { - vec![file] + + Err(error) => internal_error!( + "There was an error while trying to read the contents of a directory: {:?}", + error + ), } - }) - .collect() + } else { + files.push(path) + } + } } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { From 98f3f1498492924d282ecb60315d35c904f468ec Mon Sep 17 00:00:00 2001 From: Celso Bonutti Date: Thu, 24 Feb 2022 20:00:29 -0300 Subject: [PATCH 08/11] fixes compiling error on directory flattening --- cli/src/format.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/src/format.rs b/cli/src/format.rs index 157254293f..9950ca2a62 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -61,6 +61,8 @@ fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec files.push(path) } } + + files } pub fn format(files: std::vec::Vec, mode: FormatMode) -> Result<(), String> { From 98eb359dade5061d8fbf0bba105d0553eb08699f Mon Sep 17 00:00:00 2001 From: celso Date: Thu, 24 Feb 2022 20:07:03 -0300 Subject: [PATCH 09/11] fixes identation on flatten_directories Co-authored-by: hafiz <20735482+ayazhafiz@users.noreply.github.com> --- cli/src/format.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/src/format.rs b/cli/src/format.rs index 9950ca2a62..5504cf8e6d 100644 --- a/cli/src/format.rs +++ b/cli/src/format.rs @@ -45,8 +45,8 @@ fn flatten_directories(files: std::vec::Vec) -> std::vec::Vec } Err(error) => internal_error!( - "There was an error while trying to read a file from a directory: {:?}", - error + "There was an error while trying to read a file from a directory: {:?}", + error ), } } From 69b4e78ac74efa58225a194f201a4a22d8998794 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Thu, 24 Feb 2022 15:39:50 -0800 Subject: [PATCH 10/11] Add --opt-size and compiling smaller binaries --- cli/src/lib.rs | 36 ++++++++++++++------ compiler/build/src/program.rs | 2 +- compiler/build/src/target.rs | 2 ++ compiler/gen_llvm/src/llvm/build.rs | 52 +++++++++++++++++------------ compiler/mono/src/alias_analysis.rs | 2 +- compiler/mono/src/ir.rs | 1 + 6 files changed, 61 insertions(+), 34 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index e3027927ea..b790552538 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -5,6 +5,7 @@ use build::{BuildOutcome, BuiltFile}; use bumpalo::Bump; use clap::{App, AppSettings, Arg, ArgMatches}; use roc_build::link::LinkType; +use roc_error_macros::user_error; use roc_load::file::LoadingProblem; use roc_mono::ir::OptLevel; use std::env; @@ -31,6 +32,7 @@ pub const CMD_FORMAT: &str = "format"; pub const FLAG_DEBUG: &str = "debug"; pub const FLAG_DEV: &str = "dev"; pub const FLAG_OPTIMIZE: &str = "optimize"; +pub const FLAG_OPT_SIZE: &str = "opt-size"; pub const FLAG_LIB: &str = "lib"; pub const FLAG_BACKEND: &str = "backend"; 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.)") .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::new(FLAG_DEV) .long(FLAG_DEV) @@ -166,12 +174,18 @@ pub fn build_app<'a>() -> App<'a> { .requires(ROC_FILE) .required(false), ) - .arg( - Arg::new(FLAG_DEV) - .long(FLAG_DEV) - .about("Make compilation as fast as possible. (Runtime performance may suffer)") - .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::new(FLAG_DEV) + .long(FLAG_DEV) + .about("Make compilation as fast as possible. (Runtime performance may suffer)") + .required(false), + ) .arg( Arg::new(FLAG_DEBUG) .long(FLAG_DEBUG) @@ -272,12 +286,14 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result { let original_cwd = std::env::current_dir()?; let opt_level = match ( matches.is_present(FLAG_OPTIMIZE), + matches.is_present(FLAG_OPT_SIZE), matches.is_present(FLAG_DEV), ) { - (true, false) => OptLevel::Optimize, - (true, true) => panic!("development cannot be optimized!"), - (false, true) => OptLevel::Development, - (false, false) => OptLevel::Normal, + (true, false, false) => OptLevel::Optimize, + (false, true, false) => OptLevel::Size, + (false, false, true) => OptLevel::Development, + (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_timings = matches.is_present(FLAG_TIME); diff --git a/compiler/build/src/program.rs b/compiler/build/src/program.rs index 933e8f9e7a..53b74ae8b1 100644 --- a/compiler/build/src/program.rs +++ b/compiler/build/src/program.rs @@ -199,7 +199,7 @@ pub fn gen_from_mono_module( emit_debug_info: bool, ) -> CodeGenTiming { match opt_level { - OptLevel::Normal | OptLevel::Optimize => gen_from_mono_module_llvm( + OptLevel::Normal | OptLevel::Size | OptLevel::Optimize => gen_from_mono_module_llvm( arena, loaded, roc_file_path, diff --git a/compiler/build/src/target.rs b/compiler/build/src/target.rs index 6064e58428..a49aff892b 100644 --- a/compiler/build/src/target.rs +++ b/compiler/build/src/target.rs @@ -114,6 +114,8 @@ pub fn target_machine( pub fn convert_opt_level(level: OptLevel) -> OptimizationLevel { match level { 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, } } diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index af42090989..7058b1c635 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -657,35 +657,43 @@ pub fn construct_optimization_passes<'a>( OptLevel::Development | OptLevel::Normal => { 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 => { pmb.set_optimization_level(OptimizationLevel::Aggressive); // this threshold seems to do what we want pmb.set_inliner_with_threshold(275); - - // TODO figure out which of these actually help - - // function passes - - fpm.add_cfg_simplification_pass(); - mpm.add_cfg_simplification_pass(); - - fpm.add_jump_threading_pass(); - mpm.add_jump_threading_pass(); - - fpm.add_memcpy_optimize_pass(); // this one is very important - - fpm.add_licm_pass(); - - // turn invoke into call - mpm.add_prune_eh_pass(); - - // remove unused global values (often the `_wrapper` can be removed) - mpm.add_global_dce_pass(); - - mpm.add_function_inlining_pass(); } } + // Add optimization passes for Size and Optimize. + if matches!(opt_level, OptLevel::Size | OptLevel::Optimize) { + // TODO figure out which of these actually help + + // function passes + + fpm.add_cfg_simplification_pass(); + mpm.add_cfg_simplification_pass(); + + fpm.add_jump_threading_pass(); + mpm.add_jump_threading_pass(); + + fpm.add_memcpy_optimize_pass(); // this one is very important + + fpm.add_licm_pass(); + + // turn invoke into call + mpm.add_prune_eh_pass(); + + // remove unused global values (often the `_wrapper` can be removed) + mpm.add_global_dce_pass(); + + mpm.add_function_inlining_pass(); + } + pmb.populate_module_pass_manager(&mpm); pmb.populate_function_pass_manager(&fpm); diff --git a/compiler/mono/src/alias_analysis.rs b/compiler/mono/src/alias_analysis.rs index 810e3c3595..f25e3e3b08 100644 --- a/compiler/mono/src/alias_analysis.rs +++ b/compiler/mono/src/alias_analysis.rs @@ -245,7 +245,7 @@ where match opt_level { OptLevel::Development | OptLevel::Normal => morphic_lib::solve_trivial(program), - OptLevel::Optimize => morphic_lib::solve(program), + OptLevel::Optimize | OptLevel::Size => morphic_lib::solve(program), } } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 300c4272ef..3aed213fd3 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -90,6 +90,7 @@ macro_rules! return_on_layout_error_help { pub enum OptLevel { Development, Normal, + Size, Optimize, } From ec411b7a62d609de21f65fed6492bd4302da5a3e Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Thu, 24 Feb 2022 16:21:12 -0800 Subject: [PATCH 11/11] Also build host for size when using --opt-size --- compiler/build/src/link.rs | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/compiler/build/src/link.rs b/compiler/build/src/link.rs index 21ea8da01a..27ef1cc7ca 100644 --- a/compiler/build/src/link.rs +++ b/compiler/build/src/link.rs @@ -137,6 +137,8 @@ pub fn build_zig_host_native( if matches!(opt_level, OptLevel::Optimize) { command.args(&["-O", "ReleaseSafe"]); + } else if matches!(opt_level, OptLevel::Size) { + command.args(&["-O", "ReleaseSmall"]); } command.output().unwrap() } @@ -231,6 +233,8 @@ pub fn build_zig_host_native( ]); if matches!(opt_level, OptLevel::Optimize) { command.args(&["-O", "ReleaseSafe"]); + } else if matches!(opt_level, OptLevel::Size) { + command.args(&["-O", "ReleaseSmall"]); } command.output().unwrap() } @@ -282,6 +286,8 @@ pub fn build_zig_host_wasm32( ]); if matches!(opt_level, OptLevel::Optimize) { command.args(&["-O", "ReleaseSafe"]); + } else if matches!(opt_level, OptLevel::Size) { + command.args(&["-O", "ReleaseSmall"]); } command.output().unwrap() } @@ -317,7 +323,9 @@ pub fn build_c_host_native( command.args(&["-fPIC", "-c"]); } 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() } @@ -351,6 +359,8 @@ pub fn build_swift_host_native( if matches!(opt_level, OptLevel::Optimize) { command.arg("-O"); + } else if matches!(opt_level, OptLevel::Size) { + command.arg("-Osize"); } command.output().unwrap() @@ -456,18 +466,18 @@ pub fn rebuild_host( } else if cargo_host_src.exists() { // Compile and link Cargo.toml, if it exists let cargo_dir = host_input_path.parent().unwrap(); - let cargo_out_dir = - cargo_dir - .join("target") - .join(if matches!(opt_level, OptLevel::Optimize) { - "release" - } else { - "debug" - }); + let cargo_out_dir = cargo_dir.join("target").join( + if matches!(opt_level, OptLevel::Optimize | OptLevel::Size) { + "release" + } else { + "debug" + }, + ); let mut command = Command::new("cargo"); 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"); } let source_file = if shared_lib_path.is_some() { @@ -533,6 +543,8 @@ pub fn rebuild_host( ]); if matches!(opt_level, OptLevel::Optimize) { command.arg("-O"); + } else if matches!(opt_level, OptLevel::Size) { + command.arg("-C opt-level=s"); } let output = command.output().unwrap();