From 118633a35407f341a74379ff61728a66bd52f44f Mon Sep 17 00:00:00 2001 From: Alex Vergara Date: Sun, 30 Jun 2024 11:37:19 +0200 Subject: [PATCH] feat: No ReferenceCounted or Interior Mutability patterns are required anymore. Everything works again with plain references or moved values --- zork++/src/lib/cli/output/commands.rs | 72 ++++++++++----------------- zork++/src/lib/compiler/mod.rs | 33 ++++-------- zork++/src/lib/lib.rs | 57 ++++++--------------- 3 files changed, 50 insertions(+), 112 deletions(-) diff --git a/zork++/src/lib/cli/output/commands.rs b/zork++/src/lib/cli/output/commands.rs index feecaad1..b85c9cbe 100644 --- a/zork++/src/lib/cli/output/commands.rs +++ b/zork++/src/lib/cli/output/commands.rs @@ -1,11 +1,9 @@ //! Contains helpers and data structures to be processed in a nice and neat way the commands generated to be executed //! by Zork++ -use std::cell::RefCell; use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; -use std::rc::Rc; use std::slice::Iter; use std::{ path::{Path, PathBuf}, @@ -18,7 +16,7 @@ use crate::cache::EnvVars; use crate::cli::output::arguments::Arguments; use crate::compiler::data_factory::{CommonArgs, CompilerCommonArguments}; use crate::{ - cache::{self, ZorkCache}, + cache::ZorkCache, project_model::{compiler::CppCompiler, ZorkModel}, utils::constants, }; @@ -30,29 +28,32 @@ use serde::{Deserialize, Serialize}; pub fn run_generated_commands( program_data: &ZorkModel<'_>, - mut cache: ZorkCache<'_>, - test_mode: bool, + cache: &mut ZorkCache<'_>, ) -> Result { log::info!("Proceeding to execute the generated commands..."); - let commands = Rc::new(RefCell::new(cache.generated_commands.clone())); - let general_args = &cache.generated_commands.general_args.get_args(); + let env_args = cache.get_process_env_args().clone(); // TODO: this is yet better than clone the + // generated commands (maybe) but I'm not + // happy with it + for sys_module in &cache.generated_commands.system_modules { // TODO: will be deprecated soon, hopefully - execute_command(program_data, sys_module.1, cache.get_process_env_args())?; + // But while isn't deleted, we could normalize them into SourceCommandLine + execute_command(program_data, sys_module.1, &env_args)?; } { // Scopes for avoiding 'already borrow' errors on the different processes // TODO: better move it to a custom procedure - let mut commands_borrow = (*commands).borrow_mut(); - let translation_units = commands_borrow + let translation_units = cache + .generated_commands .get_all_command_lines() .filter(|scl| scl.need_to_build) .collect::>(); for translation_unit_cmd in translation_units { + // Join the concrete args of any translation unit with the general flyweights let translation_unit_cmd_args: Arguments = general_args .iter() .chain(translation_unit_cmd.args.iter()) @@ -61,19 +62,17 @@ pub fn run_generated_commands( let r = execute_command( program_data, &translation_unit_cmd_args, - cache.get_process_env_args(), + &env_args, ); - translation_unit_cmd.execution_result = CommandExecutionResult::from(&r); // TODO: we are modifying the cloned :( + translation_unit_cmd.execution_result = CommandExecutionResult::from(&r); if let Err(e) = r { - cache::save2(program_data, cache, test_mode)?; return Err(e); } else if !r.as_ref().unwrap().success() { let err = eyre!( "Ending the program, because the build of: {:?} failed", translation_unit_cmd.filename ); - cache::save2(program_data, cache, test_mode)?; return Err(err); } } @@ -85,53 +84,27 @@ pub fn run_generated_commands( let r = execute_command( program_data, &cache.generated_commands.linker.args, - cache.get_process_env_args(), + &env_args, ); - commands.borrow_mut().linker.execution_result = CommandExecutionResult::from(&r); + cache.generated_commands.linker.execution_result = CommandExecutionResult::from(&r); if let Err(e) = r { - cache::save2(program_data, cache, test_mode)?; + // cache::save2(program_data, cache, test_mode)?; return Err(e); } else if !r.as_ref().unwrap().success() { - cache::save2(program_data, cache, test_mode)?; + // cache::save2(program_data, cache, test_mode)?; return Err(eyre!( "Ending the program, because the linker command line execution failed", )); } } - let updated_commands = (*commands).borrow_mut().clone(); - cache.generated_commands = updated_commands; // TODO: we do really need another way of do this (we needed two clones) - cache::save2(program_data, cache, test_mode)?; + /* let updated_commands = (*commands).borrow_mut().clone(); + cache.generated_commands = updated_commands; // TODO: we do really need another way of do this (we needed two clones) */ + // cache::save2(program_data, cache, test_mode)?; Ok(CommandExecutionResult::Success) } -// fn execute_linker_command_line(program_data: &ZorkModel, -// // commands: &mut Commands, -// commands: Rc>, -// env_vars: &EnvVars) -> Result<()> { -// // if !commands.linker.args.is_empty() { -// log::debug!("Processing the linker command line..."); -// -// let r = execute_command( -// program_data, -// &commands.linker.args, -// env_vars, -// ); -// commands.linker.execution_result = CommandExecutionResult::from(&r); -// -// if let Err(e) = r { -// // cache::save(program_data, &mut cache, test_mode)?; -// return Err(e); -// } else if !r.as_ref().unwrap().success() { -// // cache::save(program_data, &mut cache, test_mode)?; -// return Err(eyre!( -// "Ending the program, because the linker command line execution failed", -// )); -// } else { Ok(()) } -// // } -// } - /// Executes a new [`std::process::Command`] to run the generated binary /// after the build process in the specified shell pub fn autorun_generated_binary( @@ -328,6 +301,11 @@ impl Commands { } } + /// Returns an [std::iter::Chain] (behind the opaque impl clause return type signature) + /// which points to all the generated commmands for the two variants of the compilers vendors C++ modular + /// standard libraries implementations (see: [crate::project_model::compiler::StdLibMode]) + /// joined to all the commands generated for every [TranslationUnit] declared by the user for + /// its project pub fn get_all_command_lines( &mut self, ) -> impl Iterator + Debug + '_ { diff --git a/zork++/src/lib/compiler/mod.rs b/zork++/src/lib/compiler/mod.rs index 822304e2..15d69a0c 100644 --- a/zork++/src/lib/compiler/mod.rs +++ b/zork++/src/lib/compiler/mod.rs @@ -26,11 +26,9 @@ use crate::{ use self::data_factory::{CommonArgs, CompilerCommonArguments}; -/// The entry point of the compilation process -/// -/// Whenever this process gets triggered, the files declared within the -/// configuration file will be build -pub fn build_project<'a>( +/// The core procedure. Generates the commands that will be sent to the compiler +/// for every translation unit declared by the user for its project +pub fn generate_commands<'a>( model: &'a ZorkModel<'a>, cache: &mut ZorkCache, tests: bool, @@ -40,16 +38,15 @@ pub fn build_project<'a>( let _compiler_specific_common_args: Box = data_factory::compiler_common_arguments_factory(model); // TODO: guard it with a presence check - // A registry of the generated command lines - // let commands = Commands::new(model, general_args, compiler_specific_common_args); - // TODO from cache, and find them here instead from the cache + cache.generated_commands.general_args = _general_args; + // cache. // TODO: add them to the commands DS, so they are together until they're generated // Build the std library as a module build_modular_stdlib(model, cache); // TODO: ward it with an if for only call this fn for the // 1st - Build the modules - if let Some(modules) = &model.modules { + if let Some(modules) = &model.modules { // TODO: re-think again this optional // Pre-tasks if model.compiler.cpp_compiler == CppCompiler::GCC && !modules.sys_modules.is_empty() { helpers::build_sys_modules(model, cache) @@ -57,9 +54,9 @@ pub fn build_project<'a>( process_modules(model, cache)?; }; - // 2nd - Build the non module sources + // 2nd - Generate the commands for the non-module sources build_sources(model, cache, tests)?; - // 3rd - Build the executable or the tests + // 3rd - Build the executable or the tests // TODO: commentary and fn name build_executable(model, cache, tests)?; Ok(()) @@ -116,21 +113,11 @@ fn build_sources(model: &ZorkModel<'_>, cache: &mut ZorkCache, tests: bool) -> R }; srcs.iter().for_each( - |src| { + |src| { // TODO: yet unchanged, we need to replicate the idea on main if !flag_source_file_without_changes(&model.compiler.cpp_compiler, cache, &src.file()) { sources::generate_sources_arguments(model, cache, &model.tests, src); } - }, // else { - // let command_line = SourceCommandLine::from_translation_unit( - // src, Arguments::default(), true, CommandExecutionResult::Cached, - // ); - // - // log::trace!("Source file: {:?} was not modified since the last iteration. No need to rebuilt it again.", &src.file()); - // cache.generated_commands.sources.push(command_line); - // cache.generated_commands.add_linker_file_path_owned(helpers::generate_obj_file_path( - // model.compiler.cpp_compiler, &model.build.output_dir, src, - // )) - // } + } ); Ok(()) diff --git a/zork++/src/lib/lib.rs b/zork++/src/lib/lib.rs index 836a965c..38c59cd8 100644 --- a/zork++/src/lib/lib.rs +++ b/zork++/src/lib/lib.rs @@ -24,7 +24,7 @@ pub mod worker { input::{CliArgs, Command}, output::commands::{self, CommandExecutionResult}, }, - compiler::build_project, + compiler::generate_commands, project_model::{compiler::CppCompiler, ZorkModel}, utils::{ self, @@ -109,30 +109,17 @@ pub mod worker { program_data: &'a ZorkModel<'_>, mut cache: ZorkCache, ) -> Result { - // TODO: the return type isn't as clever as it could be - match cli_args.command { - Command::Build => { - build_project(program_data, &mut cache, false) - .with_context(|| "Failed to build project")?; + let is_tests_run = cli_args.command.eq(&Command::Test); - commands::run_generated_commands( - program_data, - // commands, - cache, - false, - ) - } - Command::Run => { - build_project(program_data, &mut cache, false) - .with_context(|| "Failed to build project")?; + generate_commands(program_data, &mut cache, false) + .with_context(|| "Failed to generated the commands for the project")?; - match commands::run_generated_commands( - program_data, - // commands, - cache, - false, - ) { + let execution_result = match cli_args.command { + Command::Build => + commands::run_generated_commands( program_data, &mut cache,), + Command::Run | Command::Test => { + match commands::run_generated_commands( program_data, &mut cache,) { Ok(_) => commands::autorun_generated_binary( &program_data.compiler.cpp_compiler, &program_data.build.output_dir, @@ -140,31 +127,17 @@ pub mod worker { ), Err(e) => Err(e), } - } - Command::Test => { - build_project(program_data, &mut cache, true) - .with_context(|| "Failed to build project")?; - - match commands::run_generated_commands( - program_data, - // commands, - cache, - true, - ) { - Ok(_) => commands::autorun_generated_binary( - &program_data.compiler.cpp_compiler, - &program_data.build.output_dir, - &program_data.tests.test_executable_name, - ), - Err(e) => Err(e), - } - } + }, _ => todo!( "This branch should never be reached for now, as do not exists commands that may\ trigger them. The unique remaining, is ::New, that is already processed\ at the very beggining" ), - } + }; + + cache::save2(program_data, cache, is_tests_run)?; + + execution_result } /// Creates the directory for output the elements generated