Hide bootstrap boilerplate at entry point

I previously have experimented creating an entry point like:

#[tokio::main]
pub fn main() {
    initialize_rialight();
}

/// do not modify this function
fn initialize_rialight() {
    include!(concat!(env!("OUT_DIR"), "/rialight_entry.rs"));
}

Is there a way to simplify this main.rs? For example, eliminate the boilerplate and prevent user from breaking their main.rs.

The more ideal would be for the user to have this simple main.rs:

fn main() {
    // managed code
}

Then tokio::main and the include boilerplate happen elsewhere.

Note that my goal is to create a multi-media platform which is able to initialize new Cargo projects by itself.

// lib: bootstrap
#[macro_export]
macro_rules! bootstrap {
    () => {
        #[::tokio::main]
        async fn main() {
            $crate::initialize_rialight();
        }
    };
}

pub fn initialize_rialight() {
    //include!(concat!(env!("OUT_DIR"), "/rialight_entry.rs"));
}
// main.rs
bootstrap::bootstrap!();

Kinda, but is there a way to completely hide that bootstrap code from main.rs?

build.rs might help.

Yes, I've used it. It still won't resolve the issue of boilerplate included in main.rs

P.S.: I'm aiming to rewrite that repository.

I made a wrapper library as a learning project, how to clap and to make it easier for "me" to write programs, and not have to write a main(). Silly?

The library has some macros. All pretty much the same, but with some modifications allowing running the program multiple times, or mutability / ownership of the struct.

To write a program I code

  write_nomain_control!(program, Opt);

somewhere in the rs file.

The words "program" and "opt" are the function and function arg that will run. As the program.

fn program(opt: &mut Opt) -> Result<i32, nomain::return_code::ReturnCode>{
     println!("{:?}", opt);
     Ok(0)
 }

#[derive(clap::Parser, Debug)]
 #[clap(name = "program", about = "Do not write main.")]
 struct Opt {
     // Your struct can have normal clap derive objects
     /// If you want, you can give me some words.
     #[clap(name = "words")]
     words: Vec<String>,

     // The special nomain_controls item must exist in your struct
     // You MUST include the following two lines.
     #[clap(flatten)]
     nomain_controls: nomain::control::Controls,
 }

You could maybe do similar method? The writers of programs then can not mess up main().
They write a function.
They write a macro call to put the function in.

  yourmacro!(program)

The macro writes the main. My "nomain" macro calls clap and does other stuff. You could have your macro expand to

#[tokio::main]
pub fn main() {
    initialize_rialight();
    program();     
}

/// do not modify this function
fn initialize_rialight() {
    include!(concat!(env!("OUT_DIR"), "/rialight_entry.rs"));
}

No main is seen in the programs rs file code.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.