Cargo does. With rustc
you sometimes have to be more explicit.
Well, you do though. For backwards compatibility reasons, the default edition is 2015, so if you don't specify an edition you'll be missing out on some features and writing unidiomatic (modern) Rust. This is like how gcc
will default to C90, a 30-some year old standard. And you care about building libraries or not, too. Let's walk through an example to see what I mean.
mkdir library
cd library
echo -e 'pub fn hi() {\n println!("Hello, world!");\n}' > lib.rs
rustc --edition=2021 lib.rs
The invocation fails with:
error[E0601]: `main` function not found in crate `lib`
--> lib.rs:1:1
|
1 | / pub fn hi() {
2 | | println!("Hello, world!");
3 | | }
| |_^ consider adding a `main` function to `lib.rs`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0601`.
And you need to do:
rustc --edition=2021 lib.rs --crate-type=lib
ls
lib.rs liblib.rlib
(It's liblib
because you didn't give it a crate name.)
Continuing on...
mkdir ../binary && cd ../binary
echo -e 'use library;\nfn main() {\n library::hi();\n}' > main.rs
rustc --edition=2021 main.rs
error[E0432]: unresolved import `library`
--> main.rs:1:5
|
1 | use library;
| ^^^^^^^ no external crate `library`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.
And so:
rustc --edition=2021 main.rs --extern library=../library/liblib.rlib
./main
Hello, world!
And now you have a binary. (It's not optimized.)
If I have to spend a number of hours learning "best practices" of Rust packaging before I can start seeing my code run [...] that'll dampen my enthusiasm.
As I think the above demonstrates, you'll have to learn something -- a few cargo commands, or the lower-level ways to use rustc
to build and link everything instead. As you said yourself, Cargo is a build system, not just a package manager.
Here's the same thing as above with Cargo:
# One project
cargo new project && cd project
echo -e 'pub fn hi() {\n println!("Hello, world!");\n}' > src/lib.rs
echo -e 'use project;\nfn main() {\n project::hi();\n}' > src/main.rs
cargo run
# Two projects
cargo new --lib library && cd library
echo -e 'pub fn hi() {\n println!("Hello, world!");\n}' > src/lib.rs
cd .. && cargo new binary && cd binary
echo -e 'use library;\nfn main() {\n library::hi();\n}' > src/main.rs
cargo add --path ../library/
# Or if you don't have `cargo add` because it's too new:
# echo 'library = { path = "../library" }' >> Cargo.toml
cargo run
Whichever way you want to go , hopefully there's enough here to get you started.