The Cargo tool can generate a new application or library project for you
with cargo new
. It's very basic: just src/main.rs
that prints
"Hello, world!", a TOML file and a .gitignore
file. By default you also
get a Git repository.
At the other end of the spectrum there is cargo-generate, which lets you create a project based on a Git repository. It's very configurable, but can be overkill in many cases.
People have suggested that a template
feature for Cargo would be nice,
but the response hasn't been too enthusiastic, maybe because cargo-generate
already exists.
In between these, I've found that I can get by with my own main.rs
and Cargo.toml
files, which I just copy over those generated by
the cargo new
.
It's manual labor and not configurable, but it saves me a lot of typing, because
I usually need the same crates and the same main program structure.
This is the main.rs
I currently use:
use std::env;
use std::io::Error;
fn run(args: &[String]) -> Result<(), &'static str> {
for (i, arg) in args.iter().enumerate() {
println!("{}: {}", i + 1, arg);
}
Ok(())
}
fn main() -> Result<(), Error> {
env_logger::init();
let args: Vec<String> = env::args().collect();
std::process::exit(match run(&args[1..]) {
Ok(_) => exitcode::OK,
Err(err) => {
eprintln!("error: {:?}", err);
exitcode::USAGE
}
});
}
I save this as main.rs
in a subdirectory called _template
in the directory where I keep my Rust projects. When I want to use it,
I just change to the directory of a newly created Rust project
and copy the file over:
cp ../_template/main.rs src/main.rs
This is what needs to be appended to the Cargo.toml
file's
[dependencies]
section to
be able to compile that (currently; as new versions appear
I will update it):
exitcode = "1.1.2" env_logger = "0.9.0" log = "0.4.14"
I save this as Cargo.toml
in ../_templates
and use the cat
command:
cat ../_template/Cargo.toml >>Cargo.toml
To get a README file in Markdown format I just generate a very simple file with the name of the project, picked up from the current directory:
echo "# $(basename $(pwd))" >>README.md
Finally, since any open source code I publish is usually under the MIT license, I drop a LICENSE file in:
cp ../_template/LICENSE .
All of this collected into a shell script:
#!/usr/bin/env bash
echo "Copying main.rs"
cp ../_template/main.rs src/main.rs
echo "Updating Cargo.toml"
cat ../_template/Cargo.toml >>Cargo.toml
echo "Creating README.md"
echo "# $(basename $(pwd))" >>README.md
echo "Copying LICENSE"
cp ../_template/LICENSE .
echo "Building"
cargo build
retval=$?
if [ $retval -eq 0 ]; then
echo "Committing changes"
git add .
git commit -m "Initial commit"
fi
exit $retval
I put this in the ../template
directory as init
and
make it executable. A new Cargo project is then created, initialized
and built like this:
cargo new flub; cd flub; ../_template/init
You should see something like this:
Created binary (application) `flub` package Copying main.rs Updating Cargo.toml Creating README.md Copying LICENSE Building Updating crates.io index Compiling memchr v2.4.1 Compiling libc v0.2.114 Compiling log v0.4.14 Compiling cfg-if v1.0.0 Compiling regex-syntax v0.6.25 Compiling humantime v2.1.0 Compiling termcolor v1.1.2 Compiling exitcode v1.1.2 Compiling aho-corasick v0.7.18 Compiling atty v0.2.14 Compiling regex v1.5.4 Compiling env_logger v0.9.0 Compiling flub v0.1.0 (/Users/me/Projects/Rust/flub) Finished dev [unoptimized + debuginfo] target(s) in 6.34s Committing changes [main (root-commit) 4016e01] Initial commit 6 files changed, 208 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/main.rs
When you run the program, it prints the command-line arguments:
% cargo run --quiet foo bar baz 1: foo 2: bar 3: baz
Hope you found this useful!